Class: LongBody
- Inherits:
-
Object
- Object
- LongBody
- Defined in:
- lib/long_body.rb,
lib/long_body/version.rb
Overview
The base middleware class to use in your Rack application, Sinatra, Rails etc.
use LongBody
Note that if you want to use Rack::Chunked (and you most likely do) you have to insert it below LongBody:
use LongBody
use Rack::Chunked
Defined Under Namespace
Modules: HijackHandler, ThinHandler Classes: DeferrableBody, MisconfiguredBody
Constant Summary collapse
- STREAMABLE_CODES =
[200, 206]
- C_rack_logger =
'rack.logger'.freeze
- HIJACK_SUPPORTED =
'rack.hijack?'.freeze
- ASYNC_SUPPORT =
'async.callback'.freeze
- VERSION =
'0.0.2'
Instance Method Summary collapse
- #call(env) ⇒ Object
- #ensure_chunked_or_content_length!(header_hash) ⇒ Object
-
#initialize(app) ⇒ LongBody
constructor
A new instance of LongBody.
- #status_might_have_streamable_body?(status_code) ⇒ Boolean
Constructor Details
#initialize(app) ⇒ LongBody
Returns a new instance of LongBody.
37 38 39 |
# File 'lib/long_body.rb', line 37 def initialize(app) @app = app end |
Instance Method Details
#call(env) ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/long_body.rb', line 45 def call(env) # Call the upstream first s, h, b = @app.call(env) # Return as-is if the long body skip is requested return [s, h,b] if h.delete('X-Rack-Long-Body-Skip') # If the response has nothing to do with the streaming response, just # let it go through as it is not big enough to bother. Also if there is no hijack # support there is no sense to bother at all. return [s, h, b] unless status_might_have_streamable_body?(s) # If the body is nil or is not each-able, return the original response - there probably is some other # async trickery going on downstream from us, and we should not intercept this response. return [s, h, b] if (b.nil? || !b.respond_to?(:each) || (b.respond_to?(:empty?) && b.empty?)) # Ensure either Content-Length or chunking is in place ensure_chunked_or_content_length!(h) # TODO: ensure not already hijacked if env[ASYNC_SUPPORT] env[C_rack_logger].info("Streaming via async.callback (Thin)") if env[C_rack_logger].respond_to?(:info) ThinHandler.perform(env, s, h, b) elsif env[HIJACK_SUPPORTED] env[C_rack_logger].info("Streaming via hijack and IO.select") if env[C_rack_logger].respond_to?(:info) HijackHandler.perform(env, s, h, b) else [s, h, b] # No recourse end end |
#ensure_chunked_or_content_length!(header_hash) ⇒ Object
31 32 33 34 35 |
# File 'lib/long_body.rb', line 31 def ensure_chunked_or_content_length!(header_hash) unless header_hash['Transfer-Encoding'] == 'chunked' || header_hash['Content-Length'] raise MisconfiguredBody end end |
#status_might_have_streamable_body?(status_code) ⇒ Boolean
27 28 29 |
# File 'lib/long_body.rb', line 27 def status_might_have_streamable_body?(status_code) STREAMABLE_CODES.include?(status_code.to_i) end |