httpi 3.0.2 → 4.0.2

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: cd06f829b3d33418dfe3ef465949f504f6acde0e9f5988edea9615e700bb8f23
4
- data.tar.gz: '00197cf31c50d34768c76325d42cc8dc325774ffe5a2ecaf6feb33f7d22c382c'
3
+ metadata.gz: bb83de56d8f0e1b609e317db0a889b669290c6888b2ef4a41efe682bcd092ec3
4
+ data.tar.gz: a2ec713acb8c51714850de1490c2b247d10fdd0ada7227fbd89ec4cdfb3c7963
5
5
  SHA512:
6
- metadata.gz: 81a2a86d8a7784711c0a72995a21262c7bcdfb17d9127a06a9573c50f7eaffde7e544c07b332e905da3fb1b177d867d34c2b59a75f0605182a6d278db9eda4a6
7
- data.tar.gz: e59a0468efe743db6a4b4d7eff007714cb739e928396b7ff8797896a346e7808a2635185ccf1a9eb53db64d149626782a4f3dc530f3e9644c21923ce6a4a0f3d
6
+ metadata.gz: bd35a2d65bc74884715d763c2790aa0567355c84337f17459fc6d0956b2f019fc6c82dba220bd3fd707b1e1837dcf6b264395ef109251196211d700b76e9f66e
7
+ data.tar.gz: f965bcc58b97d692f295408058bbf2ee3cf70d7b19221cc892aa4bdd250aa177bedc1303efc172c1e953ec7c44327cb026ca044fbf32144b4bb1bf1c435ebb17
@@ -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,27 @@
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.2 (2024-06-13)
6
+
7
+ * Don't change http header casing by @pcai in https://github.com/savonrb/httpi/pull/249
8
+
9
+ ### 4.0.1 (2024-02-16)
10
+
11
+ 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.
12
+
13
+ * Adds support for rack 3.0.
14
+ * 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.
15
+
16
+ ### 4.0.0 (yanked)
17
+
18
+ Yanked due to a bug when used with rack 2.
4
19
 
5
20
  ### 3.0.2 (2024-02-10)
6
21
 
22
+ * Improvement: [#237](https://github.com/savonrb/httpi/pull/237) Implemented `adapter_client_setup`.
7
23
  * Add support for ruby 3.1, 3.2, 3.3. Drop support for ruby 2.7 and below.
24
+ * Pin to rack version < 3, HTTPI is not tested with rack 3 yet.
8
25
 
9
26
  ### 3.0.1 (2021-12-17)
10
27
 
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,16 +21,16 @@ 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'
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'
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,95 @@
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
+ # A case-insensitive Hash that preserves the original case of a
7
+ # header when set.
8
+ #
9
+ class Headers < Hash
10
+ def self.[](headers)
11
+ if headers.is_a?(Headers) && !headers.frozen?
12
+ return headers
13
+ else
14
+ return self.new(headers)
15
+ end
16
+ end
17
+
18
+ def initialize(hash = {})
19
+ super()
20
+ @names = {}
21
+ hash.each { |k, v| self[k] = v }
22
+ end
23
+
24
+ # on dup/clone, we need to duplicate @names hash
25
+ def initialize_copy(other)
26
+ super
27
+ @names = other.names.dup
28
+ end
29
+
30
+ # on clear, we need to clear @names hash
31
+ def clear
32
+ super
33
+ @names.clear
34
+ end
35
+
36
+ def each
37
+ super do |k, v|
38
+ yield(k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v)
39
+ end
40
+ end
41
+
42
+ def to_hash
43
+ hash = {}
44
+ each { |k, v| hash[k] = v }
45
+ hash
46
+ end
47
+
48
+ def [](k)
49
+ super(k) || super(@names[k.downcase])
50
+ end
51
+
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
57
+ end
58
+
59
+ def delete(k)
60
+ canonical = k.downcase
61
+ result = super @names.delete(canonical)
62
+ result
63
+ end
64
+
65
+ def include?(k)
66
+ super || @names.include?(k.downcase)
67
+ end
68
+
69
+ alias_method :has_key?, :include?
70
+ alias_method :member?, :include?
71
+ alias_method :key?, :include?
72
+
73
+ def merge!(other)
74
+ other.each { |k, v| self[k] = v }
75
+ self
76
+ end
77
+
78
+ def merge(other)
79
+ hash = dup
80
+ hash.merge! other
81
+ end
82
+
83
+ def replace(other)
84
+ clear
85
+ other.each { |k, v| self[k] = v }
86
+ self
87
+ end
88
+
89
+ protected
90
+ def names
91
+ @names
92
+ end
93
+ end
94
+ end
95
+ end
data/lib/httpi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module HTTPI
2
- VERSION = '3.0.2'
2
+ VERSION = '4.0.2'
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"
@@ -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")
@@ -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,11 @@ 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
+ end
121
+
122
+ it "preserves casing" do
123
+ expect(response.headers.keys).to eq ["Content-Type"]
120
124
  end
121
125
  end
122
126
 
@@ -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
 
@@ -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.2
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-06-13 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
@@ -73,14 +79,14 @@ dependencies:
73
79
  requirements:
74
80
  - - "~>"
75
81
  - !ruby/object:Gem::Version
76
- version: 0.3.2
82
+ version: 0.6.4
77
83
  type: :development
78
84
  prerelease: false
79
85
  version_requirements: !ruby/object:Gem::Requirement
80
86
  requirements:
81
87
  - - "~>"
82
88
  - !ruby/object:Gem::Version
83
- version: 0.3.2
89
+ version: 0.6.4
84
90
  - !ruby/object:Gem::Dependency
85
91
  name: rake
86
92
  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
@@ -255,7 +262,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
255
262
  - !ruby/object:Gem::Version
256
263
  version: '0'
257
264
  requirements: []
258
- rubygems_version: 3.4.10
265
+ rubygems_version: 3.4.19
259
266
  signing_key:
260
267
  specification_version: 4
261
268
  summary: Common interface for Ruby's HTTP libraries