|
| 1 | +# Headers |
| 2 | + |
| 3 | +This guide explains how to work with HTTP headers using `protocol-http`. |
| 4 | + |
| 5 | +## Core Concepts |
| 6 | + |
| 7 | +`protocol-http` provides several core concepts for working with HTTP headers: |
| 8 | + |
| 9 | +- A {ruby Protocol::HTTP::Headers} class which represents a collection of HTTP headers with built-in security and policy features. |
| 10 | +- Header-specific classes like {ruby Protocol::HTTP::Header::Accept} and {ruby Protocol::HTTP::Header::Authorization} which provide specialized parsing and formatting. |
| 11 | +- Trailer security validation to prevent HTTP request smuggling attacks. |
| 12 | + |
| 13 | +## Usage |
| 14 | + |
| 15 | +The {Protocol::HTTP::Headers} class provides a comprehensive interface for creating and manipulating HTTP headers: |
| 16 | + |
| 17 | +```ruby |
| 18 | +require 'protocol/http' |
| 19 | + |
| 20 | +headers = Protocol::HTTP::Headers.new |
| 21 | +headers.add('content-type', 'text/html') |
| 22 | +headers.add('set-cookie', 'session=abc123') |
| 23 | + |
| 24 | +# Access headers |
| 25 | +content_type = headers['content-type'] # => "text/html" |
| 26 | + |
| 27 | +# Check if header exists |
| 28 | +headers.include?('content-type') # => true |
| 29 | +``` |
| 30 | + |
| 31 | +### Header Policies |
| 32 | + |
| 33 | +Different header types have different behaviors for merging, validation, and trailer handling: |
| 34 | + |
| 35 | +```ruby |
| 36 | +# Some headers can be specified multiple times |
| 37 | +headers.add('set-cookie', 'first=value1') |
| 38 | +headers.add('set-cookie', 'second=value2') |
| 39 | + |
| 40 | +# Others are singletons and will raise errors if duplicated |
| 41 | +headers.add('content-length', '100') |
| 42 | +# headers.add('content-length', '200') # Would raise DuplicateHeaderError |
| 43 | +``` |
| 44 | + |
| 45 | +### Structured Headers |
| 46 | + |
| 47 | +Some headers have specialized classes for parsing and formatting: |
| 48 | + |
| 49 | +```ruby |
| 50 | +# Accept header with media ranges |
| 51 | +accept = Protocol::HTTP::Header::Accept.new('text/html,application/json;q=0.9') |
| 52 | +media_ranges = accept.media_ranges |
| 53 | + |
| 54 | +# Authorization header |
| 55 | +auth = Protocol::HTTP::Header::Authorization.basic('username', 'password') |
| 56 | +# => "Basic dXNlcm5hbWU6cGFzc3dvcmQ=" |
| 57 | +``` |
| 58 | + |
| 59 | +### Trailer Security |
| 60 | + |
| 61 | +HTTP trailers are headers that appear after the message body. For security reasons, only certain headers are allowed in trailers: |
| 62 | + |
| 63 | +```ruby |
| 64 | +# Working with trailers |
| 65 | +headers = Protocol::HTTP::Headers.new([ |
| 66 | + ['content-type', 'text/html'], |
| 67 | + ['content-length', '1000'] |
| 68 | +]) |
| 69 | + |
| 70 | +# Start trailer section |
| 71 | +headers.trailer! |
| 72 | + |
| 73 | +# These will be allowed (safe metadata) |
| 74 | +headers.add('etag', '"12345"') |
| 75 | +headers.add('date', Time.now.httpdate) |
| 76 | + |
| 77 | +# These will be silently ignored for security |
| 78 | +headers.add('authorization', 'Bearer token') # Ignored - credential leakage risk |
| 79 | +headers.add('connection', 'close') # Ignored - hop-by-hop header |
| 80 | +``` |
| 81 | + |
| 82 | +The trailer security system prevents HTTP request smuggling by restricting which headers can appear in trailers: |
| 83 | + |
| 84 | +**Allowed headers** (return `true` for `trailer?`): |
| 85 | +- `date` - Response generation timestamps. |
| 86 | +- `digest` - Content integrity verification. |
| 87 | +- `etag` - Cache validation tags. |
| 88 | +- `server-timing` - Performance metrics. |
| 89 | + |
| 90 | +**Forbidden headers** (return `false` for `trailer?`): |
| 91 | +- `authorization` - Prevents credential leakage. |
| 92 | +- `connection`, `te`, `transfer-encoding` - Hop-by-hop headers that control connection behavior. |
| 93 | +- `cookie`, `set-cookie` - State information needed during initial processing. |
| 94 | +- `accept` - Content negotiation must occur before response generation. |
0 commit comments