httpi 3.0.2 → 4.0.1

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: cd06f829b3d33418dfe3ef465949f504f6acde0e9f5988edea9615e700bb8f23
4
- data.tar.gz: '00197cf31c50d34768c76325d42cc8dc325774ffe5a2ecaf6feb33f7d22c382c'
3
+ metadata.gz: 70c75f8e865f40f9218b34d091ab64aad2656467fff356ac18e2530b70dc52d7
4
+ data.tar.gz: fb86901d88b603911f98d1dbcad0132a0c3f6c28ce3d7b1640ce5b84f7524659
5
5
  SHA512:
6
- metadata.gz: 81a2a86d8a7784711c0a72995a21262c7bcdfb17d9127a06a9573c50f7eaffde7e544c07b332e905da3fb1b177d867d34c2b59a75f0605182a6d278db9eda4a6
7
- data.tar.gz: e59a0468efe743db6a4b4d7eff007714cb739e928396b7ff8797896a346e7808a2635185ccf1a9eb53db64d149626782a4f3dc530f3e9644c21923ce6a4a0f3d
6
+ metadata.gz: 4eddf2bd30c64892ec8bc478e5774382030a829b58450a7e0b2266ebdba4f7b01ead27315253c56ba454addc9c7a6112b77f553684e35d143e06397c51de5389
7
+ data.tar.gz: 5b497936201359ed9b45df8486875bb6be8706fedeeed5ec7d7b43a0c15555cff46e3a7fc48a50b1970a76e2dae202eef591ccf74325caf8d5faf77a09f46789
@@ -34,7 +34,7 @@ jobs:
34
34
  experimental: true
35
35
 
36
36
  steps:
37
- - uses: actions/checkout@v3
37
+ - uses: actions/checkout@v4
38
38
 
39
39
  - name: Install dependencies
40
40
  run: sudo apt-get install libcurl4-openssl-dev
data/CHANGELOG.md CHANGED
@@ -1,10 +1,23 @@
1
1
  ### Unreleased
2
2
 
3
- * Improvement: [#237](https://github.com/savonrb/httpi/pull/237) Implemented `adapter_client_setup`.
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
@@ -15,7 +15,7 @@ gem 'net-http-persistent', '~> 4.0', :require => false
15
15
  gem 'http', :require => false
16
16
 
17
17
  # adapter extensions
18
- gem 'rack', '< 3'
18
+ gem 'rack'
19
19
  gem 'socksify'
20
20
 
21
21
  # coverage
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', '~> 3.0.0'
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', '~> 5.0'
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 ||= Rack::Utils::HeaderHash.new
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 = Rack::Utils::HeaderHash.new(headers)
72
+ @headers = HTTPI::Utils::Headers.new.merge(headers)
73
73
  end
74
74
 
75
75
  # Adds a header information to accept gzipped content.
@@ -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 = Rack::Utils::HeaderHash.new(headers)
23
+ self.headers = HTTPI::Utils::Headers.new.merge(headers)
24
24
  self.raw_body = body
25
25
  end
26
26
 
@@ -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
@@ -1,3 +1,3 @@
1
1
  module HTTPI
2
- VERSION = '3.0.2'
2
+ VERSION = '4.0.1'
3
3
  end
data/lib/httpi.rb CHANGED
@@ -3,6 +3,7 @@ require "httpi/version"
3
3
  require "httpi/logger"
4
4
  require "httpi/request"
5
5
  require "httpi/query_builder"
6
+ require "httpi/utils"
6
7
 
7
8
  require "httpi/adapter/httpclient"
8
9
  require "httpi/adapter/curb"
@@ -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[]=nested&q[]=query")
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[]=nested&q[]=query")
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[]=foo", "baz[]=tst"])
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
@@ -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
 
@@ -57,7 +57,7 @@ class IntegrationServer
57
57
  private
58
58
 
59
59
  def events
60
- Puma::Events.new($stdout, $stderr)
60
+ Puma::Events.new
61
61
  end
62
62
 
63
63
  def add_tcp_listener
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: 3.0.2
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-11 00:00:00.000000000 Z
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: '5.0'
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: '5.0'
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