diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/http/response.rb')
-rw-r--r-- | actionpack/lib/action_dispatch/http/response.rb | 106 |
1 files changed, 88 insertions, 18 deletions
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 2c6bcf7b7b..4061ea71a3 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -91,7 +91,13 @@ module ActionDispatch # :nodoc: end def each(&block) - @buf.each(&block) + @response.sending! + x = @buf.each(&block) + @response.sent! + x + end + + def abort end def close @@ -118,6 +124,8 @@ module ActionDispatch # :nodoc: @blank = false @cv = new_cond @committed = false + @sending = false + @sent = false @content_type = nil @charset = nil @@ -138,17 +146,37 @@ module ActionDispatch # :nodoc: end end + def await_sent + synchronize { @cv.wait_until { @sent } } + end + def commit! synchronize do + before_committed @committed = true @cv.broadcast end end - def committed? - @committed + def sending! + synchronize do + before_sending + @sending = true + @cv.broadcast + end + end + + def sent! + synchronize do + @sent = true + @cv.broadcast + end end + def sending?; synchronize { @sending }; end + def committed?; synchronize { @committed }; end + def sent?; synchronize { @sent }; end + # Sets the HTTP status code. def status=(status) @status = Rack::Utils.status_code(status) @@ -182,18 +210,6 @@ module ActionDispatch # :nodoc: end alias_method :status_message, :message - def respond_to?(method, include_private = false) - if method.to_s == 'to_path' - stream.respond_to?(method) - else - super - end - end - - def to_path - stream.to_path - end - # Returns the content of the response as a string. This contains the contents # of any calls to <tt>render</tt>. def body @@ -246,13 +262,25 @@ module ActionDispatch # :nodoc: stream.close if stream.respond_to?(:close) end + def abort + if stream.respond_to?(:abort) + stream.abort + elsif stream.respond_to?(:close) + # `stream.close` should really be reserved for a close from the + # other direction, but we must fall back to it for + # compatibility. + stream.close + end + end + # Turns the Response into a Rack-compatible array of the status, headers, - # and body. + # and body. Allows explict splatting: + # + # status, headers, body = *response def to_a rack_response @status, @header.to_hash end alias prepare! to_a - alias to_ary to_a # Returns the response cookies, converted to a Hash of (name => value) pairs # @@ -273,6 +301,12 @@ module ActionDispatch # :nodoc: private + def before_committed + end + + def before_sending + end + def merge_default_headers(original, default) return original unless default.respond_to?(:merge) @@ -303,6 +337,42 @@ module ActionDispatch # :nodoc: !@sending_file && @charset != false end + class RackBody + def initialize(response) + @response = response + end + + def each(*args, &block) + @response.each(*args, &block) + end + + def close + # Rack "close" maps to Response#abort, and *not* Response#close + # (which is used when the controller's finished writing) + @response.abort + end + + def body + @response.body + end + + def respond_to?(method, include_private = false) + if method.to_s == 'to_path' + @response.stream.respond_to?(method) + else + super + end + end + + def to_path + @response.stream.to_path + end + + def to_ary + nil + end + end + def rack_response(status, header) assign_default_content_type_and_charset!(header) handle_conditional_get! @@ -313,7 +383,7 @@ module ActionDispatch # :nodoc: header.delete CONTENT_TYPE [status, header, []] else - [status, header, Rack::BodyProxy.new(self){}] + [status, header, RackBody.new(self)] end end end |