http 5.1.0 → 5.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3826a20981b5ed6a7e5f29fd99af814a8409dea3d556d8d4f1c1faeee0060211
4
- data.tar.gz: 5f1a624d39059a53df7535df9d8094ec2eb17330ce113ee5f8201f028cb08a01
3
+ metadata.gz: ef55bbff996952784d0917931b8eaa6f12a1adfc9cc480daf098cbc8cd8f6107
4
+ data.tar.gz: 222f8e8723969f89994fe2a0692c41786e450c200c45b84f5c8418f736254a64
5
5
  SHA512:
6
- metadata.gz: f34965016796ff2864a48d86c45a95db18a5bd118921e9f5ab653b042d53f13332d155238b1b26d28be643b6dffea6f0bf9ac20bbc71bcab05e73e7358ca9b7d
7
- data.tar.gz: dfcf6ad46848750d86cb9139b7b0ab9d4ae28624bc7c0d779450f3cfbd8de11dd6ba242855fee759210ffade294743746059157cd1eab4eb69125f644653f5e5
6
+ metadata.gz: 49b0c9e508fb02fca9d9e8a26d707202c5ac67bbdf73fce15b616b321545a3a32be96eb9e23f4d389687ad1720372eaba4412e18d800c5d29fab5bb0f4bc0d93
7
+ data.tar.gz: 1b2e22b2b33abe8059e78535556a15c53959b321fb225cd84153d5a8ea608ba4d03ead9cf018720f63b1e7c27c477f8c3f1b151cae60f2d50b6811e7dd9f5bcc
@@ -38,6 +38,26 @@ jobs:
38
38
  path-to-lcov: ./coverage/lcov/lcov.info
39
39
  parallel: true
40
40
 
41
+ test-flaky:
42
+ runs-on: ${{ matrix.os }}
43
+
44
+ strategy:
45
+ matrix:
46
+ ruby: [ jruby-9.3 ]
47
+ os: [ ubuntu-latest ]
48
+
49
+ steps:
50
+ - uses: actions/checkout@v3
51
+
52
+ - uses: ruby/setup-ruby@v1
53
+ with:
54
+ ruby-version: ${{ matrix.ruby }}
55
+ bundler-cache: true
56
+
57
+ - name: bundle exec rspec
58
+ continue-on-error: true
59
+ run: bundle exec rspec --format progress --force-colour
60
+
41
61
  coveralls:
42
62
  needs: test
43
63
  runs-on: ubuntu-latest
data/.rubocop_todo.yml CHANGED
@@ -74,7 +74,7 @@ Metrics/AbcSize:
74
74
  - 'lib/http/request.rb'
75
75
  - 'lib/http/response.rb'
76
76
 
77
- # Offense count: 69
77
+ # Offense count: 70
78
78
  # Configuration parameters: CountComments, Max, CountAsOne, ExcludedMethods, IgnoredMethods.
79
79
  # IgnoredMethods: refine
80
80
  Metrics/BlockLength:
@@ -98,6 +98,7 @@ Metrics/BlockLength:
98
98
  - 'spec/lib/http/response/parser_spec.rb'
99
99
  - 'spec/lib/http/response/status_spec.rb'
100
100
  - 'spec/lib/http/response_spec.rb'
101
+ - 'spec/lib/http/uri_spec.rb'
101
102
  - 'spec/lib/http_spec.rb'
102
103
  - 'spec/support/http_handling_shared.rb'
103
104
 
data/CHANGES.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 5.1.1 (2022-12-17)
2
+
3
+ * [#731](https://github.com/httprb/http/pull/731)
4
+ Strip brackets from IPv6 addresses in `HTTP::URI`.
5
+ ([@jeraki])
6
+
7
+ * [#722](https://github.com/httprb/http/pull/722)
8
+ Add `on_redirect` callback.
9
+ ([@benubois])
10
+
1
11
  ## 5.1.0 (2022-06-17)
2
12
 
3
13
  * Drop ruby-2.5 support.
@@ -988,3 +998,5 @@ end
988
998
  [@YuLeven]: https://github.com/YuLeven
989
999
  [@drwl]: https://github.com/drwl
990
1000
  [@tkellogg]: https://github.com/tkellogg
1001
+ [@jeraki]: https://github.com/jeraki
1002
+ [@benubois]: https://github.com/benubois
data/README.md CHANGED
@@ -113,7 +113,8 @@ the following Ruby versions:
113
113
  - Ruby 2.6
114
114
  - Ruby 2.7
115
115
  - Ruby 3.0
116
- - JRuby 9.2
116
+ - Ruby 3.1
117
+ - JRuby 9.3
117
118
 
118
119
  If something doesn't work on one of these versions, it's a bug.
119
120
 
@@ -40,8 +40,9 @@ module HTTP
40
40
  # @option opts [Boolean] :strict (true) redirector hops policy
41
41
  # @option opts [#to_i] :max_hops (5) maximum allowed amount of hops
42
42
  def initialize(opts = {})
43
- @strict = opts.fetch(:strict, true)
44
- @max_hops = opts.fetch(:max_hops, 5).to_i
43
+ @strict = opts.fetch(:strict, true)
44
+ @max_hops = opts.fetch(:max_hops, 5).to_i
45
+ @on_redirect = opts.fetch(:on_redirect, nil)
45
46
  end
46
47
 
47
48
  # Follows redirects until non-redirect response found
@@ -65,6 +66,7 @@ module HTTP
65
66
  unless cookie_jar.empty?
66
67
  @request.headers.set(Headers::COOKIE, cookie_jar.cookies.map { |c| "#{c.name}=#{c.value}" }.join("; "))
67
68
  end
69
+ @on_redirect.call @response, @request if @on_redirect.respond_to?(:call)
68
70
  @response = yield @request
69
71
  collect_cookies_from_response
70
72
  end
data/lib/http/uri.rb CHANGED
@@ -9,7 +9,6 @@ module HTTP
9
9
  def_delegators :@uri, :scheme, :normalized_scheme, :scheme=
10
10
  def_delegators :@uri, :user, :normalized_user, :user=
11
11
  def_delegators :@uri, :password, :normalized_password, :password=
12
- def_delegators :@uri, :host, :normalized_host, :host=
13
12
  def_delegators :@uri, :authority, :normalized_authority, :authority=
14
13
  def_delegators :@uri, :origin, :origin=
15
14
  def_delegators :@uri, :normalized_port, :port=
@@ -20,6 +19,18 @@ module HTTP
20
19
  def_delegators :@uri, :fragment, :normalized_fragment, :fragment=
21
20
  def_delegators :@uri, :omit, :join, :normalize
22
21
 
22
+ # Host, either a domain name or IP address. If the host is an IPv6 address, it will be returned
23
+ # without brackets surrounding it.
24
+ #
25
+ # @return [String] The host of the URI
26
+ attr_reader :host
27
+
28
+ # Normalized host, either a domain name or IP address. If the host is an IPv6 address, it will
29
+ # be returned without brackets surrounding it.
30
+ #
31
+ # @return [String] The normalized host of the URI
32
+ attr_reader :normalized_host
33
+
23
34
  # @private
24
35
  HTTP_SCHEME = "http"
25
36
 
@@ -83,6 +94,9 @@ module HTTP
83
94
  else
84
95
  raise TypeError, "expected Hash for options, got #{options_or_uri.class}"
85
96
  end
97
+
98
+ @host = process_ipv6_brackets(@uri.host)
99
+ @normalized_host = process_ipv6_brackets(@uri.normalized_host)
86
100
  end
87
101
 
88
102
  # Are these URI objects equal? Normalizes both URIs prior to comparison
@@ -110,6 +124,17 @@ module HTTP
110
124
  @hash ||= to_s.hash * -1
111
125
  end
112
126
 
127
+ # Sets the host component for the URI.
128
+ #
129
+ # @param [String, #to_str] new_host The new host component.
130
+ # @return [void]
131
+ def host=(new_host)
132
+ @uri.host = process_ipv6_brackets(new_host, :brackets => true)
133
+
134
+ @host = process_ipv6_brackets(@uri.host)
135
+ @normalized_host = process_ipv6_brackets(@uri.normalized_host)
136
+ end
137
+
113
138
  # Port number, either as specified or the default if unspecified
114
139
  #
115
140
  # @return [Integer] port number
@@ -146,5 +171,25 @@ module HTTP
146
171
  def inspect
147
172
  format("#<%s:0x%014x URI:%s>", self.class.name, object_id << 1, to_s)
148
173
  end
174
+
175
+ private
176
+
177
+ # Process a URI host, adding or removing surrounding brackets if the host is an IPv6 address.
178
+ #
179
+ # @param [Boolean] brackets When true, brackets will be added to IPv6 addresses if missing. When
180
+ # false, they will be removed if present.
181
+ #
182
+ # @return [String] Host with IPv6 address brackets added or removed
183
+ def process_ipv6_brackets(raw_host, brackets: false)
184
+ ip = IPAddr.new(raw_host)
185
+
186
+ if ip.ipv6?
187
+ brackets ? "[#{ip}]" : ip.to_s
188
+ else
189
+ raw_host
190
+ end
191
+ rescue IPAddr::Error
192
+ raw_host
193
+ end
149
194
  end
150
195
  end
data/lib/http/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTP
4
- VERSION = "5.1.0"
4
+ VERSION = "5.1.1"
5
5
  end
@@ -1,10 +1,12 @@
1
1
  # coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "cgi"
5
+ require "logger"
6
+
4
7
  require "support/http_handling_shared"
5
8
  require "support/dummy_server"
6
9
  require "support/ssl_helper"
7
- require "logger"
8
10
 
9
11
  RSpec.describe HTTP::Client do
10
12
  run_server(:dummy) { DummyServer.new }
@@ -148,6 +148,32 @@ RSpec.describe HTTP::Redirector do
148
148
  expect(cookies["deleted"]).to eq nil
149
149
  end
150
150
 
151
+ context "with on_redirect callback" do
152
+ let(:options) do
153
+ {
154
+ :on_redirect => proc do |response, location|
155
+ @redirect_response = response
156
+ @redirect_location = location
157
+ end
158
+ }
159
+ end
160
+
161
+ it "calls on_redirect" do
162
+ req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
163
+ hops = [
164
+ redirect_response(301, "http://example.com/1"),
165
+ redirect_response(301, "http://example.com/2"),
166
+ simple_response(200, "foo")
167
+ ]
168
+
169
+ redirector.perform(req, hops.shift) do |prev_req, _|
170
+ expect(@redirect_location.uri.to_s).to eq prev_req.uri.to_s
171
+ expect(@redirect_response.code).to eq 301
172
+ hops.shift
173
+ end
174
+ end
175
+ end
176
+
151
177
  context "following 300 redirect" do
152
178
  context "with strict mode" do
153
179
  let(:options) { {:strict => true} }
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe HTTP::URI do
4
+ let(:example_ipv6_address) { "2606:2800:220:1:248:1893:25c8:1946" }
5
+
4
6
  let(:example_http_uri_string) { "http://example.com" }
5
7
  let(:example_https_uri_string) { "https://example.com" }
8
+ let(:example_ipv6_uri_string) { "https://[#{example_ipv6_address}]" }
6
9
 
7
10
  subject(:http_uri) { described_class.parse(example_http_uri_string) }
8
11
  subject(:https_uri) { described_class.parse(example_https_uri_string) }
12
+ subject(:ipv6_uri) { described_class.parse(example_ipv6_uri_string) }
9
13
 
10
14
  it "knows URI schemes" do
11
15
  expect(http_uri.scheme).to eq "http"
@@ -20,6 +24,41 @@ RSpec.describe HTTP::URI do
20
24
  expect(https_uri.port).to eq 443
21
25
  end
22
26
 
27
+ describe "#host" do
28
+ it "strips brackets from IPv6 addresses" do
29
+ expect(ipv6_uri.host).to eq("2606:2800:220:1:248:1893:25c8:1946")
30
+ end
31
+ end
32
+
33
+ describe "#normalized_host" do
34
+ it "strips brackets from IPv6 addresses" do
35
+ expect(ipv6_uri.normalized_host).to eq("2606:2800:220:1:248:1893:25c8:1946")
36
+ end
37
+ end
38
+
39
+ describe "#host=" do
40
+ it "updates cached values for #host and #normalized_host" do
41
+ expect(http_uri.host).to eq("example.com")
42
+ expect(http_uri.normalized_host).to eq("example.com")
43
+
44
+ http_uri.host = "[#{example_ipv6_address}]"
45
+
46
+ expect(http_uri.host).to eq(example_ipv6_address)
47
+ expect(http_uri.normalized_host).to eq(example_ipv6_address)
48
+ end
49
+
50
+ it "ensures IPv6 addresses are bracketed in the inner Addressable::URI" do
51
+ expect(http_uri.host).to eq("example.com")
52
+ expect(http_uri.normalized_host).to eq("example.com")
53
+
54
+ http_uri.host = example_ipv6_address
55
+
56
+ expect(http_uri.host).to eq(example_ipv6_address)
57
+ expect(http_uri.normalized_host).to eq(example_ipv6_address)
58
+ expect(http_uri.instance_variable_get(:@uri).host).to eq("[#{example_ipv6_address}]")
59
+ end
60
+ end
61
+
23
62
  describe "#dup" do
24
63
  it "doesn't share internal value between duplicates" do
25
64
  duplicated_uri = http_uri.dup
@@ -1,6 +1,8 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "cgi"
5
+
4
6
  class DummyServer < WEBrick::HTTPServer
5
7
  class Servlet < WEBrick::HTTPServlet::AbstractServlet # rubocop:disable Metrics/ClassLength
6
8
  def self.sockets
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.0
4
+ version: 5.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2022-06-17 00:00:00.000000000 Z
14
+ date: 2022-12-17 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: addressable
@@ -192,7 +192,7 @@ metadata:
192
192
  source_code_uri: https://github.com/httprb/http
193
193
  wiki_uri: https://github.com/httprb/http/wiki
194
194
  bug_tracker_uri: https://github.com/httprb/http/issues
195
- changelog_uri: https://github.com/httprb/http/blob/v5.1.0/CHANGES.md
195
+ changelog_uri: https://github.com/httprb/http/blob/v5.1.1/CHANGES.md
196
196
  rubygems_mfa_required: 'true'
197
197
  post_install_message:
198
198
  rdoc_options: []
@@ -209,7 +209,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
209
209
  - !ruby/object:Gem::Version
210
210
  version: '0'
211
211
  requirements: []
212
- rubygems_version: 3.1.6
212
+ rubygems_version: 3.0.3
213
213
  signing_key:
214
214
  specification_version: 4
215
215
  summary: HTTP should be easy