diff --git a/lib/puma/const.rb b/lib/puma/const.rb index ef3fb73c..e7599b0d 100644 --- a/lib/puma/const.rb +++ b/lib/puma/const.rb @@ -121,6 +121,7 @@ module Puma SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze HTTP_11 = "HTTP/1.1".freeze + HTTP_10 = "HTTP/1.0".freeze SERVER_SOFTWARE = "SERVER_SOFTWARE".freeze GATEWAY_INTERFACE = "GATEWAY_INTERFACE".freeze @@ -128,5 +129,36 @@ module Puma STOP_COMMAND = "!".freeze + RACK_INPUT = "rack.input".freeze + RACK_URL_SCHEME = "rack.url_scheme".freeze + RACK_AFTER_REPLY = "rack.after_reply".freeze + + HTTP = "http".freeze + HTTPS = "https".freeze + + HTTPS_KEY = "HTTPS".freeze + + HTTP_VERSION = "HTTP_VERSION".freeze + HTTP_CONNECTION = "HTTP_CONNECTION".freeze + + HTTP_11_200 = "HTTP/1.1 200 OK\r\n".freeze + HTTP_10_200 = "HTTP/1.0 200 OK\r\n".freeze + + CLOSE = "close".freeze + KEEP_ALIVE = "Keep-Alive".freeze + + CONTENT_LENGTH2 = "Content-Length".freeze + CONTENT_LENGTH_S = "Content-Length: ".freeze + TRANSFER_ENCODING = "Transfer-Encoding".freeze + + CONNECTION_CLOSE = "Connection: close\r\n".freeze + CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n".freeze + + TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n".freeze + CLOSE_CHUNKED = "0\r\n\r\n".freeze + + COLON = ": ".freeze + + NEWLINE = "\n".freeze end end diff --git a/lib/puma/server.rb b/lib/puma/server.rb index 1d6578f7..ffb83258 100644 --- a/lib/puma/server.rb +++ b/lib/puma/server.rb @@ -262,25 +262,10 @@ module Puma body = StringIO.new(EmptyBinary) end - env["rack.input"] = body - env["rack.url_scheme"] = env["HTTPS"] ? "https" : "http" + env[RACK_INPUT] = body + env[RACK_URL_SCHEME] = env[HTTPS_KEY] ? HTTPS : HTTP - allow_chunked = false - - if env['HTTP_VERSION'] == 'HTTP/1.1' - allow_chunked = true - http_version = "HTTP/1.1 " - keep_alive = env["HTTP_CONNECTION"] != "close" - include_keepalive_header = false - else - http_version = "HTTP/1.0 " - keep_alive = env["HTTP_CONNECTION"] == "Keep-Alive" - include_keepalive_header = keep_alive - end - - chunked = false - - after_reply = env['rack.after_reply'] = [] + after_reply = env[RACK_AFTER_REPLY] = [] begin begin @@ -297,26 +282,50 @@ module Puma cork_socket client - client.write http_version - client.write status.to_s - client.write " " - client.write HTTP_STATUS_CODES[status] - client.write "\r\n" + if env[HTTP_VERSION] == HTTP_11 + allow_chunked = true + keep_alive = env[HTTP_CONNECTION] != CLOSE + include_keepalive_header = false - colon = ": " - line_ending = "\r\n" + if status == 200 + client.write HTTP_11_200 + else + client.write "HTTP/1.1 " + client.write status.to_s + client.write " " + client.write HTTP_STATUS_CODES[status] + client.write "\r\n" + end + else + allow_chunked = false + keep_alive = env[HTTP_CONNECTION] == KEEP_ALIVE + include_keepalive_header = keep_alive + + if status == 200 + client.write HTTP_10_200 + else + client.write "HTTP/1.1 " + client.write status.to_s + client.write " " + client.write HTTP_STATUS_CODES[status] + client.write "\r\n" + end + end + + colon = COLON + line_ending = LINE_END headers.each do |k, vs| case k - when "Content-Length" + when CONTENT_LENGTH2 content_length = vs next - when "Transfer-Encoding" + when TRANSFER_ENCODING allow_chunked = false content_length = nil end - vs.split("\n").each do |v| + vs.split(NEWLINE).each do |v| client.write k client.write colon client.write v @@ -325,15 +334,18 @@ module Puma end if include_keepalive_header - client.write "Connection: Keep-Alive\r\n" + client.write CONNECTION_KEEP_ALIVE elsif !keep_alive - client.write "Connection: close\r\n" + client.write CONNECTION_CLOSE end if content_length - client.write "Content-Length: #{content_length}\r\n" + client.write CONTENT_LENGTH_S + client.write content_length.to_s + client.write line_ending + chunked = false elsif allow_chunked - client.write "Transfer-Encoding: chunked\r\n" + client.write TRANSFER_ENCODING_CHUNKED chunked = true end @@ -353,9 +365,7 @@ module Puma end if chunked - client.write "0" - client.write line_ending - client.write line_ending + client.write CLOSE_CHUNKED client.flush end