httpi 4.0.1 → 4.0.3

Sign up to get free protection for your applications and to get access to all the features.
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