Skip to content
This repository was archived by the owner on Dec 13, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions lib/fastly-rails/rack/set_x_forwarded_headers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module FastlyRails
module Rack
# Set the X-Forwarded-Proto header to reflect
# the browser/Fastly connection.
#
# Useful for apps hosted on Heroku, where the X-Forwarded
# headers are set by the Heroku router to represent only the
# direct connection from Fastly's proxy server to Heroku.
#
# Example usage:
# ```
# config.middleware.insert_after(Rack::MethodOverride, FastlyRails::Rack::SetXForwardedHeaders)
# ```
class SetXForwardedHeaders
def initialize(app)
@app = app
end

def call(env)
if is_behind_fastly?(env)
if is_ssl?(env)
env["HTTPS"] = "on"
env["HTTP_X_FORWARDED_PROTO"] = "https"
else
env["HTTP_X_FORWARDED_PROTO"] = "http"
end
# Disambiguate
env.delete("HTTP_X_FORWARDED_PORT")
env.delete("HTTP_X_FORWARDED_SSL")
env.delete("HTTP_X_FORWARDED_SCHEME")
end
@app.call(env)
end

def is_behind_fastly?(env)
env["HTTP_FASTLY_CLIENT_IP"].present?
end

def is_ssl?(env)
env["HTTP_FASTLY_SSL"].present?
end
end
end
end
50 changes: 50 additions & 0 deletions test/fastly-rails/set_x_forwarded_headers_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require 'test_helper'
require 'fastly-rails/rack/set_x_forwarded_headers'

describe FastlyRails::Rack::SetXForwardedHeaders do
let(:ip) { Faker::Internet.ip_v4_address }
let(:middleware) { FastlyRails::Rack::SetXForwardedHeaders.new(app) }

describe 'without fastly' do
let(:headers) { {"HTTP_X_FORWARDED_PROTO" => "ftp"} }
let(:app) {
Proc.new { |env|
assert_nil env['HTTPS'], "Env var should not exist"
assert_equal "ftp", env['HTTP_X_FORWARDED_PROTO'], "Header should not have been modifed"
[200, {'Content-Type' => 'text/html'}, ["hello"]]
}
}
it 'should not change the env' do
middleware.call(headers)
end
end

describe 'with fastly' do
describe 'without ssl header' do
let(:headers) { {"HTTP_FASTLY_CLIENT_IP" => ip} }
let(:app) {
Proc.new { |env|
assert_nil env['HTTPS'], "Env var should not exist"
assert_equal "http", env['HTTP_X_FORWARDED_PROTO']
[200, {'Content-Type' => 'text/html'}, ["hello"]]
}
}
it 'should modify the env properly' do
middleware.call(headers)
end
end
describe 'with ssl header' do
let(:headers) { {"HTTP_FASTLY_CLIENT_IP" => ip, "HTTP_FASTLY_SSL" => "1"} }
let(:app) {
Proc.new { |env|
assert_equal "on", env['HTTPS']
assert_equal "https", env['HTTP_X_FORWARDED_PROTO']
[200, {'Content-Type' => 'text/html'}, ["hello"]]
}
}
it 'should modify the env properly' do
middleware.call(headers)
end
end
end
end