protocol-http 0.47.1 → 0.48.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: d8281f44eb94360f117cba9ef4770386d57b72049ec2200e45041f7b93193147
4
- data.tar.gz: 0e93ed313a1a91971568b575b58db52857f15da6a92fe8764294f2b6ef2335c6
3
+ metadata.gz: 183d448e1ac64631b122da7f8a34c4f506ef5792efdffad906077d206cb7cdd9
4
+ data.tar.gz: 848e8e30617a473bd955419605a06625a9dd3735e42239fd11d5fbcfdbe5ca86
5
5
  SHA512:
6
- metadata.gz: 4f5765e41ef7706b20f8c82812099dc5e79fa6f5c9036332688e5dde9ea0a41a52d44a2442aa33d3514f977939f70c32b40fa858179d4bada70df5b70227e7ab
7
- data.tar.gz: 8835f1c4351794d80db3c917b374648a2090c89619b9bd9deb556955a86eb230118814930d2b8d363838b49f0d2a75d7cee0f8f91bbc2393146cc8cecc9c4f68
6
+ metadata.gz: 58cfc6bf62399c067ccdd1cb5f4e3d5ff02acd3603918f4e1aaadfcb39d505f2a0ec1e60e8f3cf542f9ae615ada5363c72bd652f1513494f50b67911cbe4d6a0
7
+ data.tar.gz: 23befb46df9d7bc48928e08400dec1a11f9028bf0d3cf7549f3f2f2273d833984ea4c1ed37eaa4e68e99d255fd1df98e78c3133c9971d65488f0d06eb41d5c08
checksums.yaml.gz.sig CHANGED
Binary file
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2023, by Samuel Williams.
4
+ # Copyright, 2019-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "middleware"
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2023, by Samuel Williams.
4
+ # Copyright, 2020-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "readable"
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2023, by Samuel Williams.
4
+ # Copyright, 2019-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "middleware"
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2023, by Samuel Williams.
4
+ # Copyright, 2019-2025, by Samuel Williams.
5
5
  # Copyright, 2022, by Herrick Fang.
6
6
 
7
7
  require_relative "url"
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require_relative "split"
7
+ require_relative "quoted_string"
8
+ require_relative "../error"
9
+
10
+ module Protocol
11
+ module HTTP
12
+ module Header
13
+ # The `accept-content-type` header represents a list of content-types that the client can accept.
14
+ class Accept < Array
15
+ # Regular expression used to split values on commas, with optional surrounding whitespace, taking into account quoted strings.
16
+ SEPARATOR = /
17
+ (?: # Start non-capturing group
18
+ "[^"\\]*" # Match quoted strings (no escaping of quotes within)
19
+ | # OR
20
+ [^,"]+ # Match non-quoted strings until a comma or quote
21
+ )+
22
+ (?=,|\z) # Match until a comma or end of string
23
+ /x
24
+
25
+ ParseError = Class.new(Error)
26
+
27
+ MEDIA_RANGE = /\A(?<type>#{TOKEN})\/(?<subtype>#{TOKEN})(?<parameters>.*)\z/
28
+
29
+ PARAMETER = /\s*;\s*(?<key>#{TOKEN})=((?<value>#{TOKEN})|(?<quoted_value>#{QUOTED_STRING}))/
30
+
31
+ # A single entry in the Accept: header, which includes a mime type and associated parameters. A media range can include wild cards, but a media type is a specific type and subtype.
32
+ MediaRange = Struct.new(:type, :subtype, :parameters) do
33
+ def initialize(type, subtype = "*", parameters = {})
34
+ super(type, subtype, parameters)
35
+ end
36
+
37
+ def <=> other
38
+ other.quality_factor <=> self.quality_factor
39
+ end
40
+
41
+ private def parameters_string
42
+ return "" if parameters == nil or parameters.empty?
43
+
44
+ parameters.collect do |key, value|
45
+ ";#{key.to_s}=#{QuotedString.quote(value.to_s)}"
46
+ end.join
47
+ end
48
+
49
+ def to_s
50
+ "#{type}/#{subtype}#{parameters_string}"
51
+ end
52
+
53
+ alias to_str to_s
54
+
55
+ def quality_factor
56
+ parameters.fetch("q", 1.0).to_f
57
+ end
58
+ end
59
+
60
+ # Parse the `accept` header value into a list of content types.
61
+ #
62
+ # @parameter value [String] the value of the header.
63
+ def initialize(value = nil)
64
+ if value
65
+ super(value.scan(SEPARATOR).map(&:strip))
66
+ end
67
+ end
68
+
69
+ # Adds one or more comma-separated values to the header.
70
+ #
71
+ # The input string is split into distinct entries and appended to the array.
72
+ #
73
+ # @parameter value [String] the value or values to add, separated by commas.
74
+ def << (value)
75
+ self.concat(value.scan(SEPARATOR).map(&:strip))
76
+ end
77
+
78
+ # Serializes the stored values into a comma-separated string.
79
+ #
80
+ # @returns [String] the serialized representation of the header values.
81
+ def to_s
82
+ join(",")
83
+ end
84
+
85
+ # Parse the `accept` header.
86
+ #
87
+ # @returns [Array(Charset)] the list of content types and their associated parameters.
88
+ def media_ranges
89
+ self.map do |value|
90
+ self.parse_media_range(value)
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def parse_media_range(value)
97
+ if match = value.match(MEDIA_RANGE)
98
+ type = match[:type]
99
+ subtype = match[:subtype]
100
+ parameters = {}
101
+
102
+ match[:parameters].scan(PARAMETER) do |key, value, quoted_value|
103
+ if quoted_value
104
+ value = QuotedString.unquote(quoted_value)
105
+ end
106
+
107
+ parameters[key] = value
108
+ end
109
+
110
+ return MediaRange.new(type, subtype, parameters)
111
+ else
112
+ raise ParseError, "Invalid media type: #{value.inspect}"
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require_relative "split"
7
+ require_relative "quoted_string"
8
+ require_relative "../error"
9
+
10
+ module Protocol
11
+ module HTTP
12
+ module Header
13
+ # The `accept-charset` header represents a list of character sets that the client can accept.
14
+ class AcceptCharset < Split
15
+ ParseError = Class.new(Error)
16
+
17
+ # https://tools.ietf.org/html/rfc7231#section-5.3.3
18
+ CHARSET = /\A(?<name>#{TOKEN})(;q=(?<q>#{QVALUE}))?\z/
19
+
20
+ Charset = Struct.new(:name, :q) do
21
+ def quality_factor
22
+ (q || 1.0).to_f
23
+ end
24
+
25
+ def <=> other
26
+ other.quality_factor <=> self.quality_factor
27
+ end
28
+ end
29
+
30
+ # Parse the `accept-charset` header value into a list of character sets.
31
+ #
32
+ # @returns [Array(Charset)] the list of character sets and their associated quality factors.
33
+ def charsets
34
+ self.map do |value|
35
+ if match = value.match(CHARSET)
36
+ Charset.new(match[:name], match[:q])
37
+ else
38
+ raise ParseError.new("Could not parse character set: #{value.inspect}")
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require_relative "split"
7
+ require_relative "quoted_string"
8
+ require_relative "../error"
9
+
10
+ module Protocol
11
+ module HTTP
12
+ module Header
13
+ # The `accept-encoding` header represents a list of encodings that the client can accept.
14
+ class AcceptEncoding < Split
15
+ ParseError = Class.new(Error)
16
+
17
+ # https://tools.ietf.org/html/rfc7231#section-5.3.1
18
+ QVALUE = /0(\.[0-9]{0,3})?|1(\.[0]{0,3})?/
19
+
20
+ # https://tools.ietf.org/html/rfc7231#section-5.3.4
21
+ ENCODING = /\A(?<name>#{TOKEN})(;q=(?<q>#{QVALUE}))?\z/
22
+
23
+ Encoding = Struct.new(:name, :q) do
24
+ def quality_factor
25
+ (q || 1.0).to_f
26
+ end
27
+
28
+ def <=> other
29
+ other.quality_factor <=> self.quality_factor
30
+ end
31
+ end
32
+
33
+ # Parse the `accept-encoding` header value into a list of encodings.
34
+ #
35
+ # @returns [Array(Charset)] the list of character sets and their associated quality factors.
36
+ def encodings
37
+ self.map do |value|
38
+ if match = value.match(ENCODING)
39
+ Encoding.new(match[:name], match[:q])
40
+ else
41
+ raise ParseError.new("Could not parse encoding: #{value.inspect}")
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require_relative "split"
7
+ require_relative "quoted_string"
8
+ require_relative "../error"
9
+
10
+ module Protocol
11
+ module HTTP
12
+ module Header
13
+ # The `accept-language` header represents a list of languages that the client can accept.
14
+ class AcceptLanguage < Split
15
+ ParseError = Class.new(Error)
16
+
17
+ # https://tools.ietf.org/html/rfc3066#section-2.1
18
+ NAME = /\*|[A-Z]{1,8}(-[A-Z0-9]{1,8})*/i
19
+
20
+ # https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.9
21
+ QVALUE = /0(\.[0-9]{0,6})?|1(\.[0]{0,6})?/
22
+
23
+ # https://greenbytes.de/tech/webdav/rfc7231.html#quality.values
24
+ LANGUAGE = /\A(?<name>#{NAME})(\s*;\s*q=(?<q>#{QVALUE}))?\z/
25
+
26
+ Language = Struct.new(:name, :q) do
27
+ def quality_factor
28
+ (q || 1.0).to_f
29
+ end
30
+
31
+ def <=> other
32
+ other.quality_factor <=> self.quality_factor
33
+ end
34
+ end
35
+
36
+ # Parse the `accept-language` header value into a list of languages.
37
+ #
38
+ # @returns [Array(Charset)] the list of character sets and their associated quality factors.
39
+ def languages
40
+ self.map do |value|
41
+ if match = value.match(LANGUAGE)
42
+ Language.new(match[:name], match[:q])
43
+ else
44
+ raise ParseError.new("Could not parse language: #{value.inspect}")
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2023, by Samuel Williams.
4
+ # Copyright, 2020-2025, by Samuel Williams.
5
5
  # Copyright, 2023, by Thomas Morgan.
6
6
 
7
7
  require_relative "split"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2024, by Samuel Williams.
4
+ # Copyright, 2019-2025, by Samuel Williams.
5
5
  # Copyright, 2024, by Thomas Morgan.
6
6
 
7
7
  require_relative "split"
@@ -53,4 +53,4 @@ module Protocol
53
53
  end
54
54
  end
55
55
  end
56
- end
56
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2023, by Samuel Williams.
4
+ # Copyright, 2019-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "multiple"
7
7
  require_relative "../cookie"
@@ -32,4 +32,4 @@ module Protocol
32
32
  end
33
33
  end
34
34
  end
35
- end
35
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2023, by Samuel Williams.
4
+ # Copyright, 2020-2025, by Samuel Williams.
5
5
 
6
6
  module Protocol
7
7
  module HTTP
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2023, by Samuel Williams.
4
+ # Copyright, 2020-2025, by Samuel Williams.
5
5
  # Copyright, 2023, by Thomas Morgan.
6
6
 
7
7
  require_relative "split"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2023, by Samuel Williams.
4
+ # Copyright, 2019-2025, by Samuel Williams.
5
5
 
6
6
  module Protocol
7
7
  module HTTP
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ module Protocol
7
+ module HTTP
8
+ module Header
9
+ # According to https://tools.ietf.org/html/rfc7231#appendix-C
10
+ TOKEN = /[!#$%&'*+\-.^_`|~0-9A-Z]+/i
11
+
12
+ QUOTED_STRING = /"(?:.(?!(?<!\\)"))*.?"/
13
+
14
+ # https://tools.ietf.org/html/rfc7231#section-5.3.1
15
+ QVALUE = /0(\.[0-9]{0,3})?|1(\.[0]{0,3})?/
16
+
17
+ # Handling of HTTP quoted strings.
18
+ module QuotedString
19
+ # Unquote a "quoted-string" value according to <https://tools.ietf.org/html/rfc7230#section-3.2.6>. It should already match the QUOTED_STRING pattern above by the parser.
20
+ def self.unquote(value, normalize_whitespace = true)
21
+ value = value[1...-1]
22
+
23
+ value.gsub!(/\\(.)/, '\1')
24
+
25
+ if normalize_whitespace
26
+ # LWS = [CRLF] 1*( SP | HT )
27
+ value.gsub!(/[\r\n]+\s+/, " ")
28
+ end
29
+
30
+ return value
31
+ end
32
+
33
+ QUOTES_REQUIRED = /[()<>@,;:\\"\/\[\]?={} \t]/
34
+
35
+ # Quote a string for HTTP header values if required.
36
+ #
37
+ # @raises [ArgumentError] if the value contains invalid characters like control characters or newlines.
38
+ def self.quote(value, force = false)
39
+ # Check if quoting is required:
40
+ if value =~ QUOTES_REQUIRED or force
41
+ "\"#{value.gsub(/["\\]/, '\\\\\0')}\""
42
+ else
43
+ value
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2023, by Samuel Williams.
4
+ # Copyright, 2019-2025, by Samuel Williams.
5
5
 
6
6
  module Protocol
7
7
  module HTTP
@@ -30,7 +30,7 @@ module Protocol
30
30
  #
31
31
  # @parameter value [String] the value or values to add, separated by commas.
32
32
  def << value
33
- self.push(*value.split(COMMA))
33
+ self.concat(value.split(COMMA))
34
34
  end
35
35
 
36
36
  # Serializes the stored values into a comma-separated string.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2023, by Samuel Williams.
4
+ # Copyright, 2020-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "split"
7
7
 
@@ -28,4 +28,4 @@ module Protocol
28
28
  end
29
29
  end
30
30
  end
31
- end
31
+ end
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2024, by Samuel Williams.
4
+ # Copyright, 2018-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "header/split"
7
7
  require_relative "header/multiple"
8
+
8
9
  require_relative "header/cookie"
9
10
  require_relative "header/connection"
10
11
  require_relative "header/cache_control"
@@ -15,6 +16,11 @@ require_relative "header/authorization"
15
16
  require_relative "header/date"
16
17
  require_relative "header/priority"
17
18
 
19
+ require_relative "header/accept"
20
+ require_relative "header/accept_charset"
21
+ require_relative "header/accept_encoding"
22
+ require_relative "header/accept_language"
23
+
18
24
  module Protocol
19
25
  module HTTP
20
26
  # @namespace
@@ -277,6 +283,12 @@ module Protocol
277
283
  "last-modified" => Header::Date,
278
284
  "if-modified-since" => Header::Date,
279
285
  "if-unmodified-since" => Header::Date,
286
+
287
+ # Accept headers:
288
+ "accept" => Header::Accept,
289
+ "accept-charset" => Header::AcceptCharset,
290
+ "accept-encoding" => Header::AcceptEncoding,
291
+ "accept-language" => Header::AcceptLanguage,
280
292
  }.tap{|hash| hash.default = Split}
281
293
 
282
294
  # Delete all header values for the given key, and return the merged value.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2023, by Samuel Williams.
4
+ # Copyright, 2019-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "methods"
7
7
  require_relative "headers"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2017-2024, by Samuel Williams.
4
+ # Copyright, 2024-2025, by Samuel Williams.
5
5
 
6
6
  module Protocol
7
7
  module HTTP
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2023, by Samuel Williams.
4
+ # Copyright, 2018-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "url"
7
7
 
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Protocol
7
7
  module HTTP
8
- VERSION = "0.47.1"
8
+ VERSION = "0.48.0"
9
9
  end
10
10
  end
data/license.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
 
3
- Copyright, 2018-2024, by Samuel Williams.
3
+ Copyright, 2018-2025, by Samuel Williams.
4
4
  Copyright, 2019, by Yuta Iwama.
5
5
  Copyright, 2020, by Olle Jonsson.
6
6
  Copyright, 2020, by Bryan Powell.
data/readme.md CHANGED
@@ -24,6 +24,10 @@ Please see the [project documentation](https://socketry.github.io/protocol-http/
24
24
 
25
25
  Please see the [project releases](https://socketry.github.io/protocol-http/releases/index) for all releases.
26
26
 
27
+ ### v0.48.0
28
+
29
+ - Add support for parsing `accept`, `accept-charset`, `accept-encoding` and `accept-language` headers into structured values.
30
+
27
31
  ### v0.46.0
28
32
 
29
33
  - Add support for `priority:` header.
data/releases.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Releases
2
2
 
3
+ ## v0.48.0
4
+
5
+ - Add support for parsing `accept`, `accept-charset`, `accept-encoding` and `accept-language` headers into structured values.
6
+
3
7
  ## v0.46.0
4
8
 
5
9
  - Add support for `priority:` header.
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.47.1
4
+ version: 0.48.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -15,7 +15,6 @@ authors:
15
15
  - Marcelo Junior
16
16
  - Olle Jonsson
17
17
  - Yuta Iwama
18
- autorequire:
19
18
  bindir: bin
20
19
  cert_chain:
21
20
  - |
@@ -47,10 +46,8 @@ cert_chain:
47
46
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
48
47
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
49
48
  -----END CERTIFICATE-----
50
- date: 2024-12-04 00:00:00.000000000 Z
49
+ date: 2025-01-24 00:00:00.000000000 Z
51
50
  dependencies: []
52
- description:
53
- email:
54
51
  executables: []
55
52
  extensions: []
56
53
  extra_rdoc_files: []
@@ -75,6 +72,10 @@ files:
75
72
  - lib/protocol/http/content_encoding.rb
76
73
  - lib/protocol/http/cookie.rb
77
74
  - lib/protocol/http/error.rb
75
+ - lib/protocol/http/header/accept.rb
76
+ - lib/protocol/http/header/accept_charset.rb
77
+ - lib/protocol/http/header/accept_encoding.rb
78
+ - lib/protocol/http/header/accept_language.rb
78
79
  - lib/protocol/http/header/authorization.rb
79
80
  - lib/protocol/http/header/cache_control.rb
80
81
  - lib/protocol/http/header/connection.rb
@@ -84,6 +85,7 @@ files:
84
85
  - lib/protocol/http/header/etags.rb
85
86
  - lib/protocol/http/header/multiple.rb
86
87
  - lib/protocol/http/header/priority.rb
88
+ - lib/protocol/http/header/quoted_string.rb
87
89
  - lib/protocol/http/header/split.rb
88
90
  - lib/protocol/http/header/vary.rb
89
91
  - lib/protocol/http/headers.rb
@@ -105,7 +107,6 @@ licenses:
105
107
  metadata:
106
108
  documentation_uri: https://socketry.github.io/protocol-http/
107
109
  source_code_uri: https://github.com/socketry/protocol-http.git
108
- post_install_message:
109
110
  rdoc_options: []
110
111
  require_paths:
111
112
  - lib
@@ -120,8 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
121
  - !ruby/object:Gem::Version
121
122
  version: '0'
122
123
  requirements: []
123
- rubygems_version: 3.5.22
124
- signing_key:
124
+ rubygems_version: 3.6.2
125
125
  specification_version: 4
126
126
  summary: Provides abstractions to handle HTTP protocols.
127
127
  test_files: []
metadata.gz.sig CHANGED
Binary file