httpi 3.0.2 → 4.0.1
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/.github/workflows/development.yml +1 -1
- data/CHANGELOG.md +14 -1
- data/Gemfile +1 -1
- data/README.md +13 -2
- data/UPDATING.md +4 -0
- data/httpi.gemspec +2 -2
- data/lib/httpi/request.rb +2 -2
- data/lib/httpi/response.rb +1 -1
- data/lib/httpi/utils.rb +238 -0
- data/lib/httpi/version.rb +1 -1
- data/lib/httpi.rb +1 -0
- data/spec/httpi/request_spec.rb +4 -4
- data/spec/httpi/response_spec.rb +2 -2
- data/spec/integration/support/server.rb +1 -1
- metadata +13 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70c75f8e865f40f9218b34d091ab64aad2656467fff356ac18e2530b70dc52d7
|
4
|
+
data.tar.gz: fb86901d88b603911f98d1dbcad0132a0c3f6c28ce3d7b1640ce5b84f7524659
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4eddf2bd30c64892ec8bc478e5774382030a829b58450a7e0b2266ebdba4f7b01ead27315253c56ba454addc9c7a6112b77f553684e35d143e06397c51de5389
|
7
|
+
data.tar.gz: 5b497936201359ed9b45df8486875bb6be8706fedeeed5ec7d7b43a0c15555cff46e3a7fc48a50b1970a76e2dae202eef591ccf74325caf8d5faf77a09f46789
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,23 @@
|
|
1
1
|
### Unreleased
|
2
2
|
|
3
|
-
*
|
3
|
+
* Add your changelog entry here
|
4
|
+
|
5
|
+
### 4.0.1 (2024-02-16)
|
6
|
+
|
7
|
+
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.
|
8
|
+
|
9
|
+
* Adds support for rack 3.0.
|
10
|
+
* POTENTIAL BREAKING CHANGE: `HTTPI::Request#headers` and `HTTPI::Response#headers` now return `HTTPI::Utils::Headers` instead of `Rack::Utils::HeaderHash`. This change will prevent HTTPI from breaking or changing its public API whenever rack rearranges its classes. If you were relying on the `Rack::Utils::HeaderHash` implementation, you will need to update your code to use `HTTPI::Utils::Headers` instead.
|
11
|
+
|
12
|
+
### 4.0.0 (yanked)
|
13
|
+
|
14
|
+
Yanked due to a bug when used with rack 2.
|
4
15
|
|
5
16
|
### 3.0.2 (2024-02-10)
|
6
17
|
|
18
|
+
* Improvement: [#237](https://github.com/savonrb/httpi/pull/237) Implemented `adapter_client_setup`.
|
7
19
|
* Add support for ruby 3.1, 3.2, 3.3. Drop support for ruby 2.7 and below.
|
20
|
+
* Pin to rack version < 3, HTTPI is not tested with rack 3 yet.
|
8
21
|
|
9
22
|
### 3.0.1 (2021-12-17)
|
10
23
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# HTTPI
|
2
2
|
|
3
|
-
A common interface for Ruby's HTTP libraries.
|
3
|
+
A common interface for Ruby's HTTP libraries. This project is now in maintenance mode. For new projects, we recommend [faraday](https://github.com/lostisland/faraday).
|
4
4
|
|
5
5
|
[Documentation](https://www.rubydoc.info/gems/httpi)
|
6
6
|
|
@@ -14,7 +14,7 @@ HTTPI is available through [Rubygems](https://rubygems.org/gems/httpi) and can b
|
|
14
14
|
|
15
15
|
or add it to your Gemfile like this:
|
16
16
|
|
17
|
-
gem 'httpi', '~>
|
17
|
+
gem 'httpi', '~> 4.0.0'
|
18
18
|
|
19
19
|
## Usage example
|
20
20
|
|
@@ -36,6 +36,17 @@ HTTPI.adapter = :httpclient
|
|
36
36
|
|
37
37
|
# and execute arbitary requests
|
38
38
|
HTTPI.request(:custom, request)
|
39
|
+
|
40
|
+
# add a client setup block that will be called before each request
|
41
|
+
HTTPI.adapter = :httpclient
|
42
|
+
HTTPI.adapter_client_setup = proc do |x|
|
43
|
+
x.ssl_config.set_default_paths
|
44
|
+
x.force_basic_auth = true
|
45
|
+
end
|
46
|
+
# ...
|
47
|
+
HTTPI.get(request) do |x|
|
48
|
+
x.force_basic_auth = false
|
49
|
+
end
|
39
50
|
```
|
40
51
|
|
41
52
|
### SOCKS Proxy Support
|
data/UPDATING.md
CHANGED
@@ -5,3 +5,7 @@
|
|
5
5
|
BREAKING CHANGE: the [#255](https://github.com/savonrb/httpi/pull/225) made the gem socksify and rack gems optional dependencies.
|
6
6
|
|
7
7
|
In order to restore the old behavior, see the README section "SOCKS Proxy Support" and "Rack Mock Adapter".
|
8
|
+
|
9
|
+
## From 3.x to 4.x
|
10
|
+
|
11
|
+
POTENTIAL BREAKING CHANGE: `HTTPI::Request#headers` and `HTTPI::Response#headers` now return `HTTPI::Utils::Headers` instead of `Rack::Utils::HeaderHash`. This change will prevent HTTPI from breaking or changing its public API whenever rack rearranges its classes. If you were relying on the `Rack::Utils::HeaderHash` implementation, you will need to update your code to use `HTTPI::Utils::Headers` instead.
|
data/httpi.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
|
22
22
|
s.license = 'MIT'
|
23
23
|
|
24
|
-
s.add_dependency 'rack', '< 3'
|
24
|
+
s.add_dependency 'rack', '>= 2.0', '< 3.1'
|
25
25
|
s.add_dependency 'nkf'
|
26
26
|
s.add_dependency 'base64'
|
27
27
|
s.add_dependency 'mutex_m'
|
@@ -30,7 +30,7 @@ Gem::Specification.new do |s|
|
|
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'
|
33
|
-
s.add_development_dependency 'puma', '~>
|
33
|
+
s.add_development_dependency 'puma', '~> 6.0'
|
34
34
|
s.add_development_dependency 'webmock'
|
35
35
|
|
36
36
|
s.metadata["rubygems_mfa_required"] = "true"
|
data/lib/httpi/request.rb
CHANGED
@@ -64,12 +64,12 @@ module HTTPI
|
|
64
64
|
|
65
65
|
# Returns a Hash of HTTP headers. Defaults to return an empty Hash.
|
66
66
|
def headers
|
67
|
-
@headers ||=
|
67
|
+
@headers ||= HTTPI::Utils::Headers.new
|
68
68
|
end
|
69
69
|
|
70
70
|
# Sets the Hash of HTTP headers.
|
71
71
|
def headers=(headers)
|
72
|
-
@headers =
|
72
|
+
@headers = HTTPI::Utils::Headers.new.merge(headers)
|
73
73
|
end
|
74
74
|
|
75
75
|
# Adds a header information to accept gzipped content.
|
data/lib/httpi/response.rb
CHANGED
@@ -20,7 +20,7 @@ module HTTPI
|
|
20
20
|
# Initializer expects an HTTP response +code+, +headers+ and +body+.
|
21
21
|
def initialize(code, headers, body)
|
22
22
|
self.code = code.to_i
|
23
|
-
self.headers =
|
23
|
+
self.headers = HTTPI::Utils::Headers.new.merge(headers)
|
24
24
|
self.raw_body = body
|
25
25
|
end
|
26
26
|
|
data/lib/httpi/utils.rb
ADDED
@@ -0,0 +1,238 @@
|
|
1
|
+
# mostly verbatim from: https://github.com/rack/rack/blob/main/lib/rack/headers.rb
|
2
|
+
# Because this is part of httpi's public API, its better not to load an external
|
3
|
+
# library for it.
|
4
|
+
module HTTPI
|
5
|
+
module Utils
|
6
|
+
# HTTPI::Utils::Headers is a Hash subclass that downcases all keys.
|
7
|
+
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
|
97
|
+
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
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
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)
|
132
|
+
end
|
133
|
+
|
134
|
+
def fetch(key, *default, &block)
|
135
|
+
key = downcase_key(key)
|
136
|
+
super
|
137
|
+
end
|
138
|
+
|
139
|
+
def fetch_values(*a)
|
140
|
+
super(*a.map!{|key| downcase_key(key)})
|
141
|
+
end
|
142
|
+
|
143
|
+
def has_key?(key)
|
144
|
+
super(downcase_key(key))
|
145
|
+
end
|
146
|
+
alias include? has_key?
|
147
|
+
alias key? has_key?
|
148
|
+
alias member? has_key?
|
149
|
+
|
150
|
+
def invert
|
151
|
+
hash = self.class.new
|
152
|
+
each{|key, value| hash[value] = key}
|
153
|
+
hash
|
154
|
+
end
|
155
|
+
|
156
|
+
def merge(hash, &block)
|
157
|
+
dup.merge!(hash, &block)
|
158
|
+
end
|
159
|
+
|
160
|
+
def reject(&block)
|
161
|
+
hash = dup
|
162
|
+
hash.reject!(&block)
|
163
|
+
hash
|
164
|
+
end
|
165
|
+
|
166
|
+
def replace(hash)
|
167
|
+
clear
|
168
|
+
update(hash)
|
169
|
+
end
|
170
|
+
|
171
|
+
def select(&block)
|
172
|
+
hash = dup
|
173
|
+
hash.select!(&block)
|
174
|
+
hash
|
175
|
+
end
|
176
|
+
|
177
|
+
def to_proc
|
178
|
+
lambda{|x| self[x]}
|
179
|
+
end
|
180
|
+
|
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
|
193
|
+
self
|
194
|
+
end
|
195
|
+
alias merge! update
|
196
|
+
|
197
|
+
def values_at(*keys)
|
198
|
+
keys.map{|key| self[key]}
|
199
|
+
end
|
200
|
+
|
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
|
221
|
+
end
|
222
|
+
|
223
|
+
# :nocov:
|
224
|
+
if RUBY_VERSION >= '3.0'
|
225
|
+
# :nocov:
|
226
|
+
def except(*a)
|
227
|
+
super(*a.map!{|key| downcase_key(key)})
|
228
|
+
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
|
+
end
|
237
|
+
end
|
238
|
+
end
|
data/lib/httpi/version.rb
CHANGED
data/lib/httpi.rb
CHANGED
data/spec/httpi/request_spec.rb
CHANGED
@@ -92,11 +92,11 @@ describe HTTPI::Request do
|
|
92
92
|
after { HTTPI.query_builder = :flat }
|
93
93
|
|
94
94
|
it "lets you specify query parameter as Hash" do
|
95
|
-
expect(request.url.to_s).to eq("http://example.com?q
|
95
|
+
expect(request.url.to_s).to eq("http://example.com?q%5B%5D=nested&q%5B%5D=query")
|
96
96
|
end
|
97
97
|
|
98
98
|
it "getter return String for query parameter as Hash" do
|
99
|
-
expect(request.query).to eq("q
|
99
|
+
expect(request.query).to eq("q%5B%5D=nested&q%5B%5D=query")
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
@@ -149,7 +149,7 @@ describe HTTPI::Request do
|
|
149
149
|
describe "#headers" do
|
150
150
|
it "lets you specify a Hash of HTTP request headers" do
|
151
151
|
request.headers = { "Accept-Encoding" => "gzip" }
|
152
|
-
expect(request.headers).to eq({ "Accept-Encoding" => "gzip" })
|
152
|
+
expect(request.headers).to eq HTTPI::Utils::Headers.new.merge({ "Accept-Encoding" => "gzip" })
|
153
153
|
end
|
154
154
|
|
155
155
|
it "defaults to return an empty Hash" do
|
@@ -235,7 +235,7 @@ describe HTTPI::Request do
|
|
235
235
|
end
|
236
236
|
it "request body using a Hash with Array" do
|
237
237
|
request.body = {:foo => :bar, :baz => [:foo, :tst]}
|
238
|
-
expect(request.body.split("&")).to match_array(["foo=bar", "baz
|
238
|
+
expect(request.body.split("&")).to match_array(["foo=bar", "baz%5B%5D=foo", "baz%5B%5D=tst"])
|
239
239
|
end
|
240
240
|
end
|
241
241
|
end
|
data/spec/httpi/response_spec.rb
CHANGED
@@ -88,7 +88,7 @@ describe HTTPI::Response do
|
|
88
88
|
|
89
89
|
describe "#headers" do
|
90
90
|
it "returns the HTTP response headers" do
|
91
|
-
expect(response.headers).to eq({ "Content-Encoding" => "gzip" })
|
91
|
+
expect(response.headers).to eq HTTPI::Utils::Headers.new.merge({ "Content-Encoding" => "gzip" })
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
@@ -116,7 +116,7 @@ describe HTTPI::Response do
|
|
116
116
|
|
117
117
|
describe "#headers" do
|
118
118
|
it "returns the HTTP response headers" do
|
119
|
-
expect(response.headers).to eq({ "Content-Type" => "application/dime" })
|
119
|
+
expect(response.headers).to eq HTTPI::Utils::Headers.new.merge({ "Content-Type" => "application/dime" })
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
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
|
+
version: 4.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Harrington
|
@@ -9,22 +9,28 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-02-
|
12
|
+
date: 2024-02-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '2.0'
|
18
21
|
- - "<"
|
19
22
|
- !ruby/object:Gem::Version
|
20
|
-
version: '3'
|
23
|
+
version: '3.1'
|
21
24
|
type: :runtime
|
22
25
|
prerelease: false
|
23
26
|
version_requirements: !ruby/object:Gem::Requirement
|
24
27
|
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '2.0'
|
25
31
|
- - "<"
|
26
32
|
- !ruby/object:Gem::Version
|
27
|
-
version: '3'
|
33
|
+
version: '3.1'
|
28
34
|
- !ruby/object:Gem::Dependency
|
29
35
|
name: nkf
|
30
36
|
requirement: !ruby/object:Gem::Requirement
|
@@ -129,14 +135,14 @@ dependencies:
|
|
129
135
|
requirements:
|
130
136
|
- - "~>"
|
131
137
|
- !ruby/object:Gem::Version
|
132
|
-
version: '
|
138
|
+
version: '6.0'
|
133
139
|
type: :development
|
134
140
|
prerelease: false
|
135
141
|
version_requirements: !ruby/object:Gem::Requirement
|
136
142
|
requirements:
|
137
143
|
- - "~>"
|
138
144
|
- !ruby/object:Gem::Version
|
139
|
-
version: '
|
145
|
+
version: '6.0'
|
140
146
|
- !ruby/object:Gem::Dependency
|
141
147
|
name: webmock
|
142
148
|
requirement: !ruby/object:Gem::Requirement
|
@@ -188,6 +194,7 @@ files:
|
|
188
194
|
- lib/httpi/query_builder.rb
|
189
195
|
- lib/httpi/request.rb
|
190
196
|
- lib/httpi/response.rb
|
197
|
+
- lib/httpi/utils.rb
|
191
198
|
- lib/httpi/version.rb
|
192
199
|
- spec/fixtures/attachment.gif
|
193
200
|
- spec/fixtures/client_cert.pem
|