diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/http/response.rb')
-rw-r--r-- | actionpack/lib/action_dispatch/http/response.rb | 81 |
1 files changed, 43 insertions, 38 deletions
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index a895d1ab18..4aee489912 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -40,10 +40,9 @@ module ActionDispatch # :nodoc: attr_writer :sending_file - # Get and set headers for this response. - attr_accessor :header + # Get headers for this response. + attr_reader :header - alias_method :headers=, :header= alias_method :headers, :header delegate :[], :[]=, :to => :@header @@ -61,12 +60,12 @@ module ActionDispatch # :nodoc: # The charset of the response. HTML wants to know the encoding of the # content you're giving them, so we need to send that along. - attr_accessor :charset + attr_reader :charset CONTENT_TYPE = "Content-Type".freeze SET_COOKIE = "Set-Cookie".freeze LOCATION = "Location".freeze - NO_CONTENT_CODES = [204, 304] + NO_CONTENT_CODES = [100, 101, 102, 204, 205, 304] cattr_accessor(:default_charset) { "utf-8" } cattr_accessor(:default_headers) @@ -81,11 +80,21 @@ module ActionDispatch # :nodoc: @response = response @buf = buf @closed = false + @str_body = nil + end + + def body + @str_body ||= begin + buf = '' + each { |chunk| buf << chunk } + buf + end end def write(string) raise IOError, "closed stream" if closed? + @str_body = nil @response.commit! @buf.push string end @@ -117,8 +126,9 @@ module ActionDispatch # :nodoc: super() header = merge_default_headers(header, default_headers) + @header = header - self.body, self.header, self.status = body, header, status + self.body, self.status = body, status @sending_file = false @blank = false @@ -127,7 +137,7 @@ module ActionDispatch # :nodoc: @sending = false @sent = false @content_type = nil - @charset = nil + @charset = self.class.default_charset if content_type = self[CONTENT_TYPE] type, charset = content_type.split(/;\s*charset=/) @@ -140,6 +150,11 @@ module ActionDispatch # :nodoc: yield self if block_given? end + def have_header?(key); headers.key? key; end + def get_header(key); headers[key]; end + def set_header(key, v); headers[key] = v; end + def delete_header(key); headers.delete key; end + def await_commit synchronize do @cv.wait_until { @committed } @@ -187,6 +202,15 @@ module ActionDispatch # :nodoc: @content_type = content_type.to_s end + # Sets the HTTP character set. In case of nil parameter + # it sets the charset to utf-8. + # + # response.charset = 'utf-16' # => 'utf-16' + # response.charset = nil # => 'utf-8' + def charset=(charset) + @charset = charset.nil? ? self.class.default_charset : charset + end + # The response code of the request. def response_code @status @@ -213,9 +237,7 @@ module ActionDispatch # :nodoc: # Returns the content of the response as a string. This contains the contents # of any calls to <tt>render</tt>. def body - strings = [] - each { |part| strings << part.to_s } - strings.join + @stream.body end EMPTY = " " @@ -239,25 +261,9 @@ module ActionDispatch # :nodoc: parts end - def set_cookie(key, value) - ::Rack::Utils.set_cookie_header!(header, key, value) - end - - def delete_cookie(key, value={}) - ::Rack::Utils.delete_cookie_header!(header, key, value) - end - # The location header we'll be responding with. - def location - headers[LOCATION] - end alias_method :redirect_url, :location - # Sets the location header we'll be responding with. - def location=(url) - headers[LOCATION] = url - end - def close stream.close if stream.respond_to?(:close) end @@ -274,10 +280,11 @@ module ActionDispatch # :nodoc: end # Turns the Response into a Rack-compatible array of the status, headers, - # and body. Allows explict splatting: + # and body. Allows explicit splatting: # # status, headers, body = *response def to_a + commit! rack_response @status, @header.to_hash end alias prepare! to_a @@ -287,7 +294,7 @@ module ActionDispatch # :nodoc: # assert_equal 'AuthorOfNewPage', r.cookies['author'] def cookies cookies = {} - if header = self[SET_COOKIE] + if header = get_header(SET_COOKIE) header = header.split("\n") if header.respond_to?(:to_str) header.each do |cookie| if pair = cookie.split(';').first @@ -302,6 +309,9 @@ module ActionDispatch # :nodoc: private def before_committed + return if committed? + assign_default_content_type_and_charset! + handle_conditional_get! end def before_sending @@ -319,16 +329,15 @@ module ActionDispatch # :nodoc: body.respond_to?(:each) ? body : [body] end - def assign_default_content_type_and_charset!(headers) - return if headers[CONTENT_TYPE].present? + def assign_default_content_type_and_charset! + return if get_header(CONTENT_TYPE).present? @content_type ||= Mime::HTML - @charset ||= self.class.default_charset unless @charset == false type = @content_type.to_s.dup - type << "; charset=#{@charset}" if append_charset? + type << "; charset=#{charset}" if append_charset? - headers[CONTENT_TYPE] = type + set_header CONTENT_TYPE, type end def append_charset? @@ -372,13 +381,9 @@ module ActionDispatch # :nodoc: end def rack_response(status, header) - assign_default_content_type_and_charset!(header) - handle_conditional_get! - - header[SET_COOKIE] = header[SET_COOKIE].join("\n") if header[SET_COOKIE].respond_to?(:join) - if NO_CONTENT_CODES.include?(@status) header.delete CONTENT_TYPE + header.delete 'Content-Length' [status, header, []] else [status, header, RackBody.new(self)] |