-
Notifications
You must be signed in to change notification settings - Fork 222
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Middleware for handling vendor-specific
$vendor-forwarded-proto
-> …
…`x-forwarded-proto`.
- Loading branch information
Showing
3 changed files
with
76 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# frozen_string_literal: true | ||
|
||
module Rack | ||
# Middleware to set the X-Forwarded-Proto header to the value | ||
# of another header. | ||
# | ||
# This header can be used to ensure the scheme matches when comparing | ||
# request.origin and request.base_url for CSRF checking, but Rack | ||
# expects that value to be in the X_FORWARDED_PROTO header. | ||
# | ||
# Example Rails usage: | ||
# If you use a vendor managed proxy or CDN which sends the proto in a header add | ||
#`config.middleware.use Rack::SetXForwardedProtoHeader, 'Vendor-Forwarded-Proto-Header'` | ||
# to your application.rb file | ||
|
||
class SetXForwardedProtoHeader | ||
def initialize(app, vendor_forwarded_header) | ||
@app = app | ||
# Rack expects to see UPPER_UNDERSCORED_HEADERS, never SnakeCased-Dashed-Headers | ||
@vendor_forwarded_header = "HTTP_#{vendor_forwarded_header.upcase.gsub "-", "_"}" | ||
end | ||
|
||
def call(env) | ||
if value = env[@vendor_forwarded_header] | ||
env["HTTP_X_FORWARDED_PROTO"] = value | ||
end | ||
@app.call(env) | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'minitest/autorun' | ||
require 'rack/contrib/runtime' | ||
|
||
describe Rack::SetXForwardedProtoHeader do | ||
response = lambda {|e| [200, {}, []] } | ||
|
||
it "leaves the value of X_FORWARDED_PROTO intact if there is no vendor header passed in the request" do | ||
vendor_forwarded_header = "not passed in the request" | ||
env = Rack::MockRequest.env_for("/", "HTTP_X_FORWARDED_PROTO" => "http") | ||
|
||
Rack::Lint.new(Rack::SetXForwardedProtoHeader.new(response, vendor_forwarded_header)).call env | ||
|
||
env["HTTP_X_FORWARDED_PROTO"].must_equal "http" | ||
end | ||
|
||
it "does not set X-Forwarded-Proto when there is no vendor header passed in the request" do | ||
vendor_forwarded_header = "not passed in the request" | ||
env = Rack::MockRequest.env_for("/", "FOO" => "bar") | ||
|
||
Rack::Lint.new(Rack::SetXForwardedProtoHeader.new(response, vendor_forwarded_header)).call env | ||
|
||
env["FOO"].must_equal "bar" | ||
assert_nil(env["HTTP_X_FORWARDED_PROTO"]) | ||
end | ||
|
||
|
||
it "copies the value of the header to X-Forwarded-Proto" do | ||
env = Rack::MockRequest.env_for("/", "HTTP_VENDOR_FORWARDED_PROTO_HEADER" => "https") | ||
|
||
Rack::Lint.new(Rack::SetXForwardedProtoHeader.new(response, "Vendor-Forwarded-Proto-Header")).call env | ||
|
||
env["HTTP_X_FORWARDED_PROTO"].must_equal "https" | ||
end | ||
|
||
it "copies the value of the header to X-Forwarded-Proto overwriting an existing X-Forwarded-Proto" do | ||
env = Rack::MockRequest.env_for("/", "HTTP_VENDOR_FORWARDED_PROTO_HEADER" => "https", "HTTP_X_FORWARDED_PROTO" => "http") | ||
|
||
Rack::Lint.new(Rack::SetXForwardedProtoHeader.new(response, "Vendor-Forwarded-Proto-Header")).call env | ||
|
||
env["HTTP_X_FORWARDED_PROTO"].must_equal "https" | ||
end | ||
end |