Class: Rainbows::DevFdResponse
- Inherits:
-
Struct
- Object
- Struct
- Rainbows::DevFdResponse
- Includes:
- Rack::Utils
- Defined in:
- lib/rainbows/dev_fd_response.rb
Overview
Rack response middleware wrapping any IO-like object with an OS-level file descriptor associated with it. May also be used to create responses from integer file descriptors or existing IO
objects. This may be used in conjunction with the #to_path method on servers that support it to pass arbitrary file descriptors into the HTTP response without additional open(2) syscalls
Defined Under Namespace
Classes: Body
Constant Summary collapse
- FD_MAP =
:stopdoc:
Rainbows::FD_MAP
Instance Attribute Summary collapse
-
#app ⇒ Object
Returns the value of attribute app.
Instance Method Summary collapse
-
#call(env) ⇒ Object
Rack middleware entry point, we’ll just pass through responses unless they respond to
to_io
orto_path
.
Instance Attribute Details
#app ⇒ Object
Returns the value of attribute app
10 11 12 |
# File 'lib/rainbows/dev_fd_response.rb', line 10 def app @app end |
Instance Method Details
#call(env) ⇒ Object
Rack middleware entry point, we’ll just pass through responses unless they respond to to_io
or to_path
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/rainbows/dev_fd_response.rb', line 18 def call(env) status, headers, body = response = app.call(env) # totally uninteresting to us if there's no body if STATUS_WITH_NO_ENTITY_BODY.include?(status.to_i) || File === body || (body.respond_to?(:to_path) && File.file?(body.to_path)) return response end io = body.to_io if body.respond_to?(:to_io) io ||= File.open(body.to_path) if body.respond_to?(:to_path) return response if io.nil? headers = Rack::Utils::HeaderHash.new(headers) unless Hash === headers st = io.stat fileno = io.fileno FD_MAP[fileno] = io if st.file? headers['Content-Length'.freeze] ||= st.size.to_s headers.delete('Transfer-Encoding'.freeze) elsif st.pipe? || st.socket? # epoll-able things unless headers.include?('Content-Length'.freeze) if env['rainbows.autochunk'] case env['HTTP_VERSION'] when "HTTP/1.0", nil else headers['Transfer-Encoding'.freeze] = 'chunked' end else env['rainbows.autochunk'] = false end end # we need to make sure our pipe output is Fiber-compatible case env['rainbows.model'] when :FiberSpawn, :FiberPool, :RevFiberSpawn, :CoolioFiberSpawn io.respond_to?(:kgio_wait_readable) or io = Rainbows::Fiber::IO.new(io) when :Revactor io = Rainbows::Revactor::Proxy.new(io) end else # unlikely, char/block device file, directory, ... return response end [ status, headers, Body.new(io, "/dev/fd/#{fileno}", body) ] end |