philiprehberger-header_kit 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0483e3f7557d6bc4a5d455fa7fcfbee3808118f120f17427f73c1b763cdfa4dd'
4
- data.tar.gz: f2834acace689c8b78da5e7af771348efa97918bf7eb71434e6317708ef9da62
3
+ metadata.gz: 3d4bcbb3c1002def0f437335a19871b535ce7764369d43fed1c4a1548367988f
4
+ data.tar.gz: 03dea17ed3566ea8cce9ea8511f741c92487113b6ba0a4cdb899ab1835f07009
5
5
  SHA512:
6
- metadata.gz: cbc23f4ecb68a3c80815a21f09de5156ccef17e9d9cc15a2d420409209f06119491d059ccfc9d3de26f268029cb78b910db12d88c56cf0918a14dea45d11f75e
7
- data.tar.gz: 6c792d9fbff457ce2377ab95e641bce5626bb3a8ce5a01df1f0062cee51b9be05c0e9ecdc91e978938842213c5c76e9847cb521f1c91031d06f766b75be5df88
6
+ metadata.gz: 35c43a782a9e1ba431f972d18ec2c248a6141e96f79c082d09a2a48f973aee449d684011e4b70e3f95b4c488ff71fb1537c8da716e0186669e9ca974ff267792
7
+ data.tar.gz: 1b82e5bdea29824445c2097f21009f57a0f71cebbd80799386aed785e2247de8a4c87bd65136e198fea1150485c6909264f21cfed3970a2365c47c61ca7b7ce7
data/CHANGELOG.md CHANGED
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.0] - 2026-03-28
11
+
12
+ ### Added
13
+
14
+ - Parse Accept-Language headers with quality values
15
+ - Negotiate best language match from Accept-Language against available languages
16
+ - Parse Accept-Encoding headers with quality values
17
+ - Parse Authorization headers (Bearer, Basic, Digest schemes)
18
+ - Parse Cookie headers into name-value hashes
19
+ - Build Set-Cookie header strings with all standard attributes
20
+ - Build Accept header strings from structured type arrays
21
+
22
+ ## [0.1.1] - 2026-03-26
23
+
24
+ ### Changed
25
+
26
+ - Fix README compliance (sponsor badge format, license link)
27
+
10
28
  ## [0.1.0] - 2026-03-26
11
29
 
12
30
  ### Added
data/README.md CHANGED
@@ -2,8 +2,12 @@
2
2
 
3
3
  [![Tests](https://github.com/philiprehberger/rb-header-kit/actions/workflows/ci.yml/badge.svg)](https://github.com/philiprehberger/rb-header-kit/actions/workflows/ci.yml)
4
4
  [![Gem Version](https://badge.fury.io/rb/philiprehberger-header_kit.svg)](https://rubygems.org/gems/philiprehberger-header_kit)
5
+ [![GitHub release](https://img.shields.io/github/v/release/philiprehberger/rb-header-kit)](https://github.com/philiprehberger/rb-header-kit/releases)
6
+ [![Last updated](https://img.shields.io/github/last-commit/philiprehberger/rb-header-kit)](https://github.com/philiprehberger/rb-header-kit/commits/main)
5
7
  [![License](https://img.shields.io/github/license/philiprehberger/rb-header-kit)](LICENSE)
6
- [![Sponsor](https://img.shields.io/badge/sponsor-philiprehberger-pink?logo=githubsponsors)](https://github.com/sponsors/philiprehberger)
8
+ [![Bug Reports](https://img.shields.io/github/issues/philiprehberger/rb-header-kit/bug)](https://github.com/philiprehberger/rb-header-kit/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
9
+ [![Feature Requests](https://img.shields.io/github/issues/philiprehberger/rb-header-kit/enhancement)](https://github.com/philiprehberger/rb-header-kit/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)
10
+ [![Sponsor](https://img.shields.io/badge/sponsor-GitHub%20Sponsors-ec6cb9)](https://github.com/sponsors/philiprehberger)
7
11
 
8
12
  HTTP header parsing, construction, and content negotiation
9
13
 
@@ -39,6 +43,44 @@ Philiprehberger::HeaderKit.parse_accept("text/html;q=0.9, application/json")
39
43
  # {type: "text/html", quality: 0.9, params: {}}]
40
44
  ```
41
45
 
46
+ ### Build Accept
47
+
48
+ ```ruby
49
+ Philiprehberger::HeaderKit.build_accept([{type: "text/html"}, {type: "application/json", quality: 0.9}])
50
+ # => "text/html, application/json;q=0.9"
51
+ ```
52
+
53
+ ### Parse Accept-Language
54
+
55
+ ```ruby
56
+ Philiprehberger::HeaderKit.parse_accept_language("en-US,en;q=0.9,fr;q=0.8")
57
+ # => [{language: "en-US", quality: 1.0}, {language: "en", quality: 0.9}, {language: "fr", quality: 0.8}]
58
+ ```
59
+
60
+ ### Negotiate Language
61
+
62
+ ```ruby
63
+ Philiprehberger::HeaderKit.negotiate_language("en-US,fr;q=0.9", ["fr", "en"])
64
+ # => "en"
65
+ ```
66
+
67
+ ### Parse Accept-Encoding
68
+
69
+ ```ruby
70
+ Philiprehberger::HeaderKit.parse_accept_encoding("gzip, deflate;q=0.5, br;q=0.8")
71
+ # => [{encoding: "gzip", quality: 1.0}, {encoding: "br", quality: 0.8}, {encoding: "deflate", quality: 0.5}]
72
+ ```
73
+
74
+ ### Parse Authorization
75
+
76
+ ```ruby
77
+ Philiprehberger::HeaderKit.parse_authorization("Bearer eyJhbGciOiJIUzI1NiJ9")
78
+ # => {scheme: "Bearer", credentials: "eyJhbGciOiJIUzI1NiJ9"}
79
+
80
+ Philiprehberger::HeaderKit.parse_authorization('Digest username="admin", realm="example"')
81
+ # => {scheme: "Digest", params: {"username" => "admin", "realm" => "example"}}
82
+ ```
83
+
42
84
  ### Parse Cache-Control
43
85
 
44
86
  ```ruby
@@ -60,6 +102,20 @@ Philiprehberger::HeaderKit.parse_content_type("text/html; charset=utf-8")
60
102
  # => {media_type: "text/html", charset: "utf-8", boundary: nil}
61
103
  ```
62
104
 
105
+ ### Parse Cookie
106
+
107
+ ```ruby
108
+ Philiprehberger::HeaderKit.parse_cookie("session=abc123; user=john")
109
+ # => {"session" => "abc123", "user" => "john"}
110
+ ```
111
+
112
+ ### Build Set-Cookie
113
+
114
+ ```ruby
115
+ Philiprehberger::HeaderKit.build_set_cookie("session", "abc123", secure: true, httponly: true, path: "/")
116
+ # => "session=abc123; Path=/; Secure; HttpOnly"
117
+ ```
118
+
63
119
  ### Parse Link
64
120
 
65
121
  ```ruby
@@ -86,9 +142,16 @@ Philiprehberger::HeaderKit.negotiate("text/html;q=0.9, application/json", ["text
86
142
  | Method | Description |
87
143
  |--------|-------------|
88
144
  | `HeaderKit.parse_accept(header)` | Parse Accept header into sorted entries |
145
+ | `HeaderKit.build_accept(types)` | Build Accept header string from type array |
146
+ | `HeaderKit.parse_accept_language(header)` | Parse Accept-Language into sorted entries |
147
+ | `HeaderKit.negotiate_language(header, available)` | Language negotiation, returns best match or nil |
148
+ | `HeaderKit.parse_accept_encoding(header)` | Parse Accept-Encoding into sorted entries |
149
+ | `HeaderKit.parse_authorization(header)` | Parse Authorization header (Bearer, Basic, Digest) |
89
150
  | `HeaderKit.parse_cache_control(header)` | Parse Cache-Control into directive hash |
90
151
  | `HeaderKit.build_cache_control(directives)` | Build Cache-Control string from hash |
91
152
  | `HeaderKit.parse_content_type(header)` | Parse Content-Type into components |
153
+ | `HeaderKit.parse_cookie(header)` | Parse Cookie header into name-value hash |
154
+ | `HeaderKit.build_set_cookie(name, value, **opts)` | Build Set-Cookie header string |
92
155
  | `HeaderKit.parse_link(header)` | Parse Link header into entry array |
93
156
  | `HeaderKit.build_link(links)` | Build Link header from array of hashes |
94
157
  | `HeaderKit.negotiate(accept_header, available)` | Content negotiation, returns best match or nil |
@@ -97,10 +160,17 @@ Philiprehberger::HeaderKit.negotiate("text/html;q=0.9, application/json", ["text
97
160
 
98
161
  ```bash
99
162
  bundle install
100
- bundle exec rspec # Run tests
101
- bundle exec rubocop # Check code style
163
+ bundle exec rspec
164
+ bundle exec rubocop
102
165
  ```
103
166
 
167
+ ## Support
168
+
169
+ If you find this package useful, consider giving it a star on GitHub — it helps motivate continued maintenance and development.
170
+
171
+ [![LinkedIn](https://img.shields.io/badge/Philip%20Rehberger-LinkedIn-0A66C2?logo=linkedin)](https://www.linkedin.com/in/philiprehberger)
172
+ [![More packages](https://img.shields.io/badge/more-open%20source%20packages-blue)](https://philiprehberger.com/open-source-packages)
173
+
104
174
  ## License
105
175
 
106
- MIT
176
+ [MIT](LICENSE)
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Philiprehberger
4
+ module HeaderKit
5
+ # Builds Accept header strings from structured type entries.
6
+ module AcceptBuilder
7
+ # Build an Accept header string from an array of type hashes.
8
+ #
9
+ # @param types [Array<Hash>] each with :type and optional :quality
10
+ # @return [String] formatted Accept header value
11
+ def self.build(types)
12
+ return '' if types.nil? || types.empty?
13
+
14
+ parts = types.map do |entry|
15
+ type = entry[:type]
16
+ quality = entry[:quality]
17
+
18
+ if quality && quality < 1.0
19
+ "#{type};q=#{format_quality(quality)}"
20
+ else
21
+ type
22
+ end
23
+ end
24
+
25
+ parts.join(', ')
26
+ end
27
+
28
+ # Format a quality value, removing trailing zeros.
29
+ #
30
+ # @param quality [Float] the quality value
31
+ # @return [String] formatted quality string
32
+ def self.format_quality(quality)
33
+ formatted = format('%.3f', quality)
34
+ formatted.sub(/0+\z/, '').sub(/\.\z/, '.0')
35
+ end
36
+
37
+ private_class_method :format_quality
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Philiprehberger
4
+ module HeaderKit
5
+ # Parses Accept-Encoding headers into structured encoding entries with quality values.
6
+ module AcceptEncoding
7
+ QUALITY_PATTERN = /\Aq\z/i
8
+
9
+ # Parse an Accept-Encoding header string.
10
+ #
11
+ # @param header [String] the Accept-Encoding header value
12
+ # @return [Array<Hash>] sorted by quality descending, each with :encoding, :quality
13
+ def self.parse(header)
14
+ return [] if header.nil? || header.strip.empty?
15
+
16
+ entries = header.split(',').map { |entry| parse_entry(entry.strip) }
17
+ entries.compact.sort_by { |e| [-e[:quality], entries.index(e)] }
18
+ end
19
+
20
+ # Parse a single encoding entry.
21
+ #
22
+ # @param entry [String] a single encoding with optional quality
23
+ # @return [Hash, nil] parsed entry or nil if invalid
24
+ def self.parse_entry(entry)
25
+ return nil if entry.empty?
26
+
27
+ parts = entry.split(';').map(&:strip)
28
+ encoding = parts.shift
29
+ return nil if encoding.nil? || encoding.empty?
30
+
31
+ quality = 1.0
32
+
33
+ parts.each do |param|
34
+ key, value = param.split('=', 2).map(&:strip)
35
+ next if key.nil? || key.empty?
36
+
37
+ quality = parse_quality(value) if QUALITY_PATTERN.match?(key)
38
+ end
39
+
40
+ { encoding: encoding.downcase, quality: quality }
41
+ end
42
+
43
+ # Parse a quality value, clamping to [0.0, 1.0].
44
+ #
45
+ # @param value [String, nil] the quality string
46
+ # @return [Float] parsed quality value
47
+ def self.parse_quality(value)
48
+ return 1.0 if value.nil? || value.empty?
49
+
50
+ value.to_f.clamp(0.0, 1.0)
51
+ end
52
+
53
+ private_class_method :parse_entry, :parse_quality
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Philiprehberger
4
+ module HeaderKit
5
+ # Parses Accept-Language headers into structured language entries with quality values.
6
+ module AcceptLanguage
7
+ QUALITY_PATTERN = /\Aq\z/i
8
+
9
+ # Parse an Accept-Language header string.
10
+ #
11
+ # @param header [String] the Accept-Language header value
12
+ # @return [Array<Hash>] sorted by quality descending, each with :language, :quality
13
+ def self.parse(header)
14
+ return [] if header.nil? || header.strip.empty?
15
+
16
+ entries = header.split(',').map { |entry| parse_entry(entry.strip) }
17
+ entries.compact.sort_by { |e| [-e[:quality], entries.index(e)] }
18
+ end
19
+
20
+ # Negotiate the best language match from available languages.
21
+ #
22
+ # @param header [String] the Accept-Language header value
23
+ # @param available [Array<String>] list of available language tags
24
+ # @return [String, nil] the best matching language, or nil if no match
25
+ def self.negotiate(header, available)
26
+ return nil if available.nil? || available.empty?
27
+ return available.first if header.nil? || header.strip.empty?
28
+
29
+ parsed = parse(header)
30
+ return nil if parsed.empty?
31
+
32
+ parsed.each do |entry|
33
+ next if entry[:quality] <= 0.0
34
+
35
+ match = find_match(entry[:language], available)
36
+ return match if match
37
+ end
38
+
39
+ nil
40
+ end
41
+
42
+ # Parse a single language entry.
43
+ #
44
+ # @param entry [String] a single language tag with optional quality
45
+ # @return [Hash, nil] parsed entry or nil if invalid
46
+ def self.parse_entry(entry)
47
+ return nil if entry.empty?
48
+
49
+ parts = entry.split(';').map(&:strip)
50
+ language = parts.shift
51
+ return nil if language.nil? || language.empty?
52
+
53
+ quality = 1.0
54
+
55
+ parts.each do |param|
56
+ key, value = param.split('=', 2).map(&:strip)
57
+ next if key.nil? || key.empty?
58
+
59
+ quality = parse_quality(value) if QUALITY_PATTERN.match?(key)
60
+ end
61
+
62
+ { language: language, quality: quality }
63
+ end
64
+
65
+ # Parse a quality value, clamping to [0.0, 1.0].
66
+ #
67
+ # @param value [String, nil] the quality string
68
+ # @return [Float] parsed quality value
69
+ def self.parse_quality(value)
70
+ return 1.0 if value.nil? || value.empty?
71
+
72
+ value.to_f.clamp(0.0, 1.0)
73
+ end
74
+
75
+ # Find the best match for a language tag among available languages.
76
+ #
77
+ # @param tag [String] the requested language tag
78
+ # @param available [Array<String>] available language tags
79
+ # @return [String, nil] matching language or nil
80
+ def self.find_match(tag, available)
81
+ return available.first if tag == '*'
82
+
83
+ downcased = tag.downcase
84
+ exact = available.find { |a| a.downcase == downcased }
85
+ return exact if exact
86
+
87
+ prefix = available.find { |a| a.downcase.start_with?("#{downcased}-") }
88
+ return prefix if prefix
89
+
90
+ base = downcased.split('-').first
91
+ available.find { |a| a.downcase.split('-').first == base }
92
+ end
93
+
94
+ private_class_method :parse_entry, :parse_quality, :find_match
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Philiprehberger
4
+ module HeaderKit
5
+ # Parses Authorization headers for Bearer, Basic, and Digest schemes.
6
+ module Authorization
7
+ DIGEST_PARAM_PATTERN = %r{(\w+)=(?:"([^"]*)"|([\w+/=]+))}
8
+
9
+ # Parse an Authorization header string.
10
+ #
11
+ # @param header [String] the Authorization header value
12
+ # @return [Hash] with :scheme and :credentials (Bearer/Basic) or :params (Digest)
13
+ def self.parse(header)
14
+ return { scheme: nil, credentials: nil } if header.nil? || header.strip.empty?
15
+
16
+ stripped = header.strip
17
+ space_index = stripped.index(' ')
18
+
19
+ unless space_index
20
+ return { scheme: stripped, credentials: nil }
21
+ end
22
+
23
+ scheme = stripped[0...space_index]
24
+ rest = stripped[(space_index + 1)..].strip
25
+
26
+ case scheme.downcase
27
+ when 'bearer', 'basic'
28
+ { scheme: scheme, credentials: rest }
29
+ when 'digest'
30
+ { scheme: scheme, params: parse_digest_params(rest) }
31
+ else
32
+ { scheme: scheme, credentials: rest }
33
+ end
34
+ end
35
+
36
+ # Parse Digest authorization parameters.
37
+ #
38
+ # @param params_str [String] the parameter string after "Digest "
39
+ # @return [Hash{String => String}] parsed key-value parameters
40
+ def self.parse_digest_params(params_str)
41
+ params = {}
42
+
43
+ params_str.scan(DIGEST_PARAM_PATTERN).each do |key, quoted_value, unquoted_value|
44
+ params[key] = quoted_value || unquoted_value
45
+ end
46
+
47
+ params
48
+ end
49
+
50
+ private_class_method :parse_digest_params
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Philiprehberger
4
+ module HeaderKit
5
+ # Parses Cookie headers and builds Set-Cookie header strings.
6
+ module Cookie
7
+ # Parse a Cookie header string into a name-value hash.
8
+ #
9
+ # @param header [String] the Cookie header value
10
+ # @return [Hash{String => String}] cookie name-value pairs
11
+ def self.parse(header)
12
+ return {} if header.nil? || header.strip.empty?
13
+
14
+ cookies = {}
15
+
16
+ header.split(';').each do |pair|
17
+ pair = pair.strip
18
+ next if pair.empty?
19
+
20
+ name, value = pair.split('=', 2)
21
+ next if name.nil? || name.strip.empty?
22
+
23
+ cookies[name.strip] = (value || '').strip
24
+ end
25
+
26
+ cookies
27
+ end
28
+
29
+ # Build a Set-Cookie header string.
30
+ #
31
+ # @param name [String] cookie name
32
+ # @param value [String] cookie value
33
+ # @param expires [String, nil] Expires attribute value
34
+ # @param max_age [Integer, nil] Max-Age attribute value
35
+ # @param secure [Boolean] include Secure flag
36
+ # @param httponly [Boolean] include HttpOnly flag
37
+ # @param samesite [String, nil] SameSite attribute (Strict, Lax, None)
38
+ # @param path [String, nil] Path attribute
39
+ # @param domain [String, nil] Domain attribute
40
+ # @return [String] formatted Set-Cookie header value
41
+ def self.build_set_cookie(name, value, expires: nil, max_age: nil, secure: false, # rubocop:disable Metrics/ParameterLists
42
+ httponly: false, samesite: nil, path: nil, domain: nil)
43
+ parts = ["#{name}=#{value}"]
44
+ parts << "Expires=#{expires}" if expires
45
+ parts << "Max-Age=#{max_age}" if max_age
46
+ parts << "Domain=#{domain}" if domain
47
+ parts << "Path=#{path}" if path
48
+ parts << 'Secure' if secure
49
+ parts << 'HttpOnly' if httponly
50
+ parts << "SameSite=#{samesite}" if samesite
51
+
52
+ parts.join('; ')
53
+ end
54
+ end
55
+ end
56
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Philiprehberger
4
4
  module HeaderKit
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
6
6
  end
7
7
  end
@@ -2,8 +2,13 @@
2
2
 
3
3
  require_relative 'header_kit/version'
4
4
  require_relative 'header_kit/accept'
5
+ require_relative 'header_kit/accept_builder'
6
+ require_relative 'header_kit/accept_encoding'
7
+ require_relative 'header_kit/accept_language'
8
+ require_relative 'header_kit/authorization'
5
9
  require_relative 'header_kit/cache_control'
6
10
  require_relative 'header_kit/content_type'
11
+ require_relative 'header_kit/cookie'
7
12
  require_relative 'header_kit/link'
8
13
  require_relative 'header_kit/negotiation'
9
14
 
@@ -19,6 +24,47 @@ module Philiprehberger
19
24
  Accept.parse(header)
20
25
  end
21
26
 
27
+ # Build an Accept header string from an array of type hashes.
28
+ #
29
+ # @param types [Array<Hash>] each with :type and optional :quality
30
+ # @return [String] formatted Accept header value
31
+ def self.build_accept(types)
32
+ AcceptBuilder.build(types)
33
+ end
34
+
35
+ # Parse an Accept-Encoding header into structured entries sorted by quality.
36
+ #
37
+ # @param header [String] the Accept-Encoding header value
38
+ # @return [Array<Hash>] entries with :encoding, :quality keys
39
+ def self.parse_accept_encoding(header)
40
+ AcceptEncoding.parse(header)
41
+ end
42
+
43
+ # Parse an Accept-Language header into structured entries sorted by quality.
44
+ #
45
+ # @param header [String] the Accept-Language header value
46
+ # @return [Array<Hash>] entries with :language, :quality keys
47
+ def self.parse_accept_language(header)
48
+ AcceptLanguage.parse(header)
49
+ end
50
+
51
+ # Negotiate the best language from an Accept-Language header.
52
+ #
53
+ # @param header [String] the Accept-Language header value
54
+ # @param available [Array<String>] list of available language tags
55
+ # @return [String, nil] the best matching language, or nil if no match
56
+ def self.negotiate_language(header, available)
57
+ AcceptLanguage.negotiate(header, available)
58
+ end
59
+
60
+ # Parse an Authorization header into its components.
61
+ #
62
+ # @param header [String] the Authorization header value
63
+ # @return [Hash] with :scheme and :credentials or :params
64
+ def self.parse_authorization(header)
65
+ Authorization.parse(header)
66
+ end
67
+
22
68
  # Parse a Cache-Control header into a directive hash.
23
69
  #
24
70
  # @param header [String] the Cache-Control header value
@@ -43,6 +89,24 @@ module Philiprehberger
43
89
  ContentType.parse(header)
44
90
  end
45
91
 
92
+ # Parse a Cookie header into a name-value hash.
93
+ #
94
+ # @param header [String] the Cookie header value
95
+ # @return [Hash{String => String}] cookie name-value pairs
96
+ def self.parse_cookie(header)
97
+ Cookie.parse(header)
98
+ end
99
+
100
+ # Build a Set-Cookie header string.
101
+ #
102
+ # @param name [String] cookie name
103
+ # @param value [String] cookie value
104
+ # @param options [Hash] optional attributes (expires:, max_age:, secure:, httponly:, samesite:, path:, domain:)
105
+ # @return [String] formatted Set-Cookie header value
106
+ def self.build_set_cookie(name, value, **options)
107
+ Cookie.build_set_cookie(name, value, **options)
108
+ end
109
+
46
110
  # Parse a Link header into an array of link entries.
47
111
  #
48
112
  # @param header [String] the Link header value
metadata CHANGED
@@ -1,17 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: philiprehberger-header_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philip Rehberger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-27 00:00:00.000000000 Z
11
+ date: 2026-03-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Parse and build Accept, Cache-Control, Content-Type, and Link HTTP headers.
14
- Includes content negotiation for selecting the best response type.
13
+ description: Parse and build Accept, Accept-Language, Accept-Encoding, Authorization,
14
+ Cache-Control, Content-Type, Cookie, and Link HTTP headers. Includes content negotiation
15
+ for selecting the best response type or language.
15
16
  email:
16
17
  - me@philiprehberger.com
17
18
  executables: []
@@ -23,8 +24,13 @@ files:
23
24
  - README.md
24
25
  - lib/philiprehberger/header_kit.rb
25
26
  - lib/philiprehberger/header_kit/accept.rb
27
+ - lib/philiprehberger/header_kit/accept_builder.rb
28
+ - lib/philiprehberger/header_kit/accept_encoding.rb
29
+ - lib/philiprehberger/header_kit/accept_language.rb
30
+ - lib/philiprehberger/header_kit/authorization.rb
26
31
  - lib/philiprehberger/header_kit/cache_control.rb
27
32
  - lib/philiprehberger/header_kit/content_type.rb
33
+ - lib/philiprehberger/header_kit/cookie.rb
28
34
  - lib/philiprehberger/header_kit/link.rb
29
35
  - lib/philiprehberger/header_kit/negotiation.rb
30
36
  - lib/philiprehberger/header_kit/version.rb