Skip to content

Commit

Permalink
RACK_URL_SCHEME calculation caring about more headers (#1491)
Browse files Browse the repository at this point in the history
* RACK_URL_SCHEME read the same as in Rack

* Code comment on HTTP_X_FORWARDED_PROTO

  - See rack/rack@85ca454

* Make default_server_port logic more readable

* Test: X-Forwarded-Proto and friends

* Calculate default_port respecting HTTP_X_FORWARDED_SCHEME, HTTP_X_FORWARDED_SSL

* Calculate URL scheme using #default_server_port

* Narrow down tests for default_server_port(env)
  • Loading branch information
olleolleolle authored and nateberkopec committed Jul 17, 2019
1 parent 4c85fac commit 30fbd84
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 7 deletions.
3 changes: 3 additions & 0 deletions lib/puma/const.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ module Const
LINE_END = "\r\n".freeze
REMOTE_ADDR = "REMOTE_ADDR".freeze
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL".freeze
HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME".freeze
HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO".freeze

SERVER_NAME = "SERVER_NAME".freeze
SERVER_PORT = "SERVER_PORT".freeze
Expand Down
9 changes: 6 additions & 3 deletions lib/puma/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -588,8 +588,11 @@ def normalize_env(env, client)
end

def default_server_port(env)
return PORT_443 if env[HTTPS_KEY] == 'on' || env[HTTPS_KEY] == 'https'
env['HTTP_X_FORWARDED_PROTO'] == 'https' ? PORT_443 : PORT_80
if ['on', HTTPS].include?(env[HTTPS_KEY]) || env[HTTP_X_FORWARDED_PROTO].to_s[0...5] == HTTPS || env[HTTP_X_FORWARDED_SCHEME] == HTTPS || env[HTTP_X_FORWARDED_SSL] == "on"
PORT_443
else
PORT_80
end
end

# Takes the request +req+, invokes the Rack application to construct
Expand Down Expand Up @@ -627,7 +630,7 @@ def handle_request(req, lines)
head = env[REQUEST_METHOD] == HEAD

env[RACK_INPUT] = body
env[RACK_URL_SCHEME] = env[HTTPS_KEY] ? HTTPS : HTTP
env[RACK_URL_SCHEME] = default_server_port(env) == PORT_443 ? HTTPS : HTTP

if @early_hints
env[EARLY_HINTS] = lambda { |headers|
Expand Down
32 changes: 28 additions & 4 deletions test/test_puma_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,30 @@ def test_very_large_return
end

def test_respect_x_forwarded_proto
env = {}
env['HOST'] = "example.com"
env['HTTP_X_FORWARDED_PROTO'] = "https,http"

assert_equal "443", @server.default_server_port(env)
end

def test_respect_x_forwarded_ssl_on
env = {}
env['HOST'] = "example.com"
env['HTTP_X_FORWARDED_SSL'] = "on"

assert_equal "443", @server.default_server_port(env)
end

def test_respect_x_forwarded_scheme
env = {}
env['HOST'] = "example.com"
env['HTTP_X_FORWARDED_SCHEME'] = "https"

assert_equal "443", @server.default_server_port(env)
end

def test_default_server_port
@server.app = proc do |env|
[200, {}, [env['SERVER_PORT']]]
end
Expand All @@ -104,16 +128,15 @@ def test_respect_x_forwarded_proto

req = Net::HTTP::Get.new("/")
req['HOST'] = "example.com"
req['X_FORWARDED_PROTO'] = "https"

res = Net::HTTP.start @host, @server.connected_port do |http|
http.request(req)
end

assert_equal "443", res.body
assert_equal "80", res.body
end

def test_default_server_port
def test_default_server_port_respects_x_forwarded_proto
@server.app = proc do |env|
[200, {}, [env['SERVER_PORT']]]
end
Expand All @@ -123,12 +146,13 @@ def test_default_server_port

req = Net::HTTP::Get.new("/")
req['HOST'] = "example.com"
req['X_FORWARDED_PROTO'] = "https,http"

res = Net::HTTP.start @host, @server.connected_port do |http|
http.request(req)
end

assert_equal "80", res.body
assert_equal "443", res.body
end

def test_HEAD_has_no_body
Expand Down

0 comments on commit 30fbd84

Please sign in to comment.