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 +4 -4
- data/.devcontainer/devcontainer.json +1 -1
- data/CHANGELOG.md +8 -0
- data/httpi.gemspec +2 -2
- data/lib/httpi/utils.rb +53 -196
- data/lib/httpi/version.rb +1 -1
- data/spec/httpi/adapter/httpclient_spec.rb +1 -2
- data/spec/httpi/response_spec.rb +4 -0
- data/spec/integration/curb_spec.rb +2 -1
- data/spec/integration/httpclient_spec.rb +2 -1
- data/spec/integration/net_http_spec.rb +3 -6
- data/spec/integration/support/application.rb +2 -11
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e611d4cea80f9c190772591306f7f355159f41076db623b2663eef371780e0f
|
4
|
+
data.tar.gz: 7c2c1eb582c93bc498c301f85e38d83c7917ca40f65724f646f360d93c727dd4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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', '<
|
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.
|
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
|
-
#
|
6
|
+
# A case-insensitive Hash that preserves the original case of a
|
7
|
+
# header when set.
|
8
|
+
#
|
7
9
|
class Headers < Hash
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
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
|
110
|
-
super(
|
111
|
-
|
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
|
-
|
135
|
-
|
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
|
-
|
140
|
-
|
30
|
+
# on clear, we need to clear @names hash
|
31
|
+
def clear
|
32
|
+
super
|
33
|
+
@names.clear
|
141
34
|
end
|
142
35
|
|
143
|
-
def
|
144
|
-
super
|
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
|
151
|
-
hash =
|
152
|
-
each{|
|
42
|
+
def to_hash
|
43
|
+
hash = {}
|
44
|
+
each { |k, v| hash[k] = v }
|
153
45
|
hash
|
154
46
|
end
|
155
47
|
|
156
|
-
def
|
157
|
-
|
48
|
+
def [](k)
|
49
|
+
super(k) || super(@names[k.downcase])
|
158
50
|
end
|
159
51
|
|
160
|
-
def
|
161
|
-
|
162
|
-
|
163
|
-
|
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
|
167
|
-
|
168
|
-
|
59
|
+
def delete(k)
|
60
|
+
canonical = k.downcase
|
61
|
+
result = super @names.delete(canonical)
|
62
|
+
result
|
169
63
|
end
|
170
64
|
|
171
|
-
def
|
172
|
-
|
173
|
-
hash.select!(&block)
|
174
|
-
hash
|
65
|
+
def include?(k)
|
66
|
+
super || @names.include?(k.downcase)
|
175
67
|
end
|
176
68
|
|
177
|
-
|
178
|
-
|
179
|
-
|
69
|
+
alias_method :has_key?, :include?
|
70
|
+
alias_method :member?, :include?
|
71
|
+
alias_method :key?, :include?
|
180
72
|
|
181
|
-
def
|
182
|
-
|
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
|
198
|
-
|
78
|
+
def merge(other)
|
79
|
+
hash = dup
|
80
|
+
hash.merge! other
|
199
81
|
end
|
200
82
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
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
|
-
|
224
|
-
|
225
|
-
|
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
@@ -215,8 +215,7 @@ describe HTTPI::Adapter::HTTPClient do
|
|
215
215
|
end
|
216
216
|
end
|
217
217
|
|
218
|
-
|
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")
|
data/spec/httpi/response_spec.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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-
|
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: '
|
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: '
|
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.
|
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.
|
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.
|
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
|