http 5.0.4 → 5.1.0

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: 92001458b2f36332dfd042ab8750595408d2be8e941ed52be9237e11c071fef7
4
- data.tar.gz: de00f9d0a8f59f3af1605f479e503269741c751b397d62d618c8866e58929140
3
+ metadata.gz: 3826a20981b5ed6a7e5f29fd99af814a8409dea3d556d8d4f1c1faeee0060211
4
+ data.tar.gz: 5f1a624d39059a53df7535df9d8094ec2eb17330ce113ee5f8201f028cb08a01
5
5
  SHA512:
6
- metadata.gz: 63249cd08800a312ffba0ed4b9a508e3890b3088058956e5433c71a60957bfe9985070225855b926d78f5a64c3b587a122c52137788b54e10da65076b39f541f
7
- data.tar.gz: 89605690a8dd8ac3bf23447de8a75f90bc37a77d8ff0e85d84b0748daf2cf06b69011d8e19cc4b22067e479decdfc9d8ca46f7fc0495ec90c25a433e10c1eac8
6
+ metadata.gz: f34965016796ff2864a48d86c45a95db18a5bd118921e9f5ab653b042d53f13332d155238b1b26d28be643b6dffea6f0bf9ac20bbc71bcab05e73e7358ca9b7d
7
+ data.tar.gz: dfcf6ad46848750d86cb9139b7b0ab9d4ae28624bc7c0d779450f3cfbd8de11dd6ba242855fee759210ffade294743746059157cd1eab4eb69125f644653f5e5
@@ -16,11 +16,11 @@ jobs:
16
16
 
17
17
  strategy:
18
18
  matrix:
19
- ruby: [ ruby-2.5, ruby-2.6, ruby-2.7, ruby-3.0 ]
19
+ ruby: [ ruby-2.6, ruby-2.7, ruby-3.0, ruby-3.1 ]
20
20
  os: [ ubuntu-latest ]
21
21
 
22
22
  steps:
23
- - uses: actions/checkout@v2
23
+ - uses: actions/checkout@v3
24
24
 
25
25
  - uses: ruby/setup-ruby@v1
26
26
  with:
@@ -52,11 +52,11 @@ jobs:
52
52
  runs-on: ubuntu-latest
53
53
 
54
54
  steps:
55
- - uses: actions/checkout@v2
55
+ - uses: actions/checkout@v3
56
56
 
57
57
  - uses: ruby/setup-ruby@v1
58
58
  with:
59
- ruby-version: 2.5
59
+ ruby-version: 2.6
60
60
  bundler-cache: true
61
61
 
62
62
  - name: bundle exec rubocop
data/.rubocop.yml CHANGED
@@ -7,4 +7,4 @@ AllCops:
7
7
  DefaultFormatter: fuubar
8
8
  DisplayCopNames: true
9
9
  NewCops: enable
10
- TargetRubyVersion: 2.5
10
+ TargetRubyVersion: 2.6
data/.rubocop_todo.yml CHANGED
@@ -1,13 +1,21 @@
1
1
  # This configuration was generated by
2
- # `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 42`
3
- # on 2021-04-10 09:49:03 UTC using RuboCop version 1.12.1.
2
+ # `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 100`
3
+ # on 2022-06-16 14:35:44 UTC using RuboCop version 1.30.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
+ # Offense count: 1
10
+ # This cop supports safe autocorrection (--autocorrect).
11
+ # Configuration parameters: Include.
12
+ # Include: **/*.gemspec
13
+ Gemspec/DeprecatedAttributeAssignment:
14
+ Exclude:
15
+ - 'http.gemspec'
16
+
9
17
  # Offense count: 53
10
- # Cop supports --auto-correct.
18
+ # This cop supports safe autocorrection (--autocorrect).
11
19
  # Configuration parameters: EnforcedStyle.
12
20
  # SupportedStyles: leading, trailing
13
21
  Layout/DotPosition:
@@ -22,8 +30,8 @@ Layout/DotPosition:
22
30
  - 'spec/lib/http_spec.rb'
23
31
  - 'spec/support/http_handling_shared.rb'
24
32
 
25
- # Offense count: 174
26
- # Cop supports --auto-correct.
33
+ # Offense count: 176
34
+ # This cop supports safe autocorrection (--autocorrect).
27
35
  # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces.
28
36
  # SupportedStyles: space, no_space, compact
29
37
  # SupportedStylesForEmptyBraces: space, no_space
@@ -66,7 +74,7 @@ Metrics/AbcSize:
66
74
  - 'lib/http/request.rb'
67
75
  - 'lib/http/response.rb'
68
76
 
69
- # Offense count: 66
77
+ # Offense count: 69
70
78
  # Configuration parameters: CountComments, Max, CountAsOne, ExcludedMethods, IgnoredMethods.
71
79
  # IgnoredMethods: refine
72
80
  Metrics/BlockLength:
@@ -109,7 +117,7 @@ Metrics/CyclomaticComplexity:
109
117
  - 'lib/http/chainable.rb'
110
118
  - 'lib/http/client.rb'
111
119
 
112
- # Offense count: 19
120
+ # Offense count: 18
113
121
  # Configuration parameters: CountComments, Max, CountAsOne, ExcludedMethods, IgnoredMethods.
114
122
  Metrics/MethodLength:
115
123
  Exclude:
@@ -132,8 +140,13 @@ Metrics/ModuleLength:
132
140
  Exclude:
133
141
  - 'lib/http/chainable.rb'
134
142
 
143
+ # Offense count: 1
144
+ Security/CompoundHash:
145
+ Exclude:
146
+ - 'lib/http/uri.rb'
147
+
135
148
  # Offense count: 2
136
- # Cop supports --auto-correct.
149
+ # This cop supports safe autocorrection (--autocorrect).
137
150
  # Configuration parameters: EnforcedStyle.
138
151
  # SupportedStyles: separated, grouped
139
152
  Style/AccessorGrouping:
@@ -141,7 +154,7 @@ Style/AccessorGrouping:
141
154
  - 'lib/http/request.rb'
142
155
 
143
156
  # Offense count: 4
144
- # Cop supports --auto-correct.
157
+ # This cop supports safe autocorrection (--autocorrect).
145
158
  Style/EmptyCaseCondition:
146
159
  Exclude:
147
160
  - 'lib/http/client.rb'
@@ -150,7 +163,7 @@ Style/EmptyCaseCondition:
150
163
  - 'lib/http/response/status.rb'
151
164
 
152
165
  # Offense count: 5
153
- # Cop supports --auto-correct.
166
+ # This cop supports safe autocorrection (--autocorrect).
154
167
  Style/Encoding:
155
168
  Exclude:
156
169
  - 'spec/lib/http/client_spec.rb'
@@ -160,7 +173,7 @@ Style/Encoding:
160
173
  - 'spec/support/dummy_server/servlet.rb'
161
174
 
162
175
  # Offense count: 17
163
- # Configuration parameters: SuspiciousParamNames.
176
+ # Configuration parameters: SuspiciousParamNames, Allowlist.
164
177
  # SuspiciousParamNames: options, opts, args, params, parameters
165
178
  Style/OptionHash:
166
179
  Exclude:
@@ -183,8 +196,8 @@ Style/OptionalBooleanParameter:
183
196
  - 'lib/http/uri.rb'
184
197
 
185
198
  # Offense count: 3
186
- # Cop supports --auto-correct.
187
- # Configuration parameters: AutoCorrect, Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
199
+ # This cop supports safe autocorrection (--autocorrect).
200
+ # Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, IgnoredPatterns.
188
201
  # URISchemes: http, https
189
202
  Layout/LineLength:
190
203
  Exclude:
data/CHANGES.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## 5.1.0 (2022-06-17)
2
+
3
+ * Drop ruby-2.5 support.
4
+
5
+ * [#715](https://github.com/httprb/http/pull/715)
6
+ Set default encoding to UTF-8 for `application/json`.
7
+ ([@drwl])
8
+
9
+ * [#712](https://github.com/httprb/http/pull/712)
10
+ Recognize cookies set by redirect.
11
+ ([@tkellogg])
12
+
13
+ * [#707](https://github.com/httprb/http/pull/707)
14
+ Distinguish connection timeouts.
15
+ ([@YuLeven])
16
+
1
17
  ## 5.0.4 (2021-10-07)
2
18
 
3
19
  * [#698](https://github.com/httprb/http/pull/698)
@@ -42,7 +58,7 @@
42
58
 
43
59
  * [#638](https://github.com/httprb/http/pull/638)
44
60
  DNS failover handling.
45
- ([@midnight-wonderer])
61
+ ([@midnight-wonderer])
46
62
 
47
63
 
48
64
  ## 5.0.1 (2021-06-26)
@@ -112,6 +128,7 @@
112
128
 
113
129
  * [#576](https://github.com/httprb/http/pull/576)
114
130
  [#524](https://github.com/httprb/http/issues/524)
131
+ **BREAKING CHANGE**
115
132
  Preserve header names casing.
116
133
  ([@joshuaflanagan])
117
134
 
@@ -968,3 +985,6 @@ end
968
985
  [@matheussilvasantos]: https://github.com/matheussilvasantos
969
986
  [@PhilCoggins]: https://github.com/PhilCoggins
970
987
  [@flosacca]: https://github.com/flosacca
988
+ [@YuLeven]: https://github.com/YuLeven
989
+ [@drwl]: https://github.com/drwl
990
+ [@tkellogg]: https://github.com/tkellogg
data/Gemfile CHANGED
@@ -27,7 +27,7 @@ group :test do
27
27
 
28
28
  gem "backports"
29
29
 
30
- gem "rubocop", "~> 1.21"
30
+ gem "rubocop", "~> 1.30.0"
31
31
  gem "rubocop-performance"
32
32
  gem "rubocop-rake"
33
33
  gem "rubocop-rspec"
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2021 Tony Arcieri, Erik Michaels-Ober, Alexey V. Zapparov, Zachary Anker
1
+ Copyright (c) 2011-2022 Tony Arcieri, Erik Michaels-Ober, Alexey V. Zapparov, Zachary Anker
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -141,7 +141,7 @@ dropped.
141
141
 
142
142
  ## Copyright
143
143
 
144
- Copyright © 2011-2021 Tony Arcieri, Alexey V. Zapparov, Erik Michaels-Ober, Zachary Anker.
144
+ Copyright © 2011-2022 Tony Arcieri, Alexey V. Zapparov, Erik Michaels-Ober, Zachary Anker.
145
145
  See LICENSE.txt for further details.
146
146
 
147
147
 
data/SECURITY.md ADDED
@@ -0,0 +1,5 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a Vulnerability
4
+
5
+ Please report security issues to `bascule@gmail.com`
data/http.gemspec CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |gem|
25
25
  gem.require_paths = ["lib"]
26
26
  gem.version = HTTP::VERSION
27
27
 
28
- gem.required_ruby_version = ">= 2.5"
28
+ gem.required_ruby_version = ">= 2.6"
29
29
 
30
30
  gem.add_runtime_dependency "addressable", "~> 2.8"
31
31
  gem.add_runtime_dependency "http-cookie", "~> 1.0"
@@ -35,9 +35,10 @@ Gem::Specification.new do |gem|
35
35
  gem.add_development_dependency "bundler", "~> 2.0"
36
36
 
37
37
  gem.metadata = {
38
- "source_code_uri" => "https://github.com/httprb/http",
39
- "wiki_uri" => "https://github.com/httprb/http/wiki",
40
- "bug_tracker_uri" => "https://github.com/httprb/http/issues",
41
- "changelog_uri" => "https://github.com/httprb/http/blob/v#{HTTP::VERSION}/CHANGES.md"
38
+ "source_code_uri" => "https://github.com/httprb/http",
39
+ "wiki_uri" => "https://github.com/httprb/http/wiki",
40
+ "bug_tracker_uri" => "https://github.com/httprb/http/issues",
41
+ "changelog_uri" => "https://github.com/httprb/http/blob/v#{HTTP::VERSION}/CHANGES.md",
42
+ "rubygems_mfa_required" => "true"
42
43
  }
43
44
  end
data/lib/http/errors.rb CHANGED
@@ -19,6 +19,9 @@ module HTTP
19
19
  # Generic Timeout error
20
20
  class TimeoutError < Error; end
21
21
 
22
+ # Timeout when first establishing the conncetion
23
+ class ConnectTimeoutError < TimeoutError; end
24
+
22
25
  # Header value is of unexpected format (similar to Net::HTTPHeaderSyntaxError)
23
26
  class HeaderError < Error; end
24
27
  end
data/lib/http/headers.rb CHANGED
@@ -111,7 +111,7 @@ module HTTP
111
111
  #
112
112
  # @return [Hash]
113
113
  def to_h
114
- keys.map { |k| [k, self[k]] }.to_h
114
+ keys.to_h { |k| [k, self[k]] }
115
115
  end
116
116
  alias to_hash to_h
117
117
 
@@ -49,6 +49,8 @@ module HTTP
49
49
  @request = request
50
50
  @response = response
51
51
  @visited = []
52
+ collect_cookies_from_request
53
+ collect_cookies_from_response
52
54
 
53
55
  while REDIRECT_CODES.include? @response.status.code
54
56
  @visited << "#{@request.verb} #{@request.uri}"
@@ -59,8 +61,12 @@ module HTTP
59
61
  @response.flush
60
62
 
61
63
  # XXX(ixti): using `Array#inject` to return `nil` if no Location header.
62
- @request = redirect_to(@response.headers.get(Headers::LOCATION).inject(:+))
64
+ @request = redirect_to(@response.headers.get(Headers::LOCATION).inject(:+))
65
+ unless cookie_jar.empty?
66
+ @request.headers.set(Headers::COOKIE, cookie_jar.cookies.map { |c| "#{c.name}=#{c.value}" }.join("; "))
67
+ end
63
68
  @response = yield @request
69
+ collect_cookies_from_response
64
70
  end
65
71
 
66
72
  @response
@@ -68,6 +74,48 @@ module HTTP
68
74
 
69
75
  private
70
76
 
77
+ # All known cookies. On the original request, this is only the original cookies, but after that,
78
+ # Set-Cookie headers can add, set or delete cookies.
79
+ def cookie_jar
80
+ # it seems that @response.cookies instance is reused between responses, so we have to "clone"
81
+ @cookie_jar ||= HTTP::CookieJar.new
82
+ end
83
+
84
+ def collect_cookies_from_request
85
+ request_cookie_header = @request.headers["Cookie"]
86
+ cookies =
87
+ if request_cookie_header
88
+ HTTP::Cookie.cookie_value_to_hash(request_cookie_header)
89
+ else
90
+ {}
91
+ end
92
+
93
+ cookies.each do |key, value|
94
+ cookie_jar.add(HTTP::Cookie.new(key, value, :path => @request.uri.path, :domain => @request.host))
95
+ end
96
+ end
97
+
98
+ # Carry cookies from one response to the next. Carrying cookies to the next response ends up
99
+ # carrying them to the next request as well.
100
+ #
101
+ # Note that this isn't part of the IETF standard, but all major browsers support setting cookies
102
+ # on redirect: https://blog.dubbelboer.com/2012/11/25/302-cookie.html
103
+ def collect_cookies_from_response
104
+ # Overwrite previous cookies
105
+ @response.cookies.each do |cookie|
106
+ if cookie.value == ""
107
+ cookie_jar.delete(cookie)
108
+ else
109
+ cookie_jar.add(cookie)
110
+ end
111
+ end
112
+
113
+ # I wish we could just do @response.cookes = cookie_jar
114
+ cookie_jar.each do |cookie|
115
+ @response.cookies.add(cookie)
116
+ end
117
+ end
118
+
71
119
  # Check if we reached max amount of redirect hops
72
120
  # @return [Boolean]
73
121
  def too_many_hops?
@@ -69,7 +69,7 @@ module HTTP
69
69
  # SYMBOL_CODES[:im_a_teapot] # => 418
70
70
  #
71
71
  # @return [Hash<Symbol => Fixnum>]
72
- SYMBOL_CODES = SYMBOLS.map { |k, v| [v, k] }.to_h.freeze
72
+ SYMBOL_CODES = SYMBOLS.to_h { |k, v| [v, k] }.freeze
73
73
 
74
74
  # @return [Fixnum] status code
75
75
  attr_reader :code
data/lib/http/response.rb CHANGED
@@ -53,7 +53,7 @@ module HTTP
53
53
  @body = opts.fetch(:body)
54
54
  else
55
55
  connection = opts.fetch(:connection)
56
- encoding = opts[:encoding] || charset || Encoding::BINARY
56
+ encoding = opts[:encoding] || charset || default_encoding
57
57
 
58
58
  @body = Response::Body.new(connection, :encoding => encoding)
59
59
  end
@@ -168,6 +168,12 @@ module HTTP
168
168
 
169
169
  private
170
170
 
171
+ def default_encoding
172
+ return Encoding::UTF_8 if mime_type == "application/json"
173
+
174
+ Encoding::BINARY
175
+ end
176
+
171
177
  # Initialize an HTTP::Request from options.
172
178
  #
173
179
  # @return [HTTP::Request]
@@ -21,7 +21,7 @@ module HTTP
21
21
 
22
22
  def connect(socket_class, host, port, nodelay = false)
23
23
  reset_timer
24
- ::Timeout.timeout(@time_left, TimeoutError) do
24
+ ::Timeout.timeout(@time_left, ConnectTimeoutError) do
25
25
  @socket = socket_class.open(host, port)
26
26
  @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay
27
27
  end
@@ -20,7 +20,7 @@ module HTTP
20
20
  end
21
21
 
22
22
  def connect(socket_class, host, port, nodelay = false)
23
- ::Timeout.timeout(@connect_timeout, TimeoutError) do
23
+ ::Timeout.timeout(@connect_timeout, ConnectTimeoutError) do
24
24
  @socket = socket_class.open(host, port)
25
25
  @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay
26
26
  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.0.4"
4
+ VERSION = "5.1.0"
5
5
  end
@@ -389,8 +389,8 @@ RSpec.describe HTTP::Client do
389
389
  client.use(:test_feature => feature_instance).
390
390
  timeout(0.001).
391
391
  request(:post, sleep_url)
392
- end.to raise_error(HTTP::TimeoutError)
393
- expect(feature_instance.captured_error).to be_a(HTTP::TimeoutError)
392
+ end.to raise_error(HTTP::ConnectTimeoutError)
393
+ expect(feature_instance.captured_error).to be_a(HTTP::ConnectTimeoutError)
394
394
  end
395
395
  end
396
396
  end
@@ -11,8 +11,12 @@ RSpec.describe HTTP::Redirector do
11
11
  )
12
12
  end
13
13
 
14
- def redirect_response(status, location)
15
- simple_response status, "", "Location" => location
14
+ def redirect_response(status, location, set_cookie = {})
15
+ res = simple_response status, "", "Location" => location
16
+ set_cookie.each do |name, value|
17
+ res.headers.add("Set-Cookie", "#{name}=#{value}; path=/; httponly; secure; SameSite=none; Secure")
18
+ end
19
+ res
16
20
  end
17
21
 
18
22
  describe "#strict" do
@@ -89,6 +93,61 @@ RSpec.describe HTTP::Redirector do
89
93
  expect(res.to_s).to eq "http://example.com/123"
90
94
  end
91
95
 
96
+ it "returns cookies in response" do
97
+ req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
98
+ hops = [
99
+ redirect_response(301, "http://example.com/1", {"foo" => "42"}),
100
+ redirect_response(301, "http://example.com/2", {"bar" => "53", "deleted" => "foo"}),
101
+ redirect_response(301, "http://example.com/3", {"baz" => "64", "deleted" => ""}),
102
+ redirect_response(301, "http://example.com/4", {"baz" => "65"}),
103
+ simple_response(200, "bar")
104
+ ]
105
+
106
+ request_cookies = [
107
+ {"foo" => "42"},
108
+ {"foo" => "42", "bar" => "53", "deleted" => "foo"},
109
+ {"foo" => "42", "bar" => "53", "baz" => "64"},
110
+ {"foo" => "42", "bar" => "53", "baz" => "65"}
111
+ ]
112
+
113
+ res = redirector.perform(req, hops.shift) do |request|
114
+ req_cookie = HTTP::Cookie.cookie_value_to_hash(request.headers["Cookie"] || "")
115
+ expect(req_cookie).to eq request_cookies.shift
116
+ hops.shift
117
+ end
118
+ expect(res.to_s).to eq "bar"
119
+ cookies = res.cookies.cookies.to_h { |c| [c.name, c.value] }
120
+ expect(cookies["foo"]).to eq "42"
121
+ expect(cookies["bar"]).to eq "53"
122
+ expect(cookies["baz"]).to eq "65"
123
+ expect(cookies["deleted"]).to eq nil
124
+ end
125
+
126
+ it "returns original cookies in response" do
127
+ req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
128
+ req.headers.set("Cookie", "foo=42; deleted=baz")
129
+ hops = [
130
+ redirect_response(301, "http://example.com/1", {"bar" => "64", "deleted" => ""}),
131
+ simple_response(200, "bar")
132
+ ]
133
+
134
+ request_cookies = [
135
+ {"foo" => "42", "bar" => "64"},
136
+ {"foo" => "42", "bar" => "64"}
137
+ ]
138
+
139
+ res = redirector.perform(req, hops.shift) do |request|
140
+ req_cookie = HTTP::Cookie.cookie_value_to_hash(request.headers["Cookie"] || "")
141
+ expect(req_cookie).to eq request_cookies.shift
142
+ hops.shift
143
+ end
144
+ expect(res.to_s).to eq "bar"
145
+ cookies = res.cookies.cookies.to_h { |c| [c.name, c.value] }
146
+ expect(cookies["foo"]).to eq "42"
147
+ expect(cookies["bar"]).to eq "64"
148
+ expect(cookies["deleted"]).to eq nil
149
+ end
150
+
92
151
  context "following 300 redirect" do
93
152
  context "with strict mode" do
94
153
  let(:options) { {:strict => true} }
@@ -400,7 +459,7 @@ RSpec.describe HTTP::Redirector do
400
459
  describe "changing verbs during redirects" do
401
460
  let(:options) { {:strict => false} }
402
461
  let(:post_body) { HTTP::Request::Body.new("i might be way longer in real life") }
403
- let(:cookie) { "dont eat my cookies" }
462
+ let(:cookie) { "dont=eat my cookies" }
404
463
 
405
464
  def a_dangerous_request(verb)
406
465
  HTTP::Request.new(
@@ -59,7 +59,7 @@ RSpec.describe HTTP::Response::Body do
59
59
  let(:chunks) do
60
60
  body = Zlib::Deflate.deflate("Hi, HTTP here ☺")
61
61
  len = body.length
62
- [body[0, len / 2], body[(len / 2)..-1]]
62
+ [body[0, len / 2], body[(len / 2)..]]
63
63
  end
64
64
  subject(:body) do
65
65
  inflater = HTTP::Response::Inflater.new(connection)
@@ -223,4 +223,40 @@ RSpec.describe HTTP::Response do
223
223
  end
224
224
  end
225
225
  end
226
+
227
+ describe "#body" do
228
+ let(:connection) { double(:sequence_id => 0) }
229
+ let(:chunks) { ["Hello, ", "World!"] }
230
+
231
+ subject(:response) do
232
+ HTTP::Response.new(
233
+ :status => 200,
234
+ :version => "1.1",
235
+ :headers => headers,
236
+ :request => request,
237
+ :connection => connection
238
+ )
239
+ end
240
+
241
+ before do
242
+ allow(connection).to receive(:readpartial) { chunks.shift }
243
+ allow(connection).to receive(:body_completed?) { chunks.empty? }
244
+ end
245
+
246
+ context "with no Content-Type" do
247
+ let(:headers) { {} }
248
+
249
+ it "returns a body with default binary encoding" do
250
+ expect(response.body.to_s.encoding).to eq Encoding::BINARY
251
+ end
252
+ end
253
+
254
+ context "with Content-Type: application/json" do
255
+ let(:headers) { {"Content-Type" => "application/json"} }
256
+
257
+ it "returns a body with a default UTF_8 encoding" do
258
+ expect(response.body.to_s.encoding).to eq Encoding::UTF_8
259
+ end
260
+ end
261
+ end
226
262
  end
@@ -77,7 +77,7 @@ RSpec.shared_context "HTTP handling" do
77
77
  sleep 1.25
78
78
  end
79
79
 
80
- expect { response }.to raise_error(HTTP::TimeoutError, /execution/)
80
+ expect { response }.to raise_error(HTTP::ConnectTimeoutError, /execution/)
81
81
  end
82
82
 
83
83
  it "errors if reading takes too long" do
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.0.4
4
+ version: 5.1.0
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: 2021-10-07 00:00:00.000000000 Z
14
+ date: 2022-06-17 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: addressable
@@ -106,6 +106,7 @@ files:
106
106
  - LICENSE.txt
107
107
  - README.md
108
108
  - Rakefile
109
+ - SECURITY.md
109
110
  - http.gemspec
110
111
  - lib/http.rb
111
112
  - lib/http/chainable.rb
@@ -191,7 +192,8 @@ metadata:
191
192
  source_code_uri: https://github.com/httprb/http
192
193
  wiki_uri: https://github.com/httprb/http/wiki
193
194
  bug_tracker_uri: https://github.com/httprb/http/issues
194
- changelog_uri: https://github.com/httprb/http/blob/v5.0.4/CHANGES.md
195
+ changelog_uri: https://github.com/httprb/http/blob/v5.1.0/CHANGES.md
196
+ rubygems_mfa_required: 'true'
195
197
  post_install_message:
196
198
  rdoc_options: []
197
199
  require_paths:
@@ -200,14 +202,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
200
202
  requirements:
201
203
  - - ">="
202
204
  - !ruby/object:Gem::Version
203
- version: '2.5'
205
+ version: '2.6'
204
206
  required_rubygems_version: !ruby/object:Gem::Requirement
205
207
  requirements:
206
208
  - - ">="
207
209
  - !ruby/object:Gem::Version
208
210
  version: '0'
209
211
  requirements: []
210
- rubygems_version: 3.0.3
212
+ rubygems_version: 3.1.6
211
213
  signing_key:
212
214
  specification_version: 4
213
215
  summary: HTTP should be easy