philiprehberger-header_kit

Tests Gem Version Last updated

HTTP header parsing, construction, and content negotiation

Requirements

  • Ruby >= 3.1

Installation

Add to your Gemfile:

gem "philiprehberger-header_kit"

Or install directly:

gem install philiprehberger-header_kit

Usage

require "philiprehberger/header_kit"

Parse Accept

Philiprehberger::HeaderKit.parse_accept("text/html;q=0.9, application/json")
# => [{type: "application/json", quality: 1.0, params: {}},
#     {type: "text/html", quality: 0.9, params: {}}]

Build Accept

Philiprehberger::HeaderKit.build_accept([{type: "text/html"}, {type: "application/json", quality: 0.9}])
# => "text/html, application/json;q=0.9"

Parse Accept-Language

Philiprehberger::HeaderKit.parse_accept_language("en-US,en;q=0.9,fr;q=0.8")
# => [{language: "en-US", quality: 1.0}, {language: "en", quality: 0.9}, {language: "fr", quality: 0.8}]

Negotiate Language

Philiprehberger::HeaderKit.negotiate_language("en-US,fr;q=0.9", ["fr", "en"])
# => "en"

Parse Accept-Encoding

Philiprehberger::HeaderKit.parse_accept_encoding("gzip, deflate;q=0.5, br;q=0.8")
# => [{encoding: "gzip", quality: 1.0}, {encoding: "br", quality: 0.8}, {encoding: "deflate", quality: 0.5}]

Parse Authorization

Philiprehberger::HeaderKit.parse_authorization("Bearer eyJhbGciOiJIUzI1NiJ9")
# => {scheme: "Bearer", credentials: "eyJhbGciOiJIUzI1NiJ9"}

Philiprehberger::HeaderKit.parse_authorization('Digest username="admin", realm="example"')
# => {scheme: "Digest", params: {"username" => "admin", "realm" => "example"}}

Parse Cache-Control

Philiprehberger::HeaderKit.parse_cache_control("public, max-age=3600, must-revalidate")
# => {public: true, max_age: 3600, must_revalidate: true}

Build Cache-Control

Philiprehberger::HeaderKit.build_cache_control(public: true, max_age: 3600)
# => "public, max-age=3600"

Parse Content-Type

Philiprehberger::HeaderKit.parse_content_type("text/html; charset=utf-8")
# => {media_type: "text/html", charset: "utf-8", boundary: nil}
Philiprehberger::HeaderKit.parse_cookie("session=abc123; user=john")
# => {"session" => "abc123", "user" => "john"}
Philiprehberger::HeaderKit.build_set_cookie("session", "abc123", secure: true, httponly: true, path: "/")
# => "session=abc123; Path=/; Secure; HttpOnly"
Philiprehberger::HeaderKit.parse_link('<https://example.com/2>; rel="next"')
# => [{uri: "https://example.com/2", rel: "next", type: nil, title: nil}]
Philiprehberger::HeaderKit.build_link([{uri: "https://example.com/2", rel: "next"}])
# => '<https://example.com/2>; rel="next"'

Content Negotiation

Philiprehberger::HeaderKit.negotiate("text/html;q=0.9, application/json", ["text/html", "application/json"])
# => "application/json"

Parse CORS

headers = {
  'Origin' => 'https://example.com',
  'Access-Control-Request-Method' => 'POST',
  'Access-Control-Request-Headers' => 'Content-Type, Authorization'
}
Philiprehberger::HeaderKit.parse_cors(headers)
# => {origin: "https://example.com", method: "POST", headers: ["Content-Type", "Authorization"]}

Build CORS

Philiprehberger::HeaderKit.build_cors(
  origin: "https://example.com",
  methods: ["GET", "POST"],
  headers: ["Content-Type"],
  max_age: 3600,
  credentials: true
)
# => {"Access-Control-Allow-Origin" => "https://example.com", ...}

Security Headers

Philiprehberger::HeaderKit.security_headers
# => {"X-Content-Type-Options" => "nosniff", "X-Frame-Options" => "DENY", ...}

Philiprehberger::HeaderKit.security_headers(hsts: "max-age=31536000", csp: "default-src 'self'")
# => includes Strict-Transport-Security and Content-Security-Policy

Parse Forwarded

Philiprehberger::HeaderKit.parse_forwarded('for=192.0.2.60;proto=http;by=203.0.113.43')
# => [{for: "192.0.2.60", proto: "http", by: "203.0.113.43"}]

Parse Via

Philiprehberger::HeaderKit.parse_via('1.1 vegur, 1.0 fred')
# => [{protocol: "1.1", host: "vegur"}, {protocol: "1.0", host: "fred"}]

Conditional-request matching

Philiprehberger::HeaderKit.etag_match?('"abc"', 'abc')
# => true

Philiprehberger::HeaderKit.etag_match?('W/"abc", W/"xyz"', 'xyz')
# => true

Philiprehberger::HeaderKit.etag_match?('*', 'anything')
# => true

Philiprehberger::HeaderKit.etag_match?('"abc"', 'nope')
# => false

Parse Retry-After

Philiprehberger::HeaderKit.parse_retry_after("120")
# => {seconds: 120}

Philiprehberger::HeaderKit.parse_retry_after("Fri, 04 Apr 2026 12:00:00 GMT")
# => {date: 2026-04-04 12:00:00 UTC}

API

Method Description
HeaderKit.parse_accept(header) Parse Accept header into sorted entries
HeaderKit.build_accept(types) Build Accept header string from type array
HeaderKit.parse_accept_language(header) Parse Accept-Language into sorted entries
HeaderKit.negotiate_language(header, available) Language negotiation, returns best match or nil
HeaderKit.parse_accept_encoding(header) Parse Accept-Encoding into sorted entries
HeaderKit.parse_authorization(header) Parse Authorization header (Bearer, Basic, Digest)
HeaderKit.parse_cache_control(header) Parse Cache-Control into directive hash
HeaderKit.build_cache_control(directives) Build Cache-Control string from hash
HeaderKit.parse_content_type(header) Parse Content-Type into components
HeaderKit.parse_cookie(header) Parse Cookie header into name-value hash
HeaderKit.build_set_cookie(name, value, **opts) Build Set-Cookie header string
HeaderKit.parse_link(header) Parse Link header into entry array
HeaderKit.build_link(links) Build Link header from array of hashes
HeaderKit.negotiate(accept_header, available) Content negotiation, returns best match or nil
HeaderKit.parse_cors(headers) Parse CORS-related request headers
HeaderKit.build_cors(**options) Build CORS response headers
HeaderKit.security_headers(**options) Generate recommended security headers
HeaderKit.parse_forwarded(header) Parse RFC 7239 Forwarded header
HeaderKit.parse_via(header) Parse Via header into structured entries
HeaderKit.parse_retry_after(header) Parse Retry-After header (seconds or HTTP date)
HeaderKit.etag_match?(header_value, resource_etag) Check If-None-Match / If-Match against a resource ETag (list, W/ weak prefix, * wildcard)

Development

bundle install
bundle exec rspec
bundle exec rubocop

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT