protocol-http 0.54.0 → 0.56.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/context/index.yaml +0 -8
- data/lib/protocol/http/body/stream.rb +3 -2
- data/lib/protocol/http/cookie.rb +32 -29
- data/lib/protocol/http/header/accept.rb +12 -12
- data/lib/protocol/http/header/accept_charset.rb +1 -1
- data/lib/protocol/http/header/accept_encoding.rb +1 -1
- data/lib/protocol/http/header/accept_language.rb +1 -1
- data/lib/protocol/http/header/authorization.rb +18 -2
- data/lib/protocol/http/header/cache_control.rb +33 -4
- data/lib/protocol/http/header/connection.rb +33 -4
- data/lib/protocol/http/header/date.rb +18 -2
- data/lib/protocol/http/header/digest.rb +1 -1
- data/lib/protocol/http/header/etag.rb +18 -2
- data/lib/protocol/http/header/etags.rb +1 -1
- data/lib/protocol/http/header/multiple.rb +35 -6
- data/lib/protocol/http/header/priority.rb +33 -4
- data/lib/protocol/http/header/server_timing.rb +1 -1
- data/lib/protocol/http/header/split.rb +38 -9
- data/lib/protocol/http/header/te.rb +34 -5
- data/lib/protocol/http/header/transfer_encoding.rb +33 -4
- data/lib/protocol/http/header/vary.rb +34 -5
- data/lib/protocol/http/headers.rb +48 -15
- data/lib/protocol/http/quoted_string.rb +47 -0
- data/lib/protocol/http/version.rb +1 -1
- data/readme.md +18 -13
- data/releases.md +174 -0
- data.tar.gz.sig +0 -0
- metadata +3 -5
- metadata.gz.sig +0 -0
- data/lib/protocol/http/header/quoted_string.rb +0 -49
- data/lib/protocol/http/reference.rb +0 -253
- data/lib/protocol/http/url.rb +0 -149
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5409468cd5dfe153d3ab2ecc8fae839ff0a688e0d54a81aa402395e6b3de0f1e
|
|
4
|
+
data.tar.gz: 11d700efbe0ecc425438a605f09643bba5bdde1e258bb0508e34428285b209f3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 90bf1b95afe9e830249676ab82cba8306c2184dfac7b105dff9c068eb67484f5002b73ec5141a1f42177042a4016c83a118a875df36f30ab65c8aa4b9b1ed2fb
|
|
7
|
+
data.tar.gz: 43ce8ee9a1ace9ff2ae0be4d9ae90625415a504fad5162ebf7e8b1f487bab25bae0aa452260b7cd3fe00193c53835c80f730a1ca16ac142c90f827c852119497
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/context/index.yaml
CHANGED
|
@@ -20,14 +20,6 @@ files:
|
|
|
20
20
|
- path: middleware.md
|
|
21
21
|
title: Middleware
|
|
22
22
|
description: This guide explains how to build and use HTTP middleware with `Protocol::HTTP::Middleware`.
|
|
23
|
-
- path: hypertext-references.md
|
|
24
|
-
title: Hypertext References
|
|
25
|
-
description: This guide explains how to use `Protocol::HTTP::Reference` for constructing
|
|
26
|
-
and manipulating hypertext references (URLs with parameters).
|
|
27
|
-
- path: url-parsing.md
|
|
28
|
-
title: URL Parsing
|
|
29
|
-
description: This guide explains how to use `Protocol::HTTP::URL` for parsing and
|
|
30
|
-
manipulating URL components, particularly query strings and parameters.
|
|
31
23
|
- path: streaming.md
|
|
32
24
|
title: Streaming
|
|
33
25
|
description: This guide gives an overview of how to implement streaming requests
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2019-2025, by Samuel Williams.
|
|
5
5
|
# Copyright, 2023, by Genki Takiuchi.
|
|
6
|
+
# Copyright, 2025, by William T. Nelson.
|
|
6
7
|
|
|
7
8
|
require_relative "buffered"
|
|
8
9
|
|
|
9
10
|
module Protocol
|
|
10
11
|
module HTTP
|
|
11
12
|
module Body
|
|
12
|
-
# The input stream is an IO-like object which contains the raw HTTP POST data. When applicable, its external encoding must be
|
|
13
|
+
# The input stream is an IO-like object which contains the raw HTTP POST data. When applicable, its external encoding must be "ASCII-8BIT" and it must be opened in binary mode, for Ruby 1.9 compatibility. The input stream must respond to gets, each, read and rewind.
|
|
13
14
|
class Stream
|
|
14
15
|
# The default line separator, used by {gets}.
|
|
15
16
|
NEWLINE = "\n"
|
|
@@ -315,7 +316,7 @@ module Protocol
|
|
|
315
316
|
end
|
|
316
317
|
|
|
317
318
|
# Write data to the stream using {write}.
|
|
318
|
-
def <<
|
|
319
|
+
def << buffer
|
|
319
320
|
write(buffer)
|
|
320
321
|
end
|
|
321
322
|
|
data/lib/protocol/http/cookie.rb
CHANGED
|
@@ -4,59 +4,66 @@
|
|
|
4
4
|
# Copyright, 2019-2025, by Samuel Williams.
|
|
5
5
|
# Copyright, 2022, by Herrick Fang.
|
|
6
6
|
|
|
7
|
-
require_relative "
|
|
7
|
+
require_relative "quoted_string"
|
|
8
8
|
|
|
9
9
|
module Protocol
|
|
10
10
|
module HTTP
|
|
11
11
|
# Represents an individual cookie key-value pair.
|
|
12
12
|
class Cookie
|
|
13
|
+
# Valid cookie name characters according to RFC 6265.
|
|
14
|
+
# cookie-name = token (RFC 2616 defines token)
|
|
15
|
+
VALID_COOKIE_KEY = /\A#{TOKEN}\z/.freeze
|
|
16
|
+
|
|
17
|
+
# Valid cookie value characters according to RFC 6265.
|
|
18
|
+
# cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
|
|
19
|
+
# cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
|
|
20
|
+
# Excludes control chars, whitespace, DQUOTE, comma, semicolon, and backslash
|
|
21
|
+
VALID_COOKIE_VALUE = /\A[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]*\z/.freeze
|
|
22
|
+
|
|
13
23
|
# Initialize the cookie with the given name, value, and directives.
|
|
14
24
|
#
|
|
15
|
-
# @parameter name [String] The name of the
|
|
25
|
+
# @parameter name [String] The name of the cookie, e.g. "session_id".
|
|
16
26
|
# @parameter value [String] The value of the cookie, e.g. "1234".
|
|
17
27
|
# @parameter directives [Hash] The directives of the cookie, e.g. `{"path" => "/"}`.
|
|
18
|
-
|
|
28
|
+
# @raises [ArgumentError] If the name or value contains invalid characters.
|
|
29
|
+
def initialize(name, value, directives = nil)
|
|
30
|
+
unless VALID_COOKIE_KEY.match?(name)
|
|
31
|
+
raise ArgumentError, "Invalid cookie name: #{name.inspect}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
if value && !VALID_COOKIE_VALUE.match?(value)
|
|
35
|
+
raise ArgumentError, "Invalid cookie value: #{value.inspect}"
|
|
36
|
+
end
|
|
37
|
+
|
|
19
38
|
@name = name
|
|
20
39
|
@value = value
|
|
21
40
|
@directives = directives
|
|
22
41
|
end
|
|
23
42
|
|
|
24
43
|
# @attribute [String] The name of the cookie.
|
|
25
|
-
|
|
44
|
+
attr_accessor :name
|
|
26
45
|
|
|
27
46
|
# @attribute [String] The value of the cookie.
|
|
28
|
-
|
|
47
|
+
attr_accessor :value
|
|
29
48
|
|
|
30
49
|
# @attribute [Hash] The directives of the cookie.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
# Encode the name of the cookie.
|
|
34
|
-
def encoded_name
|
|
35
|
-
URL.escape(@name)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# Encode the value of the cookie.
|
|
39
|
-
def encoded_value
|
|
40
|
-
URL.escape(@value)
|
|
41
|
-
end
|
|
50
|
+
attr_accessor :directives
|
|
42
51
|
|
|
43
52
|
# Convert the cookie to a string.
|
|
44
53
|
#
|
|
45
54
|
# @returns [String] The string representation of the cookie.
|
|
46
55
|
def to_s
|
|
47
|
-
buffer = String.new
|
|
56
|
+
buffer = String.new
|
|
48
57
|
|
|
49
|
-
buffer <<
|
|
58
|
+
buffer << @name << "=" << @value
|
|
50
59
|
|
|
51
60
|
if @directives
|
|
52
|
-
@directives.
|
|
61
|
+
@directives.each do |key, value|
|
|
53
62
|
buffer << ";"
|
|
63
|
+
buffer << key
|
|
54
64
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
buffer << key << "=" << value
|
|
58
|
-
when TrueClass
|
|
59
|
-
buffer << key
|
|
65
|
+
if value != true
|
|
66
|
+
buffer << "=" << value.to_s
|
|
60
67
|
end
|
|
61
68
|
end
|
|
62
69
|
end
|
|
@@ -74,11 +81,7 @@ module Protocol
|
|
|
74
81
|
key, value = head.split("=", 2)
|
|
75
82
|
directives = self.parse_directives(directives)
|
|
76
83
|
|
|
77
|
-
self.new(
|
|
78
|
-
URL.unescape(key),
|
|
79
|
-
URL.unescape(value),
|
|
80
|
-
directives,
|
|
81
|
-
)
|
|
84
|
+
self.new(key, value, directives)
|
|
82
85
|
end
|
|
83
86
|
|
|
84
87
|
# Parse a list of strings into a hash of directives.
|
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2025, by Samuel Williams.
|
|
5
|
+
# Copyright, 2025, by William T. Nelson.
|
|
5
6
|
|
|
6
7
|
require_relative "split"
|
|
7
|
-
require_relative "quoted_string"
|
|
8
|
+
require_relative "../quoted_string"
|
|
8
9
|
require_relative "../error"
|
|
9
10
|
|
|
10
11
|
module Protocol
|
|
11
12
|
module HTTP
|
|
12
13
|
module Header
|
|
13
14
|
# The `accept-content-type` header represents a list of content-types that the client can accept.
|
|
14
|
-
class Accept <
|
|
15
|
+
class Accept < Split
|
|
15
16
|
# Regular expression used to split values on commas, with optional surrounding whitespace, taking into account quoted strings.
|
|
16
17
|
SEPARATOR = /
|
|
17
18
|
(?: # Start non-capturing group
|
|
@@ -67,27 +68,26 @@ module Protocol
|
|
|
67
68
|
end
|
|
68
69
|
end
|
|
69
70
|
|
|
70
|
-
#
|
|
71
|
+
# Parses a raw header value.
|
|
71
72
|
#
|
|
72
|
-
# @parameter value [String]
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
end
|
|
73
|
+
# @parameter value [String] a raw header value containing comma-separated media types.
|
|
74
|
+
# @returns [Accept] a new instance containing the parsed media types.
|
|
75
|
+
def self.parse(value)
|
|
76
|
+
self.new(value.scan(SEPARATOR).map(&:strip))
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
# Adds one or more comma-separated values to the header.
|
|
80
80
|
#
|
|
81
81
|
# The input string is split into distinct entries and appended to the array.
|
|
82
82
|
#
|
|
83
|
-
# @parameter value [String]
|
|
84
|
-
def <<
|
|
83
|
+
# @parameter value [String] a raw header value containing one or more media types separated by commas.
|
|
84
|
+
def << value
|
|
85
85
|
self.concat(value.scan(SEPARATOR).map(&:strip))
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
-
#
|
|
88
|
+
# Converts the parsed header value into a raw header value.
|
|
89
89
|
#
|
|
90
|
-
# @returns [String]
|
|
90
|
+
# @returns [String] a raw header value (comma-separated string).
|
|
91
91
|
def to_s
|
|
92
92
|
join(",")
|
|
93
93
|
end
|
|
@@ -15,6 +15,22 @@ module Protocol
|
|
|
15
15
|
#
|
|
16
16
|
# TODO Support other authorization mechanisms, e.g. bearer token.
|
|
17
17
|
class Authorization < String
|
|
18
|
+
# Parses a raw header value.
|
|
19
|
+
#
|
|
20
|
+
# @parameter value [String] a raw header value.
|
|
21
|
+
# @returns [Authorization] a new instance.
|
|
22
|
+
def self.parse(value)
|
|
23
|
+
self.new(value)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Coerces a value into a parsed header object.
|
|
27
|
+
#
|
|
28
|
+
# @parameter value [String] the value to coerce.
|
|
29
|
+
# @returns [Authorization] a parsed header object.
|
|
30
|
+
def self.coerce(value)
|
|
31
|
+
self.new(value.to_s)
|
|
32
|
+
end
|
|
33
|
+
|
|
18
34
|
# Splits the header into the credentials.
|
|
19
35
|
#
|
|
20
36
|
# @returns [Tuple(String, String)] The username and password.
|
|
@@ -31,8 +47,8 @@ module Protocol
|
|
|
31
47
|
strict_base64_encoded = ["#{username}:#{password}"].pack("m0")
|
|
32
48
|
|
|
33
49
|
self.new(
|
|
34
|
-
|
|
35
|
-
|
|
50
|
+
"Basic #{strict_base64_encoded}"
|
|
51
|
+
)
|
|
36
52
|
end
|
|
37
53
|
|
|
38
54
|
# Whether this header is acceptable in HTTP trailers.
|
|
@@ -44,16 +44,44 @@ module Protocol
|
|
|
44
44
|
# The `proxy-revalidate` directive is similar to `must-revalidate` but applies only to shared caches.
|
|
45
45
|
PROXY_REVALIDATE = "proxy-revalidate"
|
|
46
46
|
|
|
47
|
-
#
|
|
47
|
+
# Parses a raw header value.
|
|
48
48
|
#
|
|
49
|
-
# @parameter value [String
|
|
49
|
+
# @parameter value [String] a raw header value containing comma-separated directives.
|
|
50
|
+
# @returns [CacheControl] a new instance containing the parsed and normalized directives.
|
|
51
|
+
def self.parse(value)
|
|
52
|
+
self.new(value.downcase.split(COMMA))
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Coerces a value into a parsed header object.
|
|
56
|
+
#
|
|
57
|
+
# @parameter value [String | Array] the value to coerce.
|
|
58
|
+
# @returns [CacheControl] a parsed header object with normalized values.
|
|
59
|
+
def self.coerce(value)
|
|
60
|
+
case value
|
|
61
|
+
when Array
|
|
62
|
+
self.new(value.map(&:downcase))
|
|
63
|
+
else
|
|
64
|
+
self.parse(value.to_s)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Initializes the cache control header with the given values.
|
|
69
|
+
#
|
|
70
|
+
# @parameter value [Array | String | Nil] an array of directives, a raw header value, or `nil` for an empty header.
|
|
50
71
|
def initialize(value = nil)
|
|
51
|
-
|
|
72
|
+
if value.is_a?(Array)
|
|
73
|
+
super(value)
|
|
74
|
+
elsif value.is_a?(String)
|
|
75
|
+
super()
|
|
76
|
+
self << value
|
|
77
|
+
elsif value
|
|
78
|
+
raise ArgumentError, "Invalid value: #{value.inspect}"
|
|
79
|
+
end
|
|
52
80
|
end
|
|
53
81
|
|
|
54
82
|
# Adds a directive to the Cache-Control header. The value will be normalized to lowercase before being added.
|
|
55
83
|
#
|
|
56
|
-
# @parameter value [String]
|
|
84
|
+
# @parameter value [String] a raw header value containing directives to add.
|
|
57
85
|
def << value
|
|
58
86
|
super(value.downcase)
|
|
59
87
|
end
|
|
@@ -132,3 +160,4 @@ module Protocol
|
|
|
132
160
|
end
|
|
133
161
|
end
|
|
134
162
|
end
|
|
163
|
+
|
|
@@ -22,16 +22,44 @@ module Protocol
|
|
|
22
22
|
# The `upgrade` directive indicates that the connection should be upgraded to a different protocol, as specified in the `Upgrade` header.
|
|
23
23
|
UPGRADE = "upgrade"
|
|
24
24
|
|
|
25
|
-
#
|
|
25
|
+
# Parses a raw header value.
|
|
26
26
|
#
|
|
27
|
-
# @parameter value [String
|
|
27
|
+
# @parameter value [String] a raw header value containing comma-separated directives.
|
|
28
|
+
# @returns [Connection] a new instance with normalized (lowercase) directives.
|
|
29
|
+
def self.parse(value)
|
|
30
|
+
self.new(value.downcase.split(COMMA))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Coerces a value into a parsed header object.
|
|
34
|
+
#
|
|
35
|
+
# @parameter value [String | Array] the value to coerce.
|
|
36
|
+
# @returns [Connection] a parsed header object with normalized values.
|
|
37
|
+
def self.coerce(value)
|
|
38
|
+
case value
|
|
39
|
+
when Array
|
|
40
|
+
self.new(value.map(&:downcase))
|
|
41
|
+
else
|
|
42
|
+
self.parse(value.to_s)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Initializes the connection header with the given values.
|
|
47
|
+
#
|
|
48
|
+
# @parameter value [Array | String | Nil] an array of directives, a raw header value, or `nil` for an empty header.
|
|
28
49
|
def initialize(value = nil)
|
|
29
|
-
|
|
50
|
+
if value.is_a?(Array)
|
|
51
|
+
super(value)
|
|
52
|
+
elsif value.is_a?(String)
|
|
53
|
+
super()
|
|
54
|
+
self << value
|
|
55
|
+
elsif value
|
|
56
|
+
raise ArgumentError, "Invalid value: #{value.inspect}"
|
|
57
|
+
end
|
|
30
58
|
end
|
|
31
59
|
|
|
32
60
|
# Adds a directive to the `connection` header. The value will be normalized to lowercase before being added.
|
|
33
61
|
#
|
|
34
|
-
# @parameter value [String]
|
|
62
|
+
# @parameter value [String] a raw header value containing directives to add.
|
|
35
63
|
def << value
|
|
36
64
|
super(value.downcase)
|
|
37
65
|
end
|
|
@@ -61,3 +89,4 @@ module Protocol
|
|
|
61
89
|
end
|
|
62
90
|
end
|
|
63
91
|
end
|
|
92
|
+
|
|
@@ -12,9 +12,25 @@ module Protocol
|
|
|
12
12
|
#
|
|
13
13
|
# This header is typically included in HTTP responses and follows the format defined in RFC 9110.
|
|
14
14
|
class Date < String
|
|
15
|
-
#
|
|
15
|
+
# Parses a raw header value.
|
|
16
16
|
#
|
|
17
|
-
# @parameter value [String]
|
|
17
|
+
# @parameter value [String] a raw header value.
|
|
18
|
+
# @returns [Date] a new instance.
|
|
19
|
+
def self.parse(value)
|
|
20
|
+
self.new(value)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Coerces a value into a parsed header object.
|
|
24
|
+
#
|
|
25
|
+
# @parameter value [String] the value to coerce.
|
|
26
|
+
# @returns [Date] a parsed header object.
|
|
27
|
+
def self.coerce(value)
|
|
28
|
+
self.new(value.to_s)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Replaces the current value of the `date` header.
|
|
32
|
+
#
|
|
33
|
+
# @parameter value [String] a raw header value for the `date` header.
|
|
18
34
|
def << value
|
|
19
35
|
replace(value)
|
|
20
36
|
end
|
|
@@ -10,9 +10,25 @@ module Protocol
|
|
|
10
10
|
#
|
|
11
11
|
# The `etag` header provides a unique identifier for a specific version of a resource, typically used for cache validation or conditional requests. It can be either a strong or weak validator as defined in RFC 9110.
|
|
12
12
|
class ETag < String
|
|
13
|
-
#
|
|
13
|
+
# Parses a raw header value.
|
|
14
14
|
#
|
|
15
|
-
# @parameter value [String]
|
|
15
|
+
# @parameter value [String] a raw header value.
|
|
16
|
+
# @returns [ETag] a new instance.
|
|
17
|
+
def self.parse(value)
|
|
18
|
+
self.new(value)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Coerces a value into a parsed header object.
|
|
22
|
+
#
|
|
23
|
+
# @parameter value [String] the value to coerce.
|
|
24
|
+
# @returns [ETag] a parsed header object.
|
|
25
|
+
def self.coerce(value)
|
|
26
|
+
self.new(value.to_s)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Replaces the current value of the `etag` header.
|
|
30
|
+
#
|
|
31
|
+
# @parameter value [String] a raw header value for the `etag` header.
|
|
16
32
|
def << value
|
|
17
33
|
replace(value)
|
|
18
34
|
end
|
|
@@ -10,18 +10,47 @@ module Protocol
|
|
|
10
10
|
#
|
|
11
11
|
# This isn't a specific header but is used as a base for headers that store multiple values, such as cookies. The values are split and stored as an array internally, and serialized back to a newline-separated string when needed.
|
|
12
12
|
class Multiple < Array
|
|
13
|
-
#
|
|
13
|
+
# Parses a raw header value.
|
|
14
14
|
#
|
|
15
|
-
#
|
|
16
|
-
|
|
15
|
+
# Multiple headers receive each value as a separate header entry, so this method takes a single string value and creates a new instance containing it.
|
|
16
|
+
#
|
|
17
|
+
# @parameter value [String] a single raw header value.
|
|
18
|
+
# @returns [Multiple] a new instance containing the parsed value.
|
|
19
|
+
def self.parse(value)
|
|
20
|
+
self.new([value])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Coerces a value into a parsed header object.
|
|
24
|
+
#
|
|
25
|
+
# This method is used by the Headers class when setting values via `[]=` to convert application values into the appropriate policy type.
|
|
26
|
+
#
|
|
27
|
+
# @parameter value [String | Array] the value to coerce.
|
|
28
|
+
# @returns [Multiple] a parsed header object.
|
|
29
|
+
def self.coerce(value)
|
|
30
|
+
case value
|
|
31
|
+
when Array
|
|
32
|
+
self.new(value.map(&:to_s))
|
|
33
|
+
else
|
|
34
|
+
self.parse(value.to_s)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Initializes the multiple header with the given values.
|
|
39
|
+
#
|
|
40
|
+
# @parameter value [Array | Nil] an array of header values, or `nil` for an empty header.
|
|
41
|
+
def initialize(value = nil)
|
|
17
42
|
super()
|
|
18
43
|
|
|
19
|
-
|
|
44
|
+
if value
|
|
45
|
+
self.concat(value)
|
|
46
|
+
end
|
|
20
47
|
end
|
|
21
48
|
|
|
22
|
-
#
|
|
49
|
+
# Converts the parsed header value into a raw header value.
|
|
50
|
+
#
|
|
51
|
+
# Multiple headers are transmitted as separate header entries, so this serializes to a newline-separated string for storage.
|
|
23
52
|
#
|
|
24
|
-
# @returns [String]
|
|
53
|
+
# @returns [String] a raw header value (newline-separated string).
|
|
25
54
|
def to_s
|
|
26
55
|
join("\n")
|
|
27
56
|
end
|
|
@@ -12,16 +12,44 @@ module Protocol
|
|
|
12
12
|
#
|
|
13
13
|
# The `priority` header allows clients to express their preference for how resources should be prioritized by the server. It supports directives like `u=` to specify the urgency level of a request, and `i` to indicate whether a response can be delivered incrementally. The urgency levels range from 0 (highest priority) to 7 (lowest priority), while the `i` directive is a boolean flag.
|
|
14
14
|
class Priority < Split
|
|
15
|
-
#
|
|
15
|
+
# Parses a raw header value.
|
|
16
16
|
#
|
|
17
|
-
# @parameter value [String
|
|
17
|
+
# @parameter value [String] a raw header value containing comma-separated directives.
|
|
18
|
+
# @returns [Priority] a new instance with normalized (lowercase) directives.
|
|
19
|
+
def self.parse(value)
|
|
20
|
+
self.new(value.downcase.split(COMMA))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Coerces a value into a parsed header object.
|
|
24
|
+
#
|
|
25
|
+
# @parameter value [String | Array] the value to coerce.
|
|
26
|
+
# @returns [Priority] a parsed header object with normalized values.
|
|
27
|
+
def self.coerce(value)
|
|
28
|
+
case value
|
|
29
|
+
when Array
|
|
30
|
+
self.new(value.map(&:downcase))
|
|
31
|
+
else
|
|
32
|
+
self.parse(value.to_s)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Initializes the priority header with the given values.
|
|
37
|
+
#
|
|
38
|
+
# @parameter value [Array | String | Nil] an array of directives, a raw header value, or `nil` for an empty header.
|
|
18
39
|
def initialize(value = nil)
|
|
19
|
-
|
|
40
|
+
if value.is_a?(Array)
|
|
41
|
+
super(value)
|
|
42
|
+
elsif value.is_a?(String)
|
|
43
|
+
super()
|
|
44
|
+
self << value
|
|
45
|
+
elsif value
|
|
46
|
+
raise ArgumentError, "Invalid value: #{value.inspect}"
|
|
47
|
+
end
|
|
20
48
|
end
|
|
21
49
|
|
|
22
50
|
# Add a value to the priority header.
|
|
23
51
|
#
|
|
24
|
-
# @parameter value [String]
|
|
52
|
+
# @parameter value [String] a raw header value containing directives to add to the header.
|
|
25
53
|
def << value
|
|
26
54
|
super(value.downcase)
|
|
27
55
|
end
|
|
@@ -55,3 +83,4 @@ module Protocol
|
|
|
55
83
|
end
|
|
56
84
|
end
|
|
57
85
|
end
|
|
86
|
+
|
|
@@ -13,14 +13,43 @@ module Protocol
|
|
|
13
13
|
# Regular expression used to split values on commas, with optional surrounding whitespace.
|
|
14
14
|
COMMA = /\s*,\s*/
|
|
15
15
|
|
|
16
|
-
#
|
|
16
|
+
# Parses a raw header value.
|
|
17
17
|
#
|
|
18
|
-
#
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
# Split headers receive comma-separated values in a single header entry. This method splits the raw value into individual entries.
|
|
19
|
+
#
|
|
20
|
+
# @parameter value [String] a raw header value containing multiple entries separated by commas.
|
|
21
|
+
# @returns [Split] a new instance containing the parsed values.
|
|
22
|
+
def self.parse(value)
|
|
23
|
+
self.new(value.split(COMMA))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Coerces a value into a parsed header object.
|
|
27
|
+
#
|
|
28
|
+
# This method is used by the Headers class when setting values via `[]=` to convert application values into the appropriate policy type.
|
|
29
|
+
#
|
|
30
|
+
# @parameter value [String | Array] the value to coerce.
|
|
31
|
+
# @returns [Split] a parsed header object.
|
|
32
|
+
def self.coerce(value)
|
|
33
|
+
case value
|
|
34
|
+
when Array
|
|
35
|
+
self.new(value.map(&:to_s))
|
|
22
36
|
else
|
|
37
|
+
self.parse(value.to_s)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Initializes a `Split` header with the given values.
|
|
42
|
+
#
|
|
43
|
+
# @parameter value [Array | String | Nil] an array of values, a raw header value, or `nil` for an empty header.
|
|
44
|
+
def initialize(value = nil)
|
|
45
|
+
if value.is_a?(Array)
|
|
46
|
+
super(value)
|
|
47
|
+
elsif value.is_a?(String)
|
|
48
|
+
# Compatibility with the old constructor, prefer to use `parse` instead:
|
|
23
49
|
super()
|
|
50
|
+
self << value
|
|
51
|
+
elsif value
|
|
52
|
+
raise ArgumentError, "Invalid value: #{value.inspect}"
|
|
24
53
|
end
|
|
25
54
|
end
|
|
26
55
|
|
|
@@ -28,14 +57,14 @@ module Protocol
|
|
|
28
57
|
#
|
|
29
58
|
# The input string is split into distinct entries and appended to the array.
|
|
30
59
|
#
|
|
31
|
-
# @parameter value [String]
|
|
60
|
+
# @parameter value [String] a raw header value containing one or more values separated by commas.
|
|
32
61
|
def << value
|
|
33
62
|
self.concat(value.split(COMMA))
|
|
34
63
|
end
|
|
35
64
|
|
|
36
|
-
#
|
|
65
|
+
# Converts the parsed header value into a raw header value.
|
|
37
66
|
#
|
|
38
|
-
# @returns [String]
|
|
67
|
+
# @returns [String] a raw header value (comma-separated string).
|
|
39
68
|
def to_s
|
|
40
69
|
join(",")
|
|
41
70
|
end
|
|
@@ -47,7 +76,7 @@ module Protocol
|
|
|
47
76
|
false
|
|
48
77
|
end
|
|
49
78
|
|
|
50
|
-
|
|
79
|
+
protected
|
|
51
80
|
|
|
52
81
|
def reverse_find(&block)
|
|
53
82
|
reverse_each do |value|
|