Created
May 25, 2016 06:44
-
-
Save pda/ece0858ecf9c2258f7de6d34c4417c1e to your computer and use it in GitHub Desktop.
RackHeaderRenamer middleware for Rack; copy a request header to a different name before Rails etc sees it. e.g. config.middleware.insert(0, RackHeaderRenamer, "X-Varnish-Proto" => "X-Forwarded-Proto")
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
class RackHeaderRenamer | |
# mapping example, sets/overwrites second header with first: | |
# {"X-Varnish-Proto" => "X-Forwarded-Proto"} | |
def initialize(app, mapping) | |
@app = app | |
@mapping = mapping | |
end | |
def call(env) | |
@mapping.each_pair do |src, dst| | |
Command.new(env, src, dst).rename | |
end | |
@app.call(env) | |
end | |
private | |
class Command | |
def initialize(env, src, dst) | |
@env = env | |
@src = src | |
@dst = dst | |
end | |
def rename | |
if @env.key?(src_key) | |
@env[dst_key] = @env[src_key] | |
end | |
end | |
private | |
def src_key | |
header_to_key(@src) | |
end | |
def dst_key | |
header_to_key(@dst) | |
end | |
def header_to_key(header_name) | |
"HTTP_" << header_name.upcase.gsub("-", "_") | |
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
RSpec.describe RackHeaderRenamer do | |
subject(:renamer) do | |
RackHeaderRenamer.new(app, "X-Source-Header" => "X-Destination-Header") | |
end | |
let(:app) { double("app", call: [200, {}, []]) } | |
let(:env) do | |
{"HTTP_X_HERRING" => "red"} | |
end | |
context "with only source header present" do | |
before do | |
env["HTTP_X_SOURCE_HEADER"] = "only source" | |
end | |
it "creates new destination header" do | |
renamer.call(env) | |
expect(env["HTTP_X_DESTINATION_HEADER"]).to eq("only source") | |
end | |
end | |
context "with only destination header present" do | |
before do | |
env["HTTP_X_DESTINATION_HEADER"] = "only destination" | |
end | |
it "does not overwrite destination header" do | |
renamer.call(env) | |
expect(env["HTTP_X_DESTINATION_HEADER"]).to eq("only destination") | |
end | |
end | |
context "with neither header present" do | |
it "does not touch env" do | |
expect { renamer.call(env) }.to_not change { env } | |
end | |
end | |
context "with both headers present" do | |
before do | |
env["HTTP_X_SOURCE_HEADER"] = "source" | |
env["HTTP_X_DESTINATION_HEADER"] = "destination" | |
end | |
it "overwrites destination header" do | |
renamer.call(env) | |
expect(env["HTTP_X_DESTINATION_HEADER"]).to eq("source") | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment