http 5.0.4 → 5.1.0

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: 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