protocol-http 0.64.0 → 0.65.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/protocol/http/header/accept.rb +30 -6
- data/lib/protocol/http/header/cookie.rb +39 -10
- data/lib/protocol/http/header/set_cookie.rb +37 -0
- data/lib/protocol/http/headers.rb +8 -1
- data/lib/protocol/http/version.rb +1 -1
- data/readme.md +5 -8
- data/releases.md +5 -0
- data.tar.gz.sig +0 -0
- metadata +2 -1
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b17dbce0da66e6f9093d1e3e6a3cebbe8e666a7fd9f5e002dc41f9de427d8415
|
|
4
|
+
data.tar.gz: 07aa35d8c33d720d9f00c95228f2d2d88a755a5aad9d1f8e652967a2e88080a4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c976e4a859e43de63ca1ee55eaced96ff4122e167a806f95a9e6b001de0fcfcece9132915e6004c14249b57b539a1f7add64411747f402bd4a9e8ecaf5120242
|
|
7
|
+
data.tar.gz: dc9422aaf8a88c83c477c8ad2e35a3e88b7de37d2b6b2d7636dec9ea6b88860c35b100214727b6baafed1175aa96e1366223e6dbe2a725adaf7600d5350d4a49
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
|
@@ -15,12 +15,12 @@ module Protocol
|
|
|
15
15
|
class Accept < Split
|
|
16
16
|
# Regular expression used to split values on commas, with optional surrounding whitespace, taking into account quoted strings.
|
|
17
17
|
SEPARATOR = /
|
|
18
|
-
(?:
|
|
19
|
-
"[^"\\]*"
|
|
20
|
-
|
|
|
21
|
-
[^,"]+
|
|
18
|
+
(?: # Start non-capturing group
|
|
19
|
+
"(?:[^"\\]|\\.)*" # Match quoted strings, including quoted pairs
|
|
20
|
+
| # OR
|
|
21
|
+
[^,"]+ # Match non-quoted strings until a comma or quote
|
|
22
22
|
)+
|
|
23
|
-
(?=,|\z)
|
|
23
|
+
(?=,|\z) # Match until a comma or end of string
|
|
24
24
|
/x
|
|
25
25
|
|
|
26
26
|
ParseError = Class.new(Error)
|
|
@@ -114,8 +114,24 @@ module Protocol
|
|
|
114
114
|
type = match[:type]
|
|
115
115
|
subtype = match[:subtype]
|
|
116
116
|
parameters = {}
|
|
117
|
+
parameters_string = match[:parameters]
|
|
118
|
+
offset = 0
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
parameters_string.scan(PARAMETER) do |key, value, quoted_value|
|
|
121
|
+
parameter_match = Regexp.last_match
|
|
122
|
+
unless parameter_match.begin(0) == offset
|
|
123
|
+
raise ParseError, "Invalid media range parameters: #{parameters_string[offset..].inspect}"
|
|
124
|
+
end
|
|
125
|
+
offset = parameter_match.end(0)
|
|
126
|
+
|
|
127
|
+
if key.casecmp?("q")
|
|
128
|
+
if quoted_value || parameters.key?("q") || !value.match?(/\A(?:#{QVALUE})\z/)
|
|
129
|
+
raise ParseError, "Invalid quality factor: #{value.inspect}"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
key = "q"
|
|
133
|
+
end
|
|
134
|
+
|
|
119
135
|
if quoted_value
|
|
120
136
|
value = QuotedString.unquote(quoted_value)
|
|
121
137
|
end
|
|
@@ -123,6 +139,14 @@ module Protocol
|
|
|
123
139
|
parameters[key] = value
|
|
124
140
|
end
|
|
125
141
|
|
|
142
|
+
unless offset == parameters_string.length
|
|
143
|
+
raise ParseError, "Invalid media range parameters: #{parameters_string[offset..].inspect}"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
if (type.include?("*") && type != "*") || (subtype.include?("*") && subtype != "*") || (type == "*" && subtype != "*")
|
|
147
|
+
raise ParseError, "Invalid wildcards in media range: #{type}/#{subtype}"
|
|
148
|
+
end
|
|
149
|
+
|
|
126
150
|
return MediaRange.new(type, subtype, parameters)
|
|
127
151
|
else
|
|
128
152
|
raise ParseError, "Invalid media type: #{value.inspect}"
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2019-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
|
-
require_relative "multiple"
|
|
7
6
|
require_relative "../cookie"
|
|
8
7
|
|
|
9
8
|
module Protocol
|
|
@@ -12,7 +11,40 @@ module Protocol
|
|
|
12
11
|
# The `cookie` header contains stored HTTP cookies previously sent by the server with the `set-cookie` header.
|
|
13
12
|
#
|
|
14
13
|
# It is used by clients to send key-value pairs representing stored cookies back to the server.
|
|
15
|
-
|
|
14
|
+
# Multiple cookies within a single `Cookie` header are joined with `"; "` per RFC 6265.
|
|
15
|
+
class Cookie < Array
|
|
16
|
+
# Parses a raw header value.
|
|
17
|
+
#
|
|
18
|
+
# @parameter value [String] a single raw header value.
|
|
19
|
+
# @returns [Cookie] a new instance containing the parsed value.
|
|
20
|
+
def self.parse(value)
|
|
21
|
+
self.new([value])
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Coerces a value into a parsed header object.
|
|
25
|
+
#
|
|
26
|
+
# @parameter value [String | Array] the value to coerce.
|
|
27
|
+
# @returns [Cookie] a parsed header object.
|
|
28
|
+
def self.coerce(value)
|
|
29
|
+
case value
|
|
30
|
+
when Array
|
|
31
|
+
self.new(value.map(&:to_s))
|
|
32
|
+
else
|
|
33
|
+
self.parse(value.to_s)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Initializes the cookie header with the given values.
|
|
38
|
+
#
|
|
39
|
+
# @parameter value [Array | Nil] an array of cookie strings, or `nil` for an empty header.
|
|
40
|
+
def initialize(value = nil)
|
|
41
|
+
super()
|
|
42
|
+
|
|
43
|
+
if value
|
|
44
|
+
self.concat(value)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
16
48
|
# Parses the `cookie` header into a hash of cookie names and their corresponding cookie objects.
|
|
17
49
|
#
|
|
18
50
|
# @returns [Hash(String, HTTP::Cookie)] a hash where keys are cookie names and values are {HTTP::Cookie} objects.
|
|
@@ -24,9 +56,9 @@ module Protocol
|
|
|
24
56
|
cookies.map{|cookie| [cookie.name, cookie]}.to_h
|
|
25
57
|
end
|
|
26
58
|
|
|
27
|
-
# Serializes the `cookie` header by joining individual cookie strings with
|
|
59
|
+
# Serializes the `cookie` header by joining individual cookie strings with `"; "` per RFC 6265.
|
|
28
60
|
def to_s
|
|
29
|
-
join(";")
|
|
61
|
+
join("; ")
|
|
30
62
|
end
|
|
31
63
|
|
|
32
64
|
# Whether this header is acceptable in HTTP trailers.
|
|
@@ -36,12 +68,9 @@ module Protocol
|
|
|
36
68
|
false
|
|
37
69
|
end
|
|
38
70
|
end
|
|
39
|
-
|
|
40
|
-
# The `set-cookie` header sends cookies from the server to the user agent.
|
|
41
|
-
#
|
|
42
|
-
# It is used to store cookies on the client side, which are then sent back to the server in subsequent requests using the `cookie` header.
|
|
43
|
-
class SetCookie < Cookie
|
|
44
|
-
end
|
|
45
71
|
end
|
|
46
72
|
end
|
|
47
73
|
end
|
|
74
|
+
|
|
75
|
+
# Preserve the existing behavior where requiring this file also defines SetCookie.
|
|
76
|
+
require_relative "set_cookie"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2019-2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
require_relative "multiple"
|
|
7
|
+
require_relative "../cookie"
|
|
8
|
+
|
|
9
|
+
module Protocol
|
|
10
|
+
module HTTP
|
|
11
|
+
module Header
|
|
12
|
+
# The `set-cookie` header sends cookies from the server to the user agent.
|
|
13
|
+
#
|
|
14
|
+
# Each `Set-Cookie` header must be a separate header field — they cannot be combined.
|
|
15
|
+
# It is used to store cookies on the client side, which are then sent back to the server
|
|
16
|
+
# in subsequent requests using the `cookie` header.
|
|
17
|
+
class SetCookie < Multiple
|
|
18
|
+
# Parses the `set-cookie` headers into a hash of cookie names and their corresponding cookie objects.
|
|
19
|
+
#
|
|
20
|
+
# @returns [Hash(String, HTTP::Cookie)] a hash where keys are cookie names and values are {HTTP::Cookie} objects.
|
|
21
|
+
def to_h
|
|
22
|
+
cookies = self.collect do |string|
|
|
23
|
+
HTTP::Cookie.parse(string)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
cookies.map{|cookie| [cookie.name, cookie]}.to_h
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Whether this header is acceptable in HTTP trailers.
|
|
30
|
+
# @returns [Boolean] `false`, as set-cookie headers are needed during initial response processing.
|
|
31
|
+
def self.trailer?
|
|
32
|
+
false
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -9,6 +9,7 @@ require_relative "header/split"
|
|
|
9
9
|
require_relative "header/multiple"
|
|
10
10
|
|
|
11
11
|
require_relative "header/cookie"
|
|
12
|
+
require_relative "header/set_cookie"
|
|
12
13
|
require_relative "header/connection"
|
|
13
14
|
require_relative "header/cache_control"
|
|
14
15
|
require_relative "header/etag"
|
|
@@ -300,7 +301,13 @@ module Protocol
|
|
|
300
301
|
@indexed[key] = value
|
|
301
302
|
end
|
|
302
303
|
|
|
303
|
-
|
|
304
|
+
if value.is_a?(Multiple)
|
|
305
|
+
value.each do |v|
|
|
306
|
+
@fields << [key, v.to_s]
|
|
307
|
+
end
|
|
308
|
+
else
|
|
309
|
+
@fields << [key, value.to_s]
|
|
310
|
+
end
|
|
304
311
|
end
|
|
305
312
|
|
|
306
313
|
# Get the value of the specified header key.
|
data/readme.md
CHANGED
|
@@ -30,6 +30,11 @@ Please see the [project documentation](https://socketry.github.io/protocol-http/
|
|
|
30
30
|
|
|
31
31
|
Please see the [project releases](https://socketry.github.io/protocol-http/releases/index) for all releases.
|
|
32
32
|
|
|
33
|
+
### v0.65.0
|
|
34
|
+
|
|
35
|
+
- Improve `Accept` header parsing for quoted pairs, malformed parameters, invalid wildcards, and invalid quality factors.
|
|
36
|
+
- Emit multiple `Set-Cookie` values as separate header fields and delimit combined `Cookie` values with a space after each semicolon.
|
|
37
|
+
|
|
33
38
|
### v0.64.0
|
|
34
39
|
|
|
35
40
|
- Add `Protocol::HTTP::Request#rewind!` and `#retry!` for preparing requests to be sent again.
|
|
@@ -71,14 +76,6 @@ Please see the [project releases](https://socketry.github.io/protocol-http/relea
|
|
|
71
76
|
- Introduce `Protocol::HTTP::InvalidTrailerError` which is raised when a trailer header is not allowed by the current policy.
|
|
72
77
|
- **Breaking**: `Headers#each` now yields parsed values according to the current policy. For the previous behaviour, use `Headers#fields`.
|
|
73
78
|
|
|
74
|
-
### v0.56.0
|
|
75
|
-
|
|
76
|
-
- Introduce `Header::*.parse(value)` which parses a raw header value string into a header instance.
|
|
77
|
-
- Introduce `Header::*.coerce(value)` which coerces any value (`String`, `Array`, etc.) into a header instance with normalization.
|
|
78
|
-
- `Header::*#initialize` now accepts arrays without normalization for efficiency, or strings for backward compatibility.
|
|
79
|
-
- Update `Headers#[]=` to use `coerce(value)` for smart conversion of user input.
|
|
80
|
-
- Normalization (e.g., lowercasing) is applied by `parse`, `coerce`, and `<<` methods, but not by `new` when given arrays.
|
|
81
|
-
|
|
82
79
|
## See Also
|
|
83
80
|
|
|
84
81
|
- [protocol-http1](https://github.com/socketry/protocol-http1) — HTTP/1 client/server implementation using this
|
data/releases.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v0.65.0
|
|
4
|
+
|
|
5
|
+
- Improve `Accept` header parsing for quoted pairs, malformed parameters, invalid wildcards, and invalid quality factors.
|
|
6
|
+
- Emit multiple `Set-Cookie` values as separate header fields and delimit combined `Cookie` values with a space after each semicolon.
|
|
7
|
+
|
|
3
8
|
## v0.64.0
|
|
4
9
|
|
|
5
10
|
- Add `Protocol::HTTP::Request#rewind!` and `#retry!` for preparing requests to be sent again.
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: protocol-http
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.65.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -98,6 +98,7 @@ files:
|
|
|
98
98
|
- lib/protocol/http/header/multiple.rb
|
|
99
99
|
- lib/protocol/http/header/priority.rb
|
|
100
100
|
- lib/protocol/http/header/server_timing.rb
|
|
101
|
+
- lib/protocol/http/header/set_cookie.rb
|
|
101
102
|
- lib/protocol/http/header/split.rb
|
|
102
103
|
- lib/protocol/http/header/te.rb
|
|
103
104
|
- lib/protocol/http/header/trailer.rb
|
metadata.gz.sig
CHANGED
|
Binary file
|