./lib/lux/response/response.rb in lux-fw-0.2.3 vs ./lib/lux/response/response.rb in lux-fw-0.5.32
- old
+ new
@@ -5,13 +5,12 @@
class Lux::Response
# define in seconds, how long should page be accessible in client cache
# if defined, cache becomes public and can be cache by proxies
# use with care.only for static resources and
attr_reader :max_age
+ attr_accessor :headers, :cookies, :content_type, :status
- attr_accessor :body, :headers, :cookies, :content_type, :status, :cookie_multidomain, :cookie_domain
-
def initialize
@render_start = Time.monotonic
@headers = Lux::Response::Header.new
@max_age = 0
end
@@ -27,26 +26,30 @@
def max_age= age
@max_age = age.to_i
end
+ # http 103
+ def early_hints link=nil, type=nil
+ @early_hints ||= []
+ @early_hints.push [link, type] if type && !@early_hints.include?(link)
+ @early_hints
+ end
+
def etag *args
unless @headers['etag']
args.push current.request.url
key = '"%s"' % Lux.cache.generate_key(args)
key = 'W/%s' % key unless max_age > 0
@headers['etag'] = key
end
- if current.request.env['HTTP_IF_NONE_MATCH'] == @headers['etag']
- @status = 304
- @body = 'not-modified'
- true
- else
- false
+ if !@body && current.request.env['HTTP_IF_NONE_MATCH'] == @headers['etag']
+ status 304
+ body 'not-modified'
end
end
def status num=nil
return @status unless num
@@ -62,38 +65,35 @@
@body = msg if msg
throw :done
end
- def body what=nil
- @body ||= what
-
- if @body && block_given?
- @body = yield @body
- Lux.error 'Lux.current.response.body is not a string (bad current.response.body filter)' unless @body.is_a?(String)
- end
-
+ def body body_data=nil, status=nil
+ @status = status if status
+ @body = body_data if body_data
+ @body = yield @body if block_given?
@body
end
- alias :body= :body
- def body! what
- @body = what
+ def body?
+ !!@body
end
def content_type type=nil
return @content_type unless type
- # can be set only once
- return @content_type if @content_type
+ if type.is_a?(Symbol)
+ case type
+ when :javascript then 'application/javascript'
+ when :json then 'application/json'
+ when :text then 'text/plain'
+ when :html then 'text/html'
+ else
+ raise ArgumentError.new('Bad content type')
+ end
+ end
- type = 'application/json' if type == :json
- type = 'text/plain' if type == :text
- type = 'text/html' if type == :html
-
- raise 'Invalid page content-type %s' % type if type === Symbol
-
@content_type = type
end
def content_type= type
content_type type
@@ -103,21 +103,45 @@
@flash ||= Flash.new current.session[:lux_flash]
message ? @flash.error(message) : @flash
end
- def redirect where=nil, opts={}
- return @headers['location'] unless where
+ def send_file file, opts={}
+ ::Lux::Response::File.new(file, opts).send
+ end
+ # redirect '/foo'
+ # redirect :back, info: 'bar ...'
+ def redirect where, opts={}
+ where = current.request.env['HTTP_REFERER'].or('/') if where == :back
+ where = "#{current.request.path}#{where}" if where[0,1] == '?'
+ where = current.host + where unless where.include?('://')
+
+ # local redirect
+ if where.include?(current.host)
+ redirect_var = Lux.config.redirect_var || :_r
+
+ url = Url.new where
+ url[redirect_var] = current.request.params[redirect_var].to_i + 1
+
+ where =
+ if opts.delete(:silent)
+ url.delete redirect_var
+ url.to_s
+ else
+ url[redirect_var] > 3 ? '/' : url.to_s
+ end
+ end
+
@status = opts.delete(:status) || 302
opts.map { |k,v| flash.send(k, v) }
- @headers['location'] = where.index('//') ? where : "#{current.host}#{where}"
+ @body = %[redirecting to #{where}\n\n#{opts.values.join("\n")}]
+
+ @headers['location'] = where
@headers['access-control-expose-headers'] ||= 'Location'
- @body = %[redirecting to #{@headers['location']}\n\n#{opts.values.join("\n")}]
-
throw :done
end
def permanent_redirect where
redirect where, status:301
@@ -130,19 +154,18 @@
return true if yield *credentials
end
status 401
header('WWW-Authenticate', 'Basic realm="%s"' % relam.or('default'))
- body = ErrorCell.unauthorized('HTTP 401 Authorization needed')
-
- false
+ body 'HTTP 401 Authorization needed'
+ throw :done
end
def write_response_body
unless @body
- @status = 404
- @body = Lux.error 'Document not found'
+ @status = 204
+ @body = 'Lux HTTP ERROR 204: NO CONTENT'
end
# respond as JSON if we recive hash
if @body.kind_of?(Hash)
@body = Lux.dev? ? JSON.pretty_generate(@body) : JSON.generate(@body)
@@ -162,17 +185,10 @@
@content_type ||= 'text/html'
end
end
def write_response_header
- domain =
- if cookie_multidomain && current.domain.index('.')
- ".#{current.domain}"
- else
- cookie_domain || current.request.host
- end
-
# cache-control
@headers['cache-control'] ||= Proc.new do
cc = ['max-age=%d' % max_age]
cc.push max_age > 0 ? 'public, no-cache' : 'private, must-revalidate'
cc.join(', ')
@@ -180,36 +196,28 @@
current.session[:lux_flash] = flash.to_h
# dont annd cookies to public pages (images, etc..)
unless @headers['cache-control'].index('public')
- encrypted = Crypt.encrypt(current.session.to_json)
-
- if current.cookies[Lux.config.session_cookie_name] != encrypted
- @headers['set-cookie'] = "#{Lux.config.session_cookie_name}=#{encrypted}; Expires=#{(Time.now+1.month).utc}; Path=/; Domain=#{domain};"
- end
+ cookie = current.session.generate_cookie
+ @headers['set-cookie'] = cookie if cookie
end
etag(@body) if current.request.request_method == 'GET'
@headers['x-lux-speed'] = "#{((Time.monotonic - @render_start)*1000).round(1)} ms"
@headers['content-type'] ||= "#{@content_type}; charset=utf-8"
- @headers['content-length'] = @body.bytesize
+ @headers['content-length'] = @body.bytesize.to_s
+
# if "no-store" is present then HTTP_IF_NONE_MATCH is not sent from browser
end
def render
write_response_body
write_response_header
@status ||= 200
Lux.log " #{@status}, #{@headers['x-lux-speed']}"
-
- if ENV['LUX_PRINT_ROUTES']
- print '* Finished route print '
- puts @status == 404 ? 'without a match'.red : 'with a match'.green
- exit
- end
[@status, @headers.to_h, [@body]]
end
end