Module: Unicorn::HttpResponse
- Included in:
- HttpServer
- Defined in:
- lib/unicorn/http_response.rb
Overview
Writes a Rack response to your client using the HTTP/1.1 specification. You use it by simply doing:
status, headers, body = rack_app.call(env)
http_response_write(socket, [ status, headers, body ])
Most header correctness (including Content-Length and Content-Type) is the job of Rack, with the exception of the "Date" and "Status" header.
TODO: allow keepalive
Constant Summary collapse
- CODES =
Every standard HTTP code mapped to the appropriate message.
Rack::Utils::HTTP_STATUS_CODES.inject({}) { |hash,(code,msg)| hash[code] = "#{code} #{msg}" hash }
- CRLF =
"\r\n"
Instance Method Summary collapse
-
#http_response_write(socket, rack_response) ⇒ Object
writes the rack_response to socket as an HTTP response.
Instance Method Details
#http_response_write(socket, rack_response) ⇒ Object
writes the rack_response to socket as an HTTP response
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 |
# File 'lib/unicorn/http_response.rb', line 24 def http_response_write(socket, rack_response) status, headers, body = rack_response status = CODES[status.to_i] || status if headers buf = "HTTP/1.1 #{status}\r\n" \ "Date: #{Time.now.httpdate}\r\n" \ "Status: #{status}\r\n" \ "Connection: close\r\n" headers.each do |key, value| next if %r{\A(?:Date\z|Status\z|Connection\z)}i =~ key if value =~ /\n/ # avoiding blank, key-only cookies with /\n+/ buf << value.split(/\n+/).map! { |v| "#{key}: #{v}\r\n" }.join('') else buf << "#{key}: #{value}\r\n" end end socket.write(buf << CRLF) end body.each { |chunk| socket.write(chunk) } socket.close # flushes and uncorks the socket immediately ensure body.respond_to?(:close) and body.close end |