httpi 4.0.1 → 4.0.3

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: 70c75f8e865f40f9218b34d091ab64aad2656467fff356ac18e2530b70dc52d7
4
- data.tar.gz: fb86901d88b603911f98d1dbcad0132a0c3f6c28ce3d7b1640ce5b84f7524659
3
+ metadata.gz: 6e611d4cea80f9c190772591306f7f355159f41076db623b2663eef371780e0f
4
+ data.tar.gz: 7c2c1eb582c93bc498c301f85e38d83c7917ca40f65724f646f360d93c727dd4
5
5
  SHA512:
6
- metadata.gz: 4eddf2bd30c64892ec8bc478e5774382030a829b58450a7e0b2266ebdba4f7b01ead27315253c56ba454addc9c7a6112b77f553684e35d143e06397c51de5389
7
- data.tar.gz: 5b497936201359ed9b45df8486875bb6be8706fedeeed5ec7d7b43a0c15555cff46e3a7fc48a50b1970a76e2dae202eef591ccf74325caf8d5faf77a09f46789
6
+ metadata.gz: a00241efcfcae64a4ade2fb2b3f07dce9da9524591f6dc90d76ac72caa57062246e904732835afb20794d2d307aced826f18c1e5eb8c968e93c898bdc1f017d7
7
+ data.tar.gz: 32806a0e4bd9174ea7184b231740623a1dbdef4eb7c9463c86140c6ec48d043793027453d8f40f303321cb855ff70025d823f8a477c1c0449e262fd6e4812bac
@@ -3,7 +3,7 @@
3
3
  {
4
4
  "name": "Ruby",
5
5
  // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
6
- "image": "mcr.microsoft.com/devcontainers/ruby:1-3.2-bullseye"
6
+ "image": "mcr.microsoft.com/devcontainers/ruby:1-3.3-bullseye"
7
7
 
8
8
  // Features to add to the dev container. More info: https://containers.dev/features.
9
9
  // "features": {},
data/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  * Add your changelog entry here
4
4
 
5
+ ### 4.0.3 (2024-07-06)
6
+
7
+ * Allow use with rack 3.1
8
+
9
+ ### 4.0.2 (2024-06-13)
10
+
11
+ * Don't change http header casing by @pcai in https://github.com/savonrb/httpi/pull/249
12
+
5
13
  ### 4.0.1 (2024-02-16)
6
14
 
7
15
  HTTPI is officially in maintenance mode. Our emphasis will now be on bugs, security fixes, and compatibility with the wider ecosystem. See [this issue](https://github.com/savonrb/httpi/issues/238) for details.
data/httpi.gemspec CHANGED
@@ -21,12 +21,12 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.license = 'MIT'
23
23
 
24
- s.add_dependency 'rack', '>= 2.0', '< 3.1'
24
+ s.add_dependency 'rack', '>= 2.0', '< 4'
25
25
  s.add_dependency 'nkf'
26
26
  s.add_dependency 'base64'
27
27
  s.add_dependency 'mutex_m'
28
28
 
29
- s.add_development_dependency 'rubyntlm', '~> 0.3.2'
29
+ s.add_development_dependency 'rubyntlm', '~> 0.6.4'
30
30
  s.add_development_dependency 'rake', '~> 13.0'
31
31
  s.add_development_dependency 'rspec', '~> 3.5'
32
32
  s.add_development_dependency 'mocha', '~> 0.13'
data/lib/httpi/utils.rb CHANGED
@@ -3,236 +3,93 @@
3
3
  # library for it.
4
4
  module HTTPI
5
5
  module Utils
6
- # HTTPI::Utils::Headers is a Hash subclass that downcases all keys.
6
+ # A case-insensitive Hash that preserves the original case of a
7
+ # header when set.
8
+ #
7
9
  class Headers < Hash
8
- KNOWN_HEADERS = {}
9
- %w(
10
- Accept-CH
11
- Accept-Patch
12
- Accept-Ranges
13
- Access-Control-Allow-Credentials
14
- Access-Control-Allow-Headers
15
- Access-Control-Allow-Methods
16
- Access-Control-Allow-Origin
17
- Access-Control-Expose-Headers
18
- Access-Control-Max-Age
19
- Age
20
- Allow
21
- Alt-Svc
22
- Cache-Control
23
- Connection
24
- Content-Disposition
25
- Content-Encoding
26
- Content-Language
27
- Content-Length
28
- Content-Location
29
- Content-MD5
30
- Content-Range
31
- Content-Security-Policy
32
- Content-Security-Policy-Report-Only
33
- Content-Type
34
- Date
35
- Delta-Base
36
- ETag
37
- Expect-CT
38
- Expires
39
- Feature-Policy
40
- IM
41
- Last-Modified
42
- Link
43
- Location
44
- NEL
45
- P3P
46
- Permissions-Policy
47
- Pragma
48
- Preference-Applied
49
- Proxy-Authenticate
50
- Public-Key-Pins
51
- Referrer-Policy
52
- Refresh
53
- Report-To
54
- Retry-After
55
- Server
56
- Set-Cookie
57
- Status
58
- Strict-Transport-Security
59
- Timing-Allow-Origin
60
- Tk
61
- Trailer
62
- Transfer-Encoding
63
- Upgrade
64
- Vary
65
- Via
66
- WWW-Authenticate
67
- Warning
68
- X-Cascade
69
- X-Content-Duration
70
- X-Content-Security-Policy
71
- X-Content-Type-Options
72
- X-Correlation-ID
73
- X-Correlation-Id
74
- X-Download-Options
75
- X-Frame-Options
76
- X-Permitted-Cross-Domain-Policies
77
- X-Powered-By
78
- X-Redirect-By
79
- X-Request-ID
80
- X-Request-Id
81
- X-Runtime
82
- X-UA-Compatible
83
- X-WebKit-CS
84
- X-XSS-Protection
85
- ).each do |str|
86
- downcased = str.downcase.freeze
87
- KNOWN_HEADERS[str] = KNOWN_HEADERS[downcased] = downcased
88
- end
89
-
90
- def self.[](*items)
91
- if items.length % 2 != 0
92
- if items.length == 1 && items.first.is_a?(Hash)
93
- new.merge!(items.first)
94
- else
95
- raise ArgumentError, "odd number of arguments for Utils::Headers"
96
- end
10
+ def self.[](headers)
11
+ if headers.is_a?(Headers) && !headers.frozen?
12
+ return headers
97
13
  else
98
- hash = new
99
- loop do
100
- break if items.length == 0
101
- key = items.shift
102
- value = items.shift
103
- hash[key] = value
104
- end
105
- hash
14
+ return self.new(headers)
106
15
  end
107
16
  end
108
17
 
109
- def [](key)
110
- super(downcase_key(key))
111
- end
112
-
113
- def []=(key, value)
114
- super(KNOWN_HEADERS[key] || key.downcase.freeze, value)
115
- end
116
- alias store []=
117
-
118
- def assoc(key)
119
- super(downcase_key(key))
120
- end
121
-
122
- def compare_by_identity
123
- raise TypeError, "Utils::Headers cannot compare by identity, use regular Hash"
124
- end
125
-
126
- def delete(key)
127
- super(downcase_key(key))
128
- end
129
-
130
- def dig(key, *a)
131
- super(downcase_key(key), *a)
18
+ def initialize(hash = {})
19
+ super()
20
+ @names = {}
21
+ hash.each { |k, v| self[k] = v }
132
22
  end
133
23
 
134
- def fetch(key, *default, &block)
135
- key = downcase_key(key)
24
+ # on dup/clone, we need to duplicate @names hash
25
+ def initialize_copy(other)
136
26
  super
27
+ @names = other.names.dup
137
28
  end
138
29
 
139
- def fetch_values(*a)
140
- super(*a.map!{|key| downcase_key(key)})
30
+ # on clear, we need to clear @names hash
31
+ def clear
32
+ super
33
+ @names.clear
141
34
  end
142
35
 
143
- def has_key?(key)
144
- super(downcase_key(key))
36
+ def each
37
+ super do |k, v|
38
+ yield(k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v)
39
+ end
145
40
  end
146
- alias include? has_key?
147
- alias key? has_key?
148
- alias member? has_key?
149
41
 
150
- def invert
151
- hash = self.class.new
152
- each{|key, value| hash[value] = key}
42
+ def to_hash
43
+ hash = {}
44
+ each { |k, v| hash[k] = v }
153
45
  hash
154
46
  end
155
47
 
156
- def merge(hash, &block)
157
- dup.merge!(hash, &block)
48
+ def [](k)
49
+ super(k) || super(@names[k.downcase])
158
50
  end
159
51
 
160
- def reject(&block)
161
- hash = dup
162
- hash.reject!(&block)
163
- hash
52
+ def []=(k, v)
53
+ canonical = k.downcase.freeze
54
+ delete k if @names[canonical] && @names[canonical] != k # .delete is expensive, don't invoke it unless necessary
55
+ @names[canonical] = k
56
+ super k, v
164
57
  end
165
58
 
166
- def replace(hash)
167
- clear
168
- update(hash)
59
+ def delete(k)
60
+ canonical = k.downcase
61
+ result = super @names.delete(canonical)
62
+ result
169
63
  end
170
64
 
171
- def select(&block)
172
- hash = dup
173
- hash.select!(&block)
174
- hash
65
+ def include?(k)
66
+ super || @names.include?(k.downcase)
175
67
  end
176
68
 
177
- def to_proc
178
- lambda{|x| self[x]}
179
- end
69
+ alias_method :has_key?, :include?
70
+ alias_method :member?, :include?
71
+ alias_method :key?, :include?
180
72
 
181
- def transform_values(&block)
182
- dup.transform_values!(&block)
183
- end
184
-
185
- def update(hash, &block)
186
- hash.each do |key, value|
187
- self[key] = if block_given? && include?(key)
188
- block.call(key, self[key], value)
189
- else
190
- value
191
- end
192
- end
73
+ def merge!(other)
74
+ other.each { |k, v| self[k] = v }
193
75
  self
194
76
  end
195
- alias merge! update
196
77
 
197
- def values_at(*keys)
198
- keys.map{|key| self[key]}
78
+ def merge(other)
79
+ hash = dup
80
+ hash.merge! other
199
81
  end
200
82
 
201
- # :nocov:
202
- if RUBY_VERSION >= '2.5'
203
- # :nocov:
204
- def slice(*a)
205
- h = self.class.new
206
- a.each{|k| h[k] = self[k] if has_key?(k)}
207
- h
208
- end
209
-
210
- def transform_keys(&block)
211
- dup.transform_keys!(&block)
212
- end
213
-
214
- def transform_keys!
215
- hash = self.class.new
216
- each do |k, v|
217
- hash[yield k] = v
218
- end
219
- replace(hash)
220
- end
83
+ def replace(other)
84
+ clear
85
+ other.each { |k, v| self[k] = v }
86
+ self
221
87
  end
222
88
 
223
- # :nocov:
224
- if RUBY_VERSION >= '3.0'
225
- # :nocov:
226
- def except(*a)
227
- super(*a.map!{|key| downcase_key(key)})
89
+ protected
90
+ def names
91
+ @names
228
92
  end
229
- end
230
-
231
- private
232
-
233
- def downcase_key(key)
234
- key.is_a?(String) ? KNOWN_HEADERS[key] || key.downcase : key
235
- end
236
93
  end
237
94
  end
238
95
  end
data/lib/httpi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module HTTPI
2
- VERSION = '4.0.1'
2
+ VERSION = '4.0.3'
3
3
  end
@@ -215,8 +215,7 @@ describe HTTPI::Adapter::HTTPClient do
215
215
  end
216
216
  end
217
217
 
218
- # TODO: ntlm_openssl3 https://github.com/WinRb/rubyntlm/issues/57
219
- xit "supports NTLM authentication" do
218
+ it "supports NTLM authentication" do
220
219
  request = HTTPI::Request.new(@server.url + "ntlm-auth")
221
220
 
222
221
  request.auth.ntlm("tester", "vReqSoafRe5O")
@@ -118,6 +118,10 @@ describe HTTPI::Response do
118
118
  it "returns the HTTP response headers" do
119
119
  expect(response.headers).to eq HTTPI::Utils::Headers.new.merge({ "Content-Type" => "application/dime" })
120
120
  end
121
+
122
+ it "preserves casing" do
123
+ expect(response.headers.keys).to eq ["Content-Type"]
124
+ end
121
125
  end
122
126
 
123
127
  describe "#body" do
@@ -82,7 +82,8 @@ describe HTTPI::Adapter::Curb do
82
82
  expect(response.body).to eq("basic-auth")
83
83
  end
84
84
 
85
- it "supports digest authentication" do
85
+ # Rack::Auth::Digest is removed in Rack 3.1
86
+ xit "supports digest authentication" do
86
87
  request = HTTPI::Request.new(@server.url + "digest-auth")
87
88
  request.auth.digest("admin", "secret")
88
89
 
@@ -79,7 +79,8 @@ describe HTTPI::Adapter::HTTPClient do
79
79
  expect(response.body).to eq("basic-auth")
80
80
  end
81
81
 
82
- it "supports digest authentication" do
82
+ # Rack::Auth::Digest is removed in Rack 3.1
83
+ xit "supports digest authentication" do
83
84
  request = HTTPI::Request.new(@server.url + "digest-auth")
84
85
  request.auth.digest("admin", "secret")
85
86
 
@@ -138,8 +138,7 @@ describe HTTPI::Adapter::NetHTTP do
138
138
  to raise_error(HTTPI::NotSupportedError, /does not support HTTP digest authentication/)
139
139
  end
140
140
 
141
- # TODO: ntlm_openssl3 https://github.com/WinRb/rubyntlm/issues/57
142
- xit "supports ntlm authentication" do
141
+ it "supports ntlm authentication" do
143
142
  request = HTTPI::Request.new(@server.url + "ntlm-auth")
144
143
  request.auth.ntlm("tester", "vReqSoafRe5O")
145
144
 
@@ -167,8 +166,7 @@ describe HTTPI::Adapter::NetHTTP do
167
166
  HTTPI::Adapter::NetHTTP.any_instance.unstub(:check_net_ntlm_version!)
168
167
  end
169
168
 
170
- # TODO: ntlm_openssl3 https://github.com/WinRb/rubyntlm/issues/57
171
- xit "does check ntlm when ntlm authentication is requested" do
169
+ it "does check ntlm when ntlm authentication is requested" do
172
170
  request = HTTPI::Request.new(@server.url + "ntlm-auth")
173
171
  request.auth.ntlm("tester", "vReqSoafRe5O")
174
172
 
@@ -185,8 +183,7 @@ describe HTTPI::Adapter::NetHTTP do
185
183
  HTTPI::Adapter::NetHTTP.any_instance.unstub(:ntlm_version)
186
184
  end
187
185
 
188
- # TODO: ntlm_openssl3 https://github.com/WinRb/rubyntlm/issues/57
189
- xit "does not crash when authenticate header is missing (on second request)" do
186
+ it "does not crash when authenticate header is missing (on second request)" do
190
187
  request = HTTPI::Request.new(@server.url + "ntlm-auth")
191
188
  request.auth.ntlm("tester", "vReqSoafRe5O")
192
189
 
@@ -78,19 +78,10 @@ class IntegrationServer
78
78
  end
79
79
 
80
80
  map "/digest-auth" do
81
- unprotected_app = lambda { |env|
81
+ # Rack::Auth::Digest is removed in Rack 3.1
82
+ run lambda { |env|
82
83
  IntegrationServer.respond_with "digest-auth"
83
84
  }
84
-
85
- realm = 'digest-realm'
86
- app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username|
87
- username == 'admin' ? Digest::MD5.hexdigest("admin:#{realm}:secret") : nil
88
- end
89
- app.realm = realm
90
- app.opaque = 'this-should-be-secret'
91
- app.passwords_hashed = true
92
-
93
- run app
94
85
  end
95
86
 
96
87
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpi
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Harrington
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-02-16 00:00:00.000000000 Z
12
+ date: 2024-07-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -20,7 +20,7 @@ dependencies:
20
20
  version: '2.0'
21
21
  - - "<"
22
22
  - !ruby/object:Gem::Version
23
- version: '3.1'
23
+ version: '4'
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
@@ -30,7 +30,7 @@ dependencies:
30
30
  version: '2.0'
31
31
  - - "<"
32
32
  - !ruby/object:Gem::Version
33
- version: '3.1'
33
+ version: '4'
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: nkf
36
36
  requirement: !ruby/object:Gem::Requirement
@@ -79,14 +79,14 @@ dependencies:
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.3.2
82
+ version: 0.6.4
83
83
  type: :development
84
84
  prerelease: false
85
85
  version_requirements: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.3.2
89
+ version: 0.6.4
90
90
  - !ruby/object:Gem::Dependency
91
91
  name: rake
92
92
  requirement: !ruby/object:Gem::Requirement
@@ -262,7 +262,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
262
262
  - !ruby/object:Gem::Version
263
263
  version: '0'
264
264
  requirements: []
265
- rubygems_version: 3.4.10
265
+ rubygems_version: 3.5.3
266
266
  signing_key:
267
267
  specification_version: 4
268
268
  summary: Common interface for Ruby's HTTP libraries