Skip to content

Instantly share code, notes, and snippets.

@pda
Created May 25, 2016 06:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pda/ece0858ecf9c2258f7de6d34c4417c1e to your computer and use it in GitHub Desktop.
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")
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
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