http 4.4.0 → 5.0.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 +4 -4
- data/.github/workflows/ci.yml +65 -0
- data/.gitignore +6 -10
- data/.rspec +0 -4
- data/.rubocop.yml +8 -110
- data/.rubocop/layout.yml +8 -0
- data/.rubocop/style.yml +32 -0
- data/.rubocop_todo.yml +192 -0
- data/.yardopts +1 -1
- data/CHANGES.md +90 -0
- data/Gemfile +18 -10
- data/README.md +17 -20
- data/Rakefile +2 -10
- data/http.gemspec +3 -3
- data/lib/http/chainable.rb +23 -17
- data/lib/http/client.rb +36 -30
- data/lib/http/connection.rb +11 -7
- data/lib/http/content_type.rb +12 -7
- data/lib/http/feature.rb +3 -1
- data/lib/http/features/auto_deflate.rb +6 -6
- data/lib/http/features/auto_inflate.rb +6 -5
- data/lib/http/features/instrumentation.rb +1 -1
- data/lib/http/features/logging.rb +19 -21
- data/lib/http/headers.rb +50 -13
- data/lib/http/mime_type/adapter.rb +3 -1
- data/lib/http/mime_type/json.rb +1 -0
- data/lib/http/options.rb +5 -8
- data/lib/http/redirector.rb +2 -1
- data/lib/http/request.rb +13 -10
- data/lib/http/request/body.rb +1 -0
- data/lib/http/request/writer.rb +3 -2
- data/lib/http/response.rb +17 -15
- data/lib/http/response/body.rb +2 -2
- data/lib/http/response/inflater.rb +1 -1
- data/lib/http/response/parser.rb +75 -49
- data/lib/http/response/status.rb +4 -3
- data/lib/http/timeout/global.rb +17 -31
- data/lib/http/timeout/null.rb +2 -1
- data/lib/http/timeout/per_operation.rb +31 -54
- data/lib/http/uri.rb +5 -5
- data/lib/http/version.rb +1 -1
- data/spec/lib/http/client_spec.rb +119 -30
- data/spec/lib/http/connection_spec.rb +8 -5
- data/spec/lib/http/features/auto_inflate_spec.rb +4 -2
- data/spec/lib/http/features/instrumentation_spec.rb +28 -21
- data/spec/lib/http/features/logging_spec.rb +8 -9
- data/spec/lib/http/headers_spec.rb +53 -18
- data/spec/lib/http/options/headers_spec.rb +1 -1
- data/spec/lib/http/options/merge_spec.rb +16 -16
- data/spec/lib/http/redirector_spec.rb +2 -1
- data/spec/lib/http/request/writer_spec.rb +13 -1
- data/spec/lib/http/request_spec.rb +5 -5
- data/spec/lib/http/response/parser_spec.rb +74 -0
- data/spec/lib/http/response/status_spec.rb +3 -3
- data/spec/lib/http/response_spec.rb +11 -22
- data/spec/lib/http_spec.rb +30 -3
- data/spec/spec_helper.rb +21 -21
- data/spec/support/black_hole.rb +1 -1
- data/spec/support/dummy_server.rb +7 -7
- data/spec/support/dummy_server/servlet.rb +17 -6
- data/spec/support/fuubar.rb +21 -0
- data/spec/support/http_handling_shared.rb +4 -4
- data/spec/support/simplecov.rb +19 -0
- data/spec/support/ssl_helper.rb +4 -4
- metadata +21 -14
- data/.coveralls.yml +0 -1
- data/.travis.yml +0 -39
data/.yardopts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
--markup-provider=
|
|
1
|
+
--markup-provider=kramdown
|
|
2
2
|
--markup=markdown
|
data/CHANGES.md
CHANGED
|
@@ -1,3 +1,85 @@
|
|
|
1
|
+
## 5.0.0 (2021-05-12)
|
|
2
|
+
|
|
3
|
+
* [#656](https://github.com/httprb/http/pull/656)
|
|
4
|
+
Handle connection timeouts in `Features`
|
|
5
|
+
([@semenyukdmitry])
|
|
6
|
+
|
|
7
|
+
* [#651](https://github.com/httprb/http/pull/651)
|
|
8
|
+
Replace `http-parser` with `llhttp`
|
|
9
|
+
([@bryanp])
|
|
10
|
+
|
|
11
|
+
* [#647](https://github.com/httprb/http/pull/647)
|
|
12
|
+
Add support for `MKCALENDAR` HTTP verb
|
|
13
|
+
([@meanphil])
|
|
14
|
+
|
|
15
|
+
* [#632](https://github.com/httprb/http/pull/632)
|
|
16
|
+
Respect the SSL context's `verify_hostname` value
|
|
17
|
+
([@colemannugent])
|
|
18
|
+
|
|
19
|
+
* [#625](https://github.com/httprb/http/pull/625)
|
|
20
|
+
Fix inflator with empty responses
|
|
21
|
+
([@LukaszMaslej])
|
|
22
|
+
|
|
23
|
+
* [#599](https://github.com/httprb/http/pull/599)
|
|
24
|
+
Allow passing `HTTP::FormData::{Multipart,UrlEncoded}` object directly.
|
|
25
|
+
([@ixti])
|
|
26
|
+
|
|
27
|
+
* [#593](https://github.com/httprb/http/pull/593)
|
|
28
|
+
[#592](https://github.com/httprb/http/issues/592)
|
|
29
|
+
Support informational (1XX) responses.
|
|
30
|
+
([@ixti])
|
|
31
|
+
|
|
32
|
+
* [#590](https://github.com/httprb/http/pull/590)
|
|
33
|
+
[#589](https://github.com/httprb/http/issues/589)
|
|
34
|
+
Fix response headers paring.
|
|
35
|
+
([@Bonias])
|
|
36
|
+
|
|
37
|
+
* [#587](https://github.com/httprb/http/pull/587)
|
|
38
|
+
[#585](https://github.com/httprb/http/issues/585)
|
|
39
|
+
Fix redirections when server responds with multiple Location headers.
|
|
40
|
+
([@ixti])
|
|
41
|
+
|
|
42
|
+
* [#581](https://github.com/httprb/http/pull/581)
|
|
43
|
+
[#582](https://github.com/httprb/http/issues/582)
|
|
44
|
+
Add Ruby 2.7.x support.
|
|
45
|
+
([@janko])
|
|
46
|
+
|
|
47
|
+
* [#577](https://github.com/httprb/http/pull/577)
|
|
48
|
+
Fix `Chainable#timeout` with frozen Hash.
|
|
49
|
+
([@antonvolkoff])
|
|
50
|
+
|
|
51
|
+
* [#576](https://github.com/httprb/http/pull/576)
|
|
52
|
+
[#524](https://github.com/httprb/http/issues/524)
|
|
53
|
+
Preserve header names casing.
|
|
54
|
+
([@joshuaflanagan])
|
|
55
|
+
|
|
56
|
+
* [#532](https://github.com/httprb/http/pull/532)
|
|
57
|
+
Fix pipes support in request bodies.
|
|
58
|
+
([@ixti])
|
|
59
|
+
|
|
60
|
+
* [#530](https://github.com/httprb/http/pull/530)
|
|
61
|
+
Improve header fields name/value validation.
|
|
62
|
+
([@Bonias])
|
|
63
|
+
|
|
64
|
+
* [#506](https://github.com/httprb/http/pull/506)
|
|
65
|
+
[#521](https://github.com/httprb/http/issues/521)
|
|
66
|
+
Skip auto-deflate when there is no body.
|
|
67
|
+
([@Bonias])
|
|
68
|
+
|
|
69
|
+
* [#489](https://github.com/httprb/http/pull/489)
|
|
70
|
+
Fix HTTP parser.
|
|
71
|
+
([@ixti], [@fxposter])
|
|
72
|
+
|
|
73
|
+
* [#546](https://github.com/httprb/http/pull/546)
|
|
74
|
+
**BREAKING CHANGE**
|
|
75
|
+
Provide initiating `HTTP::Request` object on `HTTP::Response`.
|
|
76
|
+
([@joshuaflanagan])
|
|
77
|
+
|
|
78
|
+
* [#571](https://github.com/httprb/http/pull/571)
|
|
79
|
+
Drop Ruby 2.3.x support.
|
|
80
|
+
([@ixti])
|
|
81
|
+
|
|
82
|
+
|
|
1
83
|
## 4.4.0 (2020-03-25)
|
|
2
84
|
|
|
3
85
|
* Backport [#587](https://github.com/httprb/http/pull/587)
|
|
@@ -8,6 +90,7 @@
|
|
|
8
90
|
Allow passing HTTP::FormData::{Multipart,UrlEncoded} object directly.
|
|
9
91
|
([@ixti])
|
|
10
92
|
|
|
93
|
+
|
|
11
94
|
## 4.3.0 (2020-01-09)
|
|
12
95
|
|
|
13
96
|
* Backport [#581](https://github.com/httprb/http/pull/581)
|
|
@@ -797,3 +880,10 @@ end
|
|
|
797
880
|
[@RickCSong]: https://github.com/RickCSong
|
|
798
881
|
[@fxposter]: https://github.com/fxposter
|
|
799
882
|
[@mamoonraja]: https://github.com/mamoonraja
|
|
883
|
+
[@joshuaflanagan]: https://github.com/joshuaflanagan
|
|
884
|
+
[@antonvolkoff]: https://github.com/antonvolkoff
|
|
885
|
+
[@LukaszMaslej]: https://github.com/LukaszMaslej
|
|
886
|
+
[@colemannugent]: https://github.com/colemannugent
|
|
887
|
+
[@semenyukdmitry]: https://github.com/semenyukdmitry
|
|
888
|
+
[@bryanp]: https://github.com/bryanp
|
|
889
|
+
[@meanphil]: https://github.com/meanphil
|
data/Gemfile
CHANGED
|
@@ -5,30 +5,38 @@ ruby RUBY_VERSION
|
|
|
5
5
|
|
|
6
6
|
gem "rake"
|
|
7
7
|
|
|
8
|
+
# Ruby 3.0 does not ship it anymore.
|
|
9
|
+
# TODO: We should probably refactor specs to avoid need for it.
|
|
10
|
+
gem "webrick"
|
|
11
|
+
|
|
8
12
|
group :development do
|
|
9
13
|
gem "guard-rspec", :require => false
|
|
10
14
|
gem "nokogiri", :require => false
|
|
11
15
|
gem "pry", :require => false
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
# RSpec formatter
|
|
18
|
+
gem "fuubar", :require => false
|
|
19
|
+
|
|
20
|
+
platform :mri do
|
|
21
|
+
gem "pry-byebug"
|
|
16
22
|
end
|
|
17
23
|
end
|
|
18
24
|
|
|
19
25
|
group :test do
|
|
20
|
-
gem "
|
|
21
|
-
gem "certificate_authority", :require => false
|
|
26
|
+
gem "certificate_authority", "~> 1.0", :require => false
|
|
22
27
|
|
|
23
28
|
gem "backports"
|
|
24
29
|
|
|
25
|
-
gem "
|
|
26
|
-
gem "
|
|
30
|
+
gem "rubocop"
|
|
31
|
+
gem "rubocop-performance"
|
|
32
|
+
gem "rubocop-rake"
|
|
33
|
+
gem "rubocop-rspec"
|
|
27
34
|
|
|
28
|
-
gem "
|
|
29
|
-
gem "
|
|
35
|
+
gem "simplecov", :require => false
|
|
36
|
+
gem "simplecov-lcov", :require => false
|
|
30
37
|
|
|
31
|
-
gem "
|
|
38
|
+
gem "rspec", "~> 3.10"
|
|
39
|
+
gem "rspec-its"
|
|
32
40
|
|
|
33
41
|
gem "yardstick"
|
|
34
42
|
end
|
data/README.md
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
# 
|
|
2
2
|
|
|
3
|
-
[](https://github.com/httprb/http/blob/4-x-stable/LICENSE.txt)
|
|
3
|
+
[](https://rubygems.org/gems/http)
|
|
4
|
+
[](https://github.com/httprb/http/actions?query=workflow:CI)
|
|
5
|
+
[](https://codeclimate.com/github/httprb/http)
|
|
6
|
+
[](https://github.com/httprb/http/blob/master/LICENSE.txt)
|
|
8
7
|
|
|
9
8
|
[Documentation]
|
|
10
9
|
|
|
11
|
-
_NOTE: This is the
|
|
10
|
+
_NOTE: This is the 5.x **development** branch. For the 4.x **stable** branch, please see:_
|
|
12
11
|
|
|
13
|
-
https://github.com/httprb/http/tree/
|
|
12
|
+
https://github.com/httprb/http/tree/4-x-stable
|
|
14
13
|
|
|
15
14
|
## About
|
|
16
15
|
|
|
@@ -18,13 +17,12 @@ HTTP (The Gem! a.k.a. http.rb) is an easy-to-use client library for making reque
|
|
|
18
17
|
from Ruby. It uses a simple method chaining system for building requests, similar to
|
|
19
18
|
Python's [Requests].
|
|
20
19
|
|
|
21
|
-
Under the hood, http.rb uses [
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
natively and outsources the parsing to native extensions.
|
|
20
|
+
Under the hood, http.rb uses the [llhttp] parser, a fast HTTP parsing native extension.
|
|
21
|
+
This library isn't just yet another wrapper around `Net::HTTP`. It implements the HTTP
|
|
22
|
+
protocol natively and outsources the parsing to native extensions.
|
|
25
23
|
|
|
26
24
|
[requests]: http://docs.python-requests.org/en/latest/
|
|
27
|
-
[
|
|
25
|
+
[llhttp]: https://llhttp.org/
|
|
28
26
|
|
|
29
27
|
|
|
30
28
|
## Another Ruby HTTP library? Why should I care?
|
|
@@ -114,8 +112,8 @@ for more detailed documentation and usage notes.
|
|
|
114
112
|
|
|
115
113
|
The following API documentation is also available:
|
|
116
114
|
|
|
117
|
-
* [YARD API documentation](
|
|
118
|
-
* [Chainable module (all chainable methods)](
|
|
115
|
+
* [YARD API documentation](https://www.rubydoc.info/github/httprb/http)
|
|
116
|
+
* [Chainable module (all chainable methods)](https://www.rubydoc.info/github/httprb/http/HTTP/Chainable)
|
|
119
117
|
|
|
120
118
|
[documentation]: https://github.com/httprb/http/wiki
|
|
121
119
|
|
|
@@ -164,11 +162,10 @@ and call `#readpartial` on it repeatedly until it returns `nil`:
|
|
|
164
162
|
This library aims to support and is [tested against][travis] the following Ruby
|
|
165
163
|
versions:
|
|
166
164
|
|
|
167
|
-
* Ruby 2.
|
|
168
|
-
* Ruby 2.
|
|
169
|
-
* Ruby
|
|
170
|
-
*
|
|
171
|
-
* JRuby 9.2.x.x
|
|
165
|
+
* Ruby 2.6
|
|
166
|
+
* Ruby 2.7
|
|
167
|
+
* Ruby 3.0
|
|
168
|
+
* JRuby 9.2
|
|
172
169
|
|
|
173
170
|
If something doesn't work on one of these versions, it's a bug.
|
|
174
171
|
|
|
@@ -198,5 +195,5 @@ dropped.
|
|
|
198
195
|
|
|
199
196
|
## Copyright
|
|
200
197
|
|
|
201
|
-
Copyright (c) 2011-
|
|
198
|
+
Copyright (c) 2011-2021 Tony Arcieri, Alexey V. Zapparov, Erik Michaels-Ober, Zachary Anker.
|
|
202
199
|
See LICENSE.txt for further details.
|
data/Rakefile
CHANGED
|
@@ -35,7 +35,7 @@ task :generate_status_codes do
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
File.open("./lib/http/response/status/reasons.rb", "w") do |io|
|
|
38
|
-
io.puts
|
|
38
|
+
io.puts <<~TPL
|
|
39
39
|
# AUTO-GENERATED FILE, DO NOT CHANGE IT MANUALLY
|
|
40
40
|
|
|
41
41
|
require "delegate"
|
|
@@ -61,12 +61,4 @@ task :generate_status_codes do
|
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
task :default => %i[spec rubocop verify_measurements]
|
|
66
|
-
else
|
|
67
|
-
case ENV["SUITE"]
|
|
68
|
-
when "rubocop" then task :default => :rubocop
|
|
69
|
-
when "yardstick" then task :default => :verify_measurements
|
|
70
|
-
else task :default => :spec
|
|
71
|
-
end
|
|
72
|
-
end
|
|
64
|
+
task :default => %i[spec rubocop verify_measurements]
|
data/http.gemspec
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
lib = File.expand_path("
|
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require "http/version"
|
|
6
6
|
|
|
@@ -25,12 +25,12 @@ 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.
|
|
28
|
+
gem.required_ruby_version = ">= 2.5"
|
|
29
29
|
|
|
30
30
|
gem.add_runtime_dependency "addressable", "~> 2.3"
|
|
31
31
|
gem.add_runtime_dependency "http-cookie", "~> 1.0"
|
|
32
32
|
gem.add_runtime_dependency "http-form_data", "~> 2.2"
|
|
33
|
-
gem.add_runtime_dependency "
|
|
33
|
+
gem.add_runtime_dependency "llhttp-ffi", "~> 0.0.1"
|
|
34
34
|
|
|
35
35
|
gem.add_development_dependency "bundler", "~> 2.0"
|
|
36
36
|
|
data/lib/http/chainable.rb
CHANGED
|
@@ -9,63 +9,63 @@ module HTTP
|
|
|
9
9
|
# Request a get sans response body
|
|
10
10
|
# @param uri
|
|
11
11
|
# @option options [Hash]
|
|
12
|
-
def head(uri, options = {})
|
|
12
|
+
def head(uri, options = {})
|
|
13
13
|
request :head, uri, options
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
# Get a resource
|
|
17
17
|
# @param uri
|
|
18
18
|
# @option options [Hash]
|
|
19
|
-
def get(uri, options = {})
|
|
19
|
+
def get(uri, options = {})
|
|
20
20
|
request :get, uri, options
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
# Post to a resource
|
|
24
24
|
# @param uri
|
|
25
25
|
# @option options [Hash]
|
|
26
|
-
def post(uri, options = {})
|
|
26
|
+
def post(uri, options = {})
|
|
27
27
|
request :post, uri, options
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Put to a resource
|
|
31
31
|
# @param uri
|
|
32
32
|
# @option options [Hash]
|
|
33
|
-
def put(uri, options = {})
|
|
33
|
+
def put(uri, options = {})
|
|
34
34
|
request :put, uri, options
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
# Delete a resource
|
|
38
38
|
# @param uri
|
|
39
39
|
# @option options [Hash]
|
|
40
|
-
def delete(uri, options = {})
|
|
40
|
+
def delete(uri, options = {})
|
|
41
41
|
request :delete, uri, options
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
# Echo the request back to the client
|
|
45
45
|
# @param uri
|
|
46
46
|
# @option options [Hash]
|
|
47
|
-
def trace(uri, options = {})
|
|
47
|
+
def trace(uri, options = {})
|
|
48
48
|
request :trace, uri, options
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
# Return the methods supported on the given URI
|
|
52
52
|
# @param uri
|
|
53
53
|
# @option options [Hash]
|
|
54
|
-
def options(uri, options = {})
|
|
54
|
+
def options(uri, options = {})
|
|
55
55
|
request :options, uri, options
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
# Convert to a transparent TCP/IP tunnel
|
|
59
59
|
# @param uri
|
|
60
60
|
# @option options [Hash]
|
|
61
|
-
def connect(uri, options = {})
|
|
61
|
+
def connect(uri, options = {})
|
|
62
62
|
request :connect, uri, options
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
# Apply partial modifications to a resource
|
|
66
66
|
# @param uri
|
|
67
67
|
# @option options [Hash]
|
|
68
|
-
def patch(uri, options = {})
|
|
68
|
+
def patch(uri, options = {})
|
|
69
69
|
request :patch, uri, options
|
|
70
70
|
end
|
|
71
71
|
|
|
@@ -93,7 +93,7 @@ module HTTP
|
|
|
93
93
|
def timeout(options)
|
|
94
94
|
klass, options = case options
|
|
95
95
|
when Numeric then [HTTP::Timeout::Global, {:global => options}]
|
|
96
|
-
when Hash then [HTTP::Timeout::PerOperation, options]
|
|
96
|
+
when Hash then [HTTP::Timeout::PerOperation, options.dup]
|
|
97
97
|
when :null then [HTTP::Timeout::Null, {}]
|
|
98
98
|
else raise ArgumentError, "Use `.timeout(global_timeout_in_seconds)` or `.timeout(connect: x, write: y, read: z)`."
|
|
99
99
|
|
|
@@ -101,11 +101,12 @@ module HTTP
|
|
|
101
101
|
|
|
102
102
|
%i[global read write connect].each do |k|
|
|
103
103
|
next unless options.key? k
|
|
104
|
+
|
|
104
105
|
options["#{k}_timeout".to_sym] = options.delete k
|
|
105
106
|
end
|
|
106
107
|
|
|
107
108
|
branch default_options.merge(
|
|
108
|
-
:timeout_class
|
|
109
|
+
:timeout_class => klass,
|
|
109
110
|
:timeout_options => options
|
|
110
111
|
)
|
|
111
112
|
end
|
|
@@ -144,9 +145,10 @@ module HTTP
|
|
|
144
145
|
options = {:keep_alive_timeout => timeout}
|
|
145
146
|
p_client = branch default_options.merge(options).with_persistent host
|
|
146
147
|
return p_client unless block_given?
|
|
148
|
+
|
|
147
149
|
yield p_client
|
|
148
150
|
ensure
|
|
149
|
-
p_client
|
|
151
|
+
p_client&.close
|
|
150
152
|
end
|
|
151
153
|
|
|
152
154
|
# Make a request through an HTTP proxy
|
|
@@ -168,10 +170,10 @@ module HTTP
|
|
|
168
170
|
alias through via
|
|
169
171
|
|
|
170
172
|
# Make client follow redirects.
|
|
171
|
-
# @param
|
|
173
|
+
# @param options
|
|
172
174
|
# @return [HTTP::Client]
|
|
173
175
|
# @see Redirector#initialize
|
|
174
|
-
def follow(options = {})
|
|
176
|
+
def follow(options = {})
|
|
175
177
|
branch default_options.with_follow options
|
|
176
178
|
end
|
|
177
179
|
|
|
@@ -209,10 +211,11 @@ module HTTP
|
|
|
209
211
|
# @option opts [#to_s] :user
|
|
210
212
|
# @option opts [#to_s] :pass
|
|
211
213
|
def basic_auth(opts)
|
|
212
|
-
user
|
|
213
|
-
pass
|
|
214
|
+
user = opts.fetch(:user)
|
|
215
|
+
pass = opts.fetch(:pass)
|
|
216
|
+
creds = "#{user}:#{pass}"
|
|
214
217
|
|
|
215
|
-
auth("Basic
|
|
218
|
+
auth("Basic #{Base64.strict_encode64(creds)}")
|
|
216
219
|
end
|
|
217
220
|
|
|
218
221
|
# Get options for HTTP
|
|
@@ -236,6 +239,9 @@ module HTTP
|
|
|
236
239
|
# Turn on given features. Available features are:
|
|
237
240
|
# * auto_inflate
|
|
238
241
|
# * auto_deflate
|
|
242
|
+
# * instrumentation
|
|
243
|
+
# * logging
|
|
244
|
+
# * normalize_uri
|
|
239
245
|
# @param features
|
|
240
246
|
def use(*features)
|
|
241
247
|
branch default_options.with_features(features)
|
data/lib/http/client.rb
CHANGED
|
@@ -16,7 +16,7 @@ module HTTP
|
|
|
16
16
|
extend Forwardable
|
|
17
17
|
include Chainable
|
|
18
18
|
|
|
19
|
-
HTTP_OR_HTTPS_RE = %r{^https?://}i
|
|
19
|
+
HTTP_OR_HTTPS_RE = %r{^https?://}i.freeze
|
|
20
20
|
|
|
21
21
|
def initialize(default_options = {})
|
|
22
22
|
@default_options = HTTP::Options.new(default_options)
|
|
@@ -25,7 +25,7 @@ module HTTP
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
# Make an HTTP request
|
|
28
|
-
def request(verb, uri, opts = {})
|
|
28
|
+
def request(verb, uri, opts = {})
|
|
29
29
|
opts = @default_options.merge(opts)
|
|
30
30
|
req = build_request(verb, uri, opts)
|
|
31
31
|
res = perform(req, opts)
|
|
@@ -37,7 +37,7 @@ module HTTP
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
# Prepare an HTTP request
|
|
40
|
-
def build_request(verb, uri, opts = {})
|
|
40
|
+
def build_request(verb, uri, opts = {})
|
|
41
41
|
opts = @default_options.merge(opts)
|
|
42
42
|
uri = make_request_uri(uri, opts)
|
|
43
43
|
headers = make_request_headers(opts)
|
|
@@ -68,22 +68,20 @@ module HTTP
|
|
|
68
68
|
|
|
69
69
|
@state = :dirty
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
@connection.
|
|
75
|
-
|
|
71
|
+
begin
|
|
72
|
+
@connection ||= HTTP::Connection.new(req, options)
|
|
73
|
+
|
|
74
|
+
unless @connection.failed_proxy_connect?
|
|
75
|
+
@connection.send_request(req)
|
|
76
|
+
@connection.read_headers!
|
|
77
|
+
end
|
|
78
|
+
rescue Error => e
|
|
79
|
+
options.features.each_value do |feature|
|
|
80
|
+
feature.on_error(req, e)
|
|
81
|
+
end
|
|
82
|
+
raise
|
|
76
83
|
end
|
|
77
|
-
|
|
78
|
-
res = Response.new(
|
|
79
|
-
:status => @connection.status_code,
|
|
80
|
-
:version => @connection.http_version,
|
|
81
|
-
:headers => @connection.headers,
|
|
82
|
-
:proxy_headers => @connection.proxy_response_headers,
|
|
83
|
-
:connection => @connection,
|
|
84
|
-
:encoding => options.encoding,
|
|
85
|
-
:uri => req.uri
|
|
86
|
-
)
|
|
84
|
+
res = build_response(req, options)
|
|
87
85
|
|
|
88
86
|
res = options.features.inject(res) do |response, (_name, feature)|
|
|
89
87
|
feature.wrap_response(response)
|
|
@@ -99,26 +97,38 @@ module HTTP
|
|
|
99
97
|
end
|
|
100
98
|
|
|
101
99
|
def close
|
|
102
|
-
@connection
|
|
100
|
+
@connection&.close
|
|
103
101
|
@connection = nil
|
|
104
102
|
@state = :clean
|
|
105
103
|
end
|
|
106
104
|
|
|
107
105
|
private
|
|
108
106
|
|
|
107
|
+
def build_response(req, options)
|
|
108
|
+
Response.new(
|
|
109
|
+
:status => @connection.status_code,
|
|
110
|
+
:version => @connection.http_version,
|
|
111
|
+
:headers => @connection.headers,
|
|
112
|
+
:proxy_headers => @connection.proxy_response_headers,
|
|
113
|
+
:connection => @connection,
|
|
114
|
+
:encoding => options.encoding,
|
|
115
|
+
:request => req
|
|
116
|
+
)
|
|
117
|
+
end
|
|
118
|
+
|
|
109
119
|
# Verify our request isn't going to be made against another URI
|
|
110
120
|
def verify_connection!(uri)
|
|
111
121
|
if default_options.persistent? && uri.origin != default_options.persistent
|
|
112
122
|
raise StateError, "Persistence is enabled for #{default_options.persistent}, but we got #{uri.origin}"
|
|
123
|
+
end
|
|
124
|
+
|
|
113
125
|
# We re-create the connection object because we want to let prior requests
|
|
114
126
|
# lazily load the body as long as possible, and this mimics prior functionality.
|
|
115
|
-
|
|
116
|
-
|
|
127
|
+
return close if @connection && (!@connection.keep_alive? || @connection.expired?)
|
|
128
|
+
|
|
117
129
|
# If we get into a bad state (eg, Timeout.timeout ensure being killed)
|
|
118
130
|
# close the connection to prevent potential for mixed responses.
|
|
119
|
-
|
|
120
|
-
close
|
|
121
|
-
end
|
|
131
|
+
return close if @state == :dirty
|
|
122
132
|
end
|
|
123
133
|
|
|
124
134
|
# Merges query params if needed
|
|
@@ -128,15 +138,11 @@ module HTTP
|
|
|
128
138
|
def make_request_uri(uri, opts)
|
|
129
139
|
uri = uri.to_s
|
|
130
140
|
|
|
131
|
-
if default_options.persistent? && uri !~ HTTP_OR_HTTPS_RE
|
|
132
|
-
uri = "#{default_options.persistent}#{uri}"
|
|
133
|
-
end
|
|
141
|
+
uri = "#{default_options.persistent}#{uri}" if default_options.persistent? && uri !~ HTTP_OR_HTTPS_RE
|
|
134
142
|
|
|
135
143
|
uri = HTTP::URI.parse uri
|
|
136
144
|
|
|
137
|
-
if opts.params && !opts.params.empty?
|
|
138
|
-
uri.query_values = uri.query_values(Array).to_a.concat(opts.params.to_a)
|
|
139
|
-
end
|
|
145
|
+
uri.query_values = uri.query_values(Array).to_a.concat(opts.params.to_a) if opts.params && !opts.params.empty?
|
|
140
146
|
|
|
141
147
|
# Some proxies (seen on WEBRick) fail if URL has
|
|
142
148
|
# empty path (e.g. `http://example.com`) while it's RFC-complaint:
|