Skip to content

Instantly share code, notes, and snippets.

@ndbroadbent
Created September 29, 2022 08:56
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 ndbroadbent/e1760075570d723086ff8dcb887754eb to your computer and use it in GitHub Desktop.
Save ndbroadbent/e1760075570d723086ff8dcb887754eb to your computer and use it in GitHub Desktop.
Rack middleware to enforce header length
# frozen_string_literal: true
# Only used during test and development. Ensures we never receive or respond with
# header data that is over 4k.
# See: https://community.convox.com/t/getting-502-bad-gateway-errors-for-one-page-on-v3-rack-app-responds-with-200-and-the-page-works-fine-on-v2-rack/841
module Rack
class HeaderLengthEnforcer
class HeadersTooLargeError < StandardError; end
NGINX_HEADER_LENGTH_LIMIT = 4000
def initialize(app)
@app = app
end
def call(env)
request_headers = {}
env.each do |key, value|
if key.start_with?('HTTP_')
request_headers[key] = value
end
end
request_headers_string = request_headers.to_a.map { |kv| kv.join(': ') }.join("\n")
if request_headers_string.length > NGINX_HEADER_LENGTH_LIMIT
raise HeadersTooLargeError, "Request headers too large: #{request_headers_string.length} > #{NGINX_HEADER_LENGTH_LIMIT}"
end
status, response_headers, body = @app.call(env)
response_headers_string = response_headers.to_a.map { |kv| kv.join(': ') }.join("\n")
if response_headers_string.length > NGINX_HEADER_LENGTH_LIMIT
raise HeadersTooLargeError, "Response headers too large: #{response_headers_string.length} > #{NGINX_HEADER_LENGTH_LIMIT}"
end
[status, response_headers, body]
end
end
end
Rails.application.configure do
# ...
config.middleware.insert_before 0, Rack::HeaderLengthEnforcer
# ...
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment