httpx 0.8.2 → 0.11.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/LICENSE.txt +48 -0
- data/README.md +14 -4
- data/doc/release_notes/0_10_0.md +66 -0
- data/doc/release_notes/0_10_1.md +37 -0
- data/doc/release_notes/0_10_2.md +5 -0
- data/doc/release_notes/0_11_0.md +76 -0
- data/doc/release_notes/0_9_0.md +38 -0
- data/lib/httpx.rb +2 -0
- data/lib/httpx/adapters/datadog.rb +205 -0
- data/lib/httpx/adapters/faraday.rb +1 -3
- data/lib/httpx/adapters/webmock.rb +123 -0
- data/lib/httpx/chainable.rb +12 -12
- data/lib/httpx/connection.rb +7 -24
- data/lib/httpx/connection/http1.rb +15 -2
- data/lib/httpx/connection/http2.rb +15 -16
- data/lib/httpx/domain_name.rb +438 -0
- data/lib/httpx/errors.rb +4 -1
- data/lib/httpx/extensions.rb +22 -2
- data/lib/httpx/headers.rb +2 -1
- data/lib/httpx/io/ssl.rb +4 -9
- data/lib/httpx/io/tcp.rb +6 -5
- data/lib/httpx/io/udp.rb +5 -2
- data/lib/httpx/options.rb +5 -1
- data/lib/httpx/parser/http1.rb +14 -17
- data/lib/httpx/plugins/compression.rb +28 -63
- data/lib/httpx/plugins/compression/brotli.rb +10 -14
- data/lib/httpx/plugins/compression/deflate.rb +7 -6
- data/lib/httpx/plugins/compression/gzip.rb +23 -5
- data/lib/httpx/plugins/cookies.rb +21 -60
- data/lib/httpx/plugins/cookies/cookie.rb +173 -0
- data/lib/httpx/plugins/cookies/jar.rb +74 -0
- data/lib/httpx/plugins/cookies/set_cookie_parser.rb +142 -0
- data/lib/httpx/plugins/expect.rb +34 -11
- data/lib/httpx/plugins/follow_redirects.rb +20 -2
- data/lib/httpx/plugins/h2c.rb +1 -1
- data/lib/httpx/plugins/multipart.rb +41 -30
- data/lib/httpx/plugins/multipart/encoder.rb +115 -0
- data/lib/httpx/plugins/multipart/mime_type_detector.rb +64 -0
- data/lib/httpx/plugins/multipart/part.rb +34 -0
- data/lib/httpx/plugins/persistent.rb +6 -1
- data/lib/httpx/plugins/proxy.rb +16 -2
- data/lib/httpx/plugins/proxy/socks4.rb +14 -14
- data/lib/httpx/plugins/proxy/socks5.rb +3 -2
- data/lib/httpx/plugins/push_promise.rb +2 -2
- data/lib/httpx/plugins/rate_limiter.rb +51 -0
- data/lib/httpx/plugins/retries.rb +3 -2
- data/lib/httpx/plugins/stream.rb +109 -13
- data/lib/httpx/pool.rb +14 -20
- data/lib/httpx/request.rb +29 -31
- data/lib/httpx/resolver.rb +7 -6
- data/lib/httpx/resolver/https.rb +25 -25
- data/lib/httpx/resolver/native.rb +29 -22
- data/lib/httpx/resolver/resolver_mixin.rb +4 -2
- data/lib/httpx/resolver/system.rb +3 -3
- data/lib/httpx/response.rb +16 -25
- data/lib/httpx/selector.rb +12 -18
- data/lib/httpx/session.rb +50 -39
- data/lib/httpx/transcoder.rb +20 -0
- data/lib/httpx/transcoder/chunker.rb +0 -2
- data/lib/httpx/transcoder/form.rb +9 -7
- data/lib/httpx/transcoder/json.rb +0 -4
- data/lib/httpx/utils.rb +45 -0
- data/lib/httpx/version.rb +1 -1
- data/sig/buffer.rbs +24 -0
- data/sig/callbacks.rbs +14 -0
- data/sig/chainable.rbs +37 -0
- data/sig/connection.rbs +85 -0
- data/sig/connection/http1.rbs +66 -0
- data/sig/connection/http2.rbs +77 -0
- data/sig/domain_name.rbs +17 -0
- data/sig/errors.rbs +3 -0
- data/sig/headers.rbs +45 -0
- data/sig/httpx.rbs +15 -0
- data/sig/loggable.rbs +11 -0
- data/sig/options.rbs +118 -0
- data/sig/parser/http1.rbs +50 -0
- data/sig/plugins/authentication.rbs +11 -0
- data/sig/plugins/basic_authentication.rbs +13 -0
- data/sig/plugins/compression.rbs +55 -0
- data/sig/plugins/compression/brotli.rbs +21 -0
- data/sig/plugins/compression/deflate.rbs +17 -0
- data/sig/plugins/compression/gzip.rbs +29 -0
- data/sig/plugins/cookies.rbs +26 -0
- data/sig/plugins/cookies/cookie.rbs +50 -0
- data/sig/plugins/cookies/jar.rbs +27 -0
- data/sig/plugins/digest_authentication.rbs +33 -0
- data/sig/plugins/expect.rbs +19 -0
- data/sig/plugins/follow_redirects.rbs +37 -0
- data/sig/plugins/h2c.rbs +26 -0
- data/sig/plugins/multipart.rbs +44 -0
- data/sig/plugins/persistent.rbs +17 -0
- data/sig/plugins/proxy.rbs +47 -0
- data/sig/plugins/proxy/http.rbs +14 -0
- data/sig/plugins/proxy/socks4.rbs +33 -0
- data/sig/plugins/proxy/socks5.rbs +36 -0
- data/sig/plugins/proxy/ssh.rbs +18 -0
- data/sig/plugins/push_promise.rbs +22 -0
- data/sig/plugins/rate_limiter.rbs +11 -0
- data/sig/plugins/retries.rbs +48 -0
- data/sig/plugins/stream.rbs +39 -0
- data/sig/pool.rbs +36 -0
- data/sig/registry.rbs +9 -0
- data/sig/request.rbs +61 -0
- data/sig/resolver.rbs +26 -0
- data/sig/resolver/https.rbs +51 -0
- data/sig/resolver/native.rbs +60 -0
- data/sig/resolver/resolver_mixin.rbs +27 -0
- data/sig/resolver/system.rbs +17 -0
- data/sig/response.rbs +87 -0
- data/sig/selector.rbs +20 -0
- data/sig/session.rbs +49 -0
- data/sig/timeout.rbs +29 -0
- data/sig/transcoder.rbs +18 -0
- data/sig/transcoder/body.rbs +20 -0
- data/sig/transcoder/chunker.rbs +32 -0
- data/sig/transcoder/form.rbs +22 -0
- data/sig/transcoder/json.rbs +16 -0
- metadata +81 -41
- data/lib/httpx/resolver/options.rb +0 -25
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e5a33fd07fae25308cb791a086313c8dd8aa05cc7bc24504c92c17e20b692688
|
|
4
|
+
data.tar.gz: 8be24aad50c50bfea6667a94f7afade82dada7d2512177430ea5b04593f2e296
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3b03f47c4ef852af01d9d4eb6895921e6601d33e8c0261b25e34309c663c481a77ce9c5161124efdb02518b1a7c89f3e3440b823348106d492e3d27daf66ab6e
|
|
7
|
+
data.tar.gz: e4b2961e9d0b6d11348cf81eae7dbb0e744878c47a51ef584429ab89f32eadc24f9f195ceeb68ecfcb553c19b2a333818cba0e867c0cb992bec66b99dcd1def7
|
data/LICENSE.txt
CHANGED
|
@@ -189,3 +189,51 @@
|
|
|
189
189
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
190
190
|
See the License for the specific language governing permissions and
|
|
191
191
|
limitations under the License.
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
* lib/httpx/domain_name.rb
|
|
195
|
+
|
|
196
|
+
This file is derived from the implementation of punycode available at
|
|
197
|
+
here:
|
|
198
|
+
|
|
199
|
+
https://www.verisign.com/en_US/channel-resources/domain-registry-products/idn-sdks/index.xhtml
|
|
200
|
+
|
|
201
|
+
Copyright (C) 2000-2002 Verisign Inc., All rights reserved.
|
|
202
|
+
|
|
203
|
+
Redistribution and use in source and binary forms, with or
|
|
204
|
+
without modification, are permitted provided that the following
|
|
205
|
+
conditions are met:
|
|
206
|
+
|
|
207
|
+
1) Redistributions of source code must retain the above copyright
|
|
208
|
+
notice, this list of conditions and the following disclaimer.
|
|
209
|
+
|
|
210
|
+
2) Redistributions in binary form must reproduce the above copyright
|
|
211
|
+
notice, this list of conditions and the following disclaimer in
|
|
212
|
+
the documentation and/or other materials provided with the
|
|
213
|
+
distribution.
|
|
214
|
+
|
|
215
|
+
3) Neither the name of the VeriSign Inc. nor the names of its
|
|
216
|
+
contributors may be used to endorse or promote products derived
|
|
217
|
+
from this software without specific prior written permission.
|
|
218
|
+
|
|
219
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
220
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
221
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
222
|
+
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
223
|
+
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
224
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
225
|
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
226
|
+
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
227
|
+
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
228
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
229
|
+
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
230
|
+
POSSIBILITY OF SUCH DAMAGE.
|
|
231
|
+
|
|
232
|
+
This software is licensed under the BSD open source license. For more
|
|
233
|
+
information visit www.opensource.org.
|
|
234
|
+
|
|
235
|
+
Authors:
|
|
236
|
+
John Colosi (VeriSign)
|
|
237
|
+
Srikanth Veeramachaneni (VeriSign)
|
|
238
|
+
Nagesh Chigurupati (Verisign)
|
|
239
|
+
Praveen Srinivasan(Verisign)
|
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# HTTPX: A Ruby HTTP library for tomorrow... and beyond!
|
|
2
2
|
|
|
3
3
|
[](http://rubygems.org/gems/httpx)
|
|
4
|
-
[](https://gitlab.com/honeyryderchuck/httpx/
|
|
5
|
-
[](https://honeyryderchuck.gitlab.io/httpx/coverage/#_AllFiles)
|
|
4
|
+
[](https://gitlab.com/honeyryderchuck/httpx/pipelines?page=1&scope=all&ref=master)
|
|
5
|
+
[](https://honeyryderchuck.gitlab.io/httpx/coverage/#_AllFiles)
|
|
6
6
|
|
|
7
7
|
HTTPX is an HTTP client library for the Ruby programming language.
|
|
8
8
|
|
|
@@ -18,6 +18,7 @@ Among its features, it supports:
|
|
|
18
18
|
And also:
|
|
19
19
|
|
|
20
20
|
* Compression (gzip, deflate, brotli)
|
|
21
|
+
* Streaming Requests
|
|
21
22
|
* Authentication (Basic Auth, Digest Auth)
|
|
22
23
|
* Expect 100-continue
|
|
23
24
|
* Multipart Requests
|
|
@@ -25,6 +26,7 @@ And also:
|
|
|
25
26
|
* HTTP/2 Server Push
|
|
26
27
|
* H2C Upgrade
|
|
27
28
|
* Automatic follow redirects
|
|
29
|
+
* International Domain Names
|
|
28
30
|
|
|
29
31
|
## How
|
|
30
32
|
|
|
@@ -83,7 +85,15 @@ However if the server supports HTTP/1.1, it will try to use HTTP pipelining, fal
|
|
|
83
85
|
|
|
84
86
|
### Clean API
|
|
85
87
|
|
|
86
|
-
`
|
|
88
|
+
`httpx` builds all functions around the `HTTPX` module, so that all calls can compose of each other. Here are a few examples:
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
response = HTTPX.get("https://www.google.com")
|
|
92
|
+
response = HTTPX.post("https://www.nghttp2.org/httpbin/post", params: {name: "John", age: "22"})
|
|
93
|
+
response = HTTPX.plugin(:basic_authentication)
|
|
94
|
+
.basic_authentication("user", "pass")
|
|
95
|
+
.get("https://www.google.com")
|
|
96
|
+
```
|
|
87
97
|
|
|
88
98
|
### Lightweight
|
|
89
99
|
|
|
@@ -133,7 +143,7 @@ Doesn't work with ruby 2.4.0 for Windows (see [#36](https://gitlab.com/honeyryde
|
|
|
133
143
|
|
|
134
144
|
* Discuss your contribution in an issue
|
|
135
145
|
* Fork it
|
|
136
|
-
* Make your changes, add some
|
|
146
|
+
* Make your changes, add some tests
|
|
137
147
|
* Ensure all tests pass (`bundle exec rake test`)
|
|
138
148
|
* Open a Merge Request (that's Pull Request in Github-ish)
|
|
139
149
|
* Wait for feedback
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# 0.10.0
|
|
2
|
+
|
|
3
|
+
## Features
|
|
4
|
+
|
|
5
|
+
### Streaming Requests
|
|
6
|
+
|
|
7
|
+
The `stream` plugin adds functionality to handle long-lived stream responses, such as the Twitter Streaming API:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
http = HTTPX.plugin(:stream)
|
|
11
|
+
|
|
12
|
+
http.get(stream_api_endpoint, stream: true).each_line do |line|
|
|
13
|
+
payload = JSON.parse(line)
|
|
14
|
+
# do smth with this
|
|
15
|
+
end
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
https://gitlab.com/honeyryderchuck/httpx/-/wikis/Stream
|
|
19
|
+
|
|
20
|
+
### Rate Limiter
|
|
21
|
+
|
|
22
|
+
The `rate_limiter` plugin adds functionality for automatically hooking into rate-limiting responses coming from the server, and waits-and-retries them according to what the server advertises.
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
HTTPX.plugin(:rate_limiter).get(rate_limited_api_endpoint)
|
|
26
|
+
# => 429 Too Many Requests .... Retry-After: 3
|
|
27
|
+
# waits 3 seconds before retrying
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
https://gitlab.com/honeyryderchuck/httpx/-/wikis/Rate-Limiter
|
|
31
|
+
|
|
32
|
+
### Ruby 3
|
|
33
|
+
|
|
34
|
+
This release is the first testing against and targeting Ruby 3 and some of the new features.
|
|
35
|
+
|
|
36
|
+
It ships with RBS signatures for all of the client-facing APIs. There's non 100% typinng coverage yet, but I'm gradually (pun intended) working on it.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
## Improvements
|
|
40
|
+
|
|
41
|
+
### IDN support
|
|
42
|
+
|
|
43
|
+
Requests where the domains are formed by non-ASCII characters, are now supported (if you're using ruby 2.3 or more recent).
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
HTTPX.get("http://bücher.ch") # it works!
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### cookies plugin full implementation
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
The `cookies` plugin is now independent of 3rd-party gems. The motivation for this was that `http-cookie` was dependent of both `domain_name` and `unf` gems, which are currently unusable in ruby 3, and haven't received any update in the last 3 years.
|
|
53
|
+
|
|
54
|
+
The implementation is still compliant with RFC6265, and all of the features provided in earlier versions were ported, exceptwhen loading the cookie jar stored in a Netscape-format file or Mozilla sqlite database, which were not documented for `httpx` anyway, and I considered too niche to backport. If you feel `httpx` should support those, do let me know.
|
|
55
|
+
|
|
56
|
+
Some code from these gems, including the ruby punycode implementation, is now part of the source tree, along with its licenses and attribution mentions.
|
|
57
|
+
|
|
58
|
+
## Bugfixes
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
Several edge-case bugs have been fixed solely by the integration of RBS runtime type checking, including some bugs around closing a connection pool that can cause loops.
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## Regressions
|
|
65
|
+
|
|
66
|
+
`HTTPX::ErrorResponse`'s methods `#headers` and `#reason` were removed, as they didn't provide much value. Consider calling `#raise_for_status` or checking the API (`is_a?(HTTPX::ErrorResponse)` or `respond_to?(:error)` are strategies for this).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# 0.10.1
|
|
2
|
+
|
|
3
|
+
## Improvements
|
|
4
|
+
|
|
5
|
+
### URL-encoded nested params
|
|
6
|
+
|
|
7
|
+
url encoder now supports nested params, which is a standard of rack-based frameworks:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
HTTPX.post("https://httpbin.org/post", form: { a: { b: 1 }, c: [2, 3] })
|
|
11
|
+
# a[b]=1&c[]=2&c[]=3
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
This encoding scheme is now the standard for URL-encoded request bodies, query params, and `:multipart` plugin requests.
|
|
15
|
+
|
|
16
|
+
### Socks4 IPv6 addresses
|
|
17
|
+
|
|
18
|
+
HTTPX supports IPv6 Socks4 proxies now. This support is restricted to rubies where `IPAddr#hton` is implemented though, so you are encouraged to upgrade.
|
|
19
|
+
|
|
20
|
+
## More verbose HTTP Errors
|
|
21
|
+
|
|
22
|
+
`HTTPX::Response#raise_for_status` was raising exceptions for client/server HTTP errors codes (4xx/5xx). However, only the status code was part of the message.
|
|
23
|
+
|
|
24
|
+
From now on, both headers and the responnse payload will also appear, so expected more verbosity, but also more meaningful information.
|
|
25
|
+
|
|
26
|
+
## Bugfixes
|
|
27
|
+
|
|
28
|
+
* HTTP/2 and HTTP/1.1 exhausted connections now get properly migrated into a new connection;
|
|
29
|
+
* HTTP/2 421 responses will now correctly migrate the connection and pendign requests to HTTP/1.1 (a hanging loop was being caused);
|
|
30
|
+
* HTTP/2 connection failed with a GOAWAY settings timeout will now return error responses (instead of hanging indefinitely);
|
|
31
|
+
* Non-IP proxy name-resolving errors will now move on to the next available proxy in the list (instead of hanging indefinitely);
|
|
32
|
+
* Non-IP DNS resolve errors for `native` and `https` variants will now return the appropriate error response (instead of hanging indefinitely);
|
|
33
|
+
|
|
34
|
+
## Chore
|
|
35
|
+
|
|
36
|
+
* `HTTPX.plugins` is now officially deprecated (use `HTTPX.plugin` instead);
|
|
37
|
+
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# 0.11.0
|
|
2
|
+
|
|
3
|
+
## Features
|
|
4
|
+
|
|
5
|
+
### Webmock Adapter
|
|
6
|
+
|
|
7
|
+
`httpx` can now be integrated with `webmock`, a popular HTTP requests stubbing library.
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
# minitest
|
|
11
|
+
require "webmock/minitest"
|
|
12
|
+
require "httpx/adapters/webmock"
|
|
13
|
+
|
|
14
|
+
# in rspec
|
|
15
|
+
require "webmock/rspec"
|
|
16
|
+
require "httpx/adapters/webmock"
|
|
17
|
+
|
|
18
|
+
# and now you're free for mocking
|
|
19
|
+
WebMock.enable!
|
|
20
|
+
stub_http_request(:get, "https://www.google.com").and_return(status: 200, body: "here's google")
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Read more about it in the [webmock integration documentation](https://honeyryderchuck.gitlab.io/httpx/wiki/Webmock-Adapter).
|
|
25
|
+
|
|
26
|
+
### Datadog Adapter
|
|
27
|
+
|
|
28
|
+
`httpx` ships with integration for [ddtrace, datadog's official tracing client](https://github.com/DataDog/dd-trace-rb). You just need to initialize it the following way:
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
require "ddtrace"
|
|
32
|
+
require "httpx/adapters/datadog"
|
|
33
|
+
|
|
34
|
+
Datadog.configure do |c|
|
|
35
|
+
c.use :httpx
|
|
36
|
+
end
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
A trace will be emitted for every request, so this should be an interesting visualization if concurrent requests are sent.
|
|
40
|
+
|
|
41
|
+
Customization options and traces are similar to what [the net-http adapter provides](https://docs.datadoghq.com/tracing/setup_overview/setup/ruby/#nethttp).
|
|
42
|
+
|
|
43
|
+
Read more about it in the [datadog integration documentation](https://honeyryderchuck.gitlab.io/httpx/wiki/Datadog-Adapter).
|
|
44
|
+
|
|
45
|
+
## Improvements
|
|
46
|
+
|
|
47
|
+
### Own multipart request encoder
|
|
48
|
+
|
|
49
|
+
`httpx` now ships with its own multipart formdata encoder, and does not rely on `http-form_data` anymore:
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
HTTPX.plugin(:multipart).post(uri, form: {file: File.new("path/to/file")})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Read more about it in the [multipart plugin documentation](https://honeyryderchuck.gitlab.io/httpx/wiki/Multipart-Uploads), including also about why this was made.
|
|
56
|
+
|
|
57
|
+
### Expect Plugin
|
|
58
|
+
|
|
59
|
+
The `:expect` plugin now works reliably when the server does not support the `expect: 100-continue` header, i.e. it'll upload the body after a certain timeout. Building onn that, two behaviours are now implemented:
|
|
60
|
+
|
|
61
|
+
* A cache of domains which did not respond to the `expect` header is now kept, so that subsequent requests can skip the timeout and immediately upload the payload.
|
|
62
|
+
* If the "100 Continue" response arrives **after** the timeout expired and the body has been uploaded, the domain is removed from the cache, and subsequent requests will send the `expect` header.
|
|
63
|
+
|
|
64
|
+
### SNI/Host options
|
|
65
|
+
|
|
66
|
+
Some extension of the API was applied in order to support custom TLS negotiation parameters. You can now pass `:hostname` under the `:ssl` options, and this will be used for the SNI part of the TLS negotiation. This is useful in scenarios where a proxy certificate doesn't apply for the host one wants to send the request to:
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
response = session.get(proxy_ip, headers: { "host" => upstream_hostname }, ssl: { hostname: sni_hostname }
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Bugfixes
|
|
73
|
+
|
|
74
|
+
A default 5 second timeout is in-place when using the DNS `:system` resolver, as it was found out that. when using the `resolv` library, the DNS query will not be retried otherwise. You can change this setting py passing `resolver_options: { timeouts: ANOTHER_TIMEOUT}`. In the future, this may become another timeout option, however.
|
|
75
|
+
|
|
76
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# 0.9.0
|
|
2
|
+
|
|
3
|
+
## Features
|
|
4
|
+
|
|
5
|
+
### Multiple requests with specific options
|
|
6
|
+
|
|
7
|
+
You can now pass a third element to the "request element" of an array to `.request`.
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
requests = [
|
|
11
|
+
[:post, "https://url/post", { form: { foo: "bar" } }],
|
|
12
|
+
[:post, "https://url/post", { form: { foo: "bar2" } }]
|
|
13
|
+
]
|
|
14
|
+
HTTPX.request(requests)
|
|
15
|
+
# or, if you want to pass options common to all requests
|
|
16
|
+
HTTPX.request(requests, max_concurrent_requests: 1)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### HTTPX::Session#build_request
|
|
21
|
+
|
|
22
|
+
`HTTPX::Session::build_request` is now public API from a session. You can now build requests before you send them. These request objects are still considered somewhat "internal", so consider them immutable and **do not rely on its API**. Just pass them forward.
|
|
23
|
+
|
|
24
|
+
Note: this API is only available for instantiated session, so there is no `HTTPX.build_request`.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
|
|
29
|
+
HTTPX.wrap do |http|
|
|
30
|
+
requests = [
|
|
31
|
+
http.build_request(:post, "https://url/post", { form: { foo: "bar" } }),
|
|
32
|
+
http.build_request(:post, "https://url/post", { form: { foo: "bar2" } })
|
|
33
|
+
]
|
|
34
|
+
http.request(requests)
|
|
35
|
+
# or, if you want to pass options common to all requests
|
|
36
|
+
http.request(requests, max_concurrent_requests: 1)
|
|
37
|
+
end
|
|
38
|
+
```
|
data/lib/httpx.rb
CHANGED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ddtrace/contrib/integration"
|
|
4
|
+
require "ddtrace/contrib/rest_client/configuration/settings"
|
|
5
|
+
require "ddtrace/contrib/rest_client/patcher"
|
|
6
|
+
|
|
7
|
+
module Datadog
|
|
8
|
+
module Contrib
|
|
9
|
+
module HTTPX
|
|
10
|
+
# HTTPX Datadog Plugin
|
|
11
|
+
#
|
|
12
|
+
# Enables tracing for httpx requests. A span will be created for each individual requests,
|
|
13
|
+
# and it'll trace since the moment it is fed to the connection, until the moment the response is
|
|
14
|
+
# fed back to the session.
|
|
15
|
+
#
|
|
16
|
+
module Plugin
|
|
17
|
+
class RequestTracer
|
|
18
|
+
SPAN_REQUEST = "httpx.request"
|
|
19
|
+
|
|
20
|
+
def initialize(request)
|
|
21
|
+
@request = request
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def call
|
|
25
|
+
return if skip_tracing?
|
|
26
|
+
|
|
27
|
+
@request.on(:response, &method(:finish))
|
|
28
|
+
|
|
29
|
+
verb = @request.verb.to_s.upcase
|
|
30
|
+
uri = @request.uri
|
|
31
|
+
|
|
32
|
+
@span = datadog_pin.tracer.trace(SPAN_REQUEST)
|
|
33
|
+
service_name = datadog_config[:split_by_domain] ? uri.host : datadog_pin.service_name
|
|
34
|
+
|
|
35
|
+
begin
|
|
36
|
+
@span.service = service_name
|
|
37
|
+
@span.span_type = Datadog::Ext::HTTP::TYPE_OUTBOUND
|
|
38
|
+
@span.resource = verb
|
|
39
|
+
|
|
40
|
+
Datadog::HTTPPropagator.inject!(@span.context, @request.headers) if datadog_pin.tracer.enabled && !skip_distributed_tracing?
|
|
41
|
+
|
|
42
|
+
# Add additional request specific tags to the span.
|
|
43
|
+
|
|
44
|
+
@span.set_tag(Datadog::Ext::HTTP::URL, @request.path)
|
|
45
|
+
@span.set_tag(Datadog::Ext::HTTP::METHOD, verb)
|
|
46
|
+
|
|
47
|
+
@span.set_tag(Datadog::Ext::NET::TARGET_HOST, uri.host)
|
|
48
|
+
@span.set_tag(Datadog::Ext::NET::TARGET_PORT, uri.port.to_s)
|
|
49
|
+
|
|
50
|
+
# Tag as an external peer service
|
|
51
|
+
@span.set_tag(Datadog::Ext::Integration::TAG_PEER_SERVICE, @span.service)
|
|
52
|
+
|
|
53
|
+
# Set analytics sample rate
|
|
54
|
+
if Contrib::Analytics.enabled?(datadog_config[:analytics_enabled])
|
|
55
|
+
Contrib::Analytics.set_sample_rate(@span, datadog_config[:analytics_sample_rate])
|
|
56
|
+
end
|
|
57
|
+
rescue StandardError => e
|
|
58
|
+
Datadog.logger.error("error preparing span for http request: #{e}")
|
|
59
|
+
end
|
|
60
|
+
rescue StandardError => e
|
|
61
|
+
Datadog.logger.debug("Failed to start span: #{e}")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def finish(response)
|
|
65
|
+
return unless @span
|
|
66
|
+
|
|
67
|
+
if response.respond_to?(:error)
|
|
68
|
+
@span.set_error(response.error)
|
|
69
|
+
else
|
|
70
|
+
@span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, response.status.to_s)
|
|
71
|
+
|
|
72
|
+
@span.set_error(::HTTPX::HTTPError.new(response)) if response.status >= 400 && response.status <= 599
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
@span.finish
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def skip_tracing?
|
|
81
|
+
return true if @request.headers.key?(Datadog::Ext::Transport::HTTP::HEADER_META_TRACER_VERSION)
|
|
82
|
+
|
|
83
|
+
return false unless @datadog_pin
|
|
84
|
+
|
|
85
|
+
span = @datadog_pin.tracer.active_span
|
|
86
|
+
|
|
87
|
+
return true if span && (span.name == SPAN_REQUEST)
|
|
88
|
+
|
|
89
|
+
false
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def skip_distributed_tracing?
|
|
93
|
+
return !datadog_pin.config[:distributed_tracing] if datadog_pin.config && datadog_pin.config.key?(:distributed_tracing)
|
|
94
|
+
|
|
95
|
+
!Datadog.configuration[:httpx][:distributed_tracing]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def datadog_pin
|
|
99
|
+
@datadog_pin ||= begin
|
|
100
|
+
service = datadog_config[:service_name]
|
|
101
|
+
tracer = datadog_config[:tracer]
|
|
102
|
+
|
|
103
|
+
Datadog::Pin.new(
|
|
104
|
+
service,
|
|
105
|
+
app: "httpx",
|
|
106
|
+
app_type: Datadog::Ext::AppTypes::WEB,
|
|
107
|
+
tracer: -> { tracer }
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def datadog_config
|
|
113
|
+
@datadog_config ||= Datadog.configuration[:httpx, @request.uri.host]
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
module ConnectionMethods
|
|
118
|
+
def send(request)
|
|
119
|
+
RequestTracer.new(request).call
|
|
120
|
+
super
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
module Configuration
|
|
126
|
+
# Default settings for httpx
|
|
127
|
+
#
|
|
128
|
+
class Settings < Datadog::Contrib::Configuration::Settings
|
|
129
|
+
option :service_name, default: "httpx"
|
|
130
|
+
option :distributed_tracing, default: true
|
|
131
|
+
option :split_by_domain, default: false
|
|
132
|
+
|
|
133
|
+
option :enabled do |o|
|
|
134
|
+
o.default { env_to_bool("DD_TRACE_HTTPX_ENABLED", true) }
|
|
135
|
+
o.lazy
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
option :analytics_enabled do |o|
|
|
139
|
+
o.default { env_to_bool(%w[DD_TRACE_HTTPX_ANALYTICS_ENABLED DD_HTTPX_ANALYTICS_ENABLED], false) }
|
|
140
|
+
o.lazy
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
option :analytics_sample_rate do |o|
|
|
144
|
+
o.default { env_to_float(%w[DD_TRACE_HTTPX_ANALYTICS_SAMPLE_RATE DD_HTTPX_ANALYTICS_SAMPLE_RATE], 1.0) }
|
|
145
|
+
o.lazy
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
option :error_handler, default: Datadog::Tracer::DEFAULT_ON_ERROR
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Patcher enables patching of 'httpx' with datadog components.
|
|
153
|
+
#
|
|
154
|
+
module Patcher
|
|
155
|
+
include Datadog::Contrib::Patcher
|
|
156
|
+
|
|
157
|
+
module_function
|
|
158
|
+
|
|
159
|
+
def target_version
|
|
160
|
+
Integration.version
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# loads a session instannce with the datadog plugin, and replaces the
|
|
164
|
+
# base HTTPX::Session with the patched session class.
|
|
165
|
+
def patch
|
|
166
|
+
datadog_session = ::HTTPX.plugin(Plugin)
|
|
167
|
+
|
|
168
|
+
::HTTPX.send(:remove_const, :Session)
|
|
169
|
+
::HTTPX.send(:const_set, :Session, datadog_session.class)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Datadog Integration for HTTPX.
|
|
174
|
+
#
|
|
175
|
+
class Integration
|
|
176
|
+
include Contrib::Integration
|
|
177
|
+
|
|
178
|
+
# MINIMUM_VERSION = Gem::Version.new('0.11.0')
|
|
179
|
+
MINIMUM_VERSION = Gem::Version.new("0.10.2")
|
|
180
|
+
|
|
181
|
+
register_as :httpx
|
|
182
|
+
|
|
183
|
+
def self.version
|
|
184
|
+
Gem.loaded_specs["httpx"] && Gem.loaded_specs["httpx"].version
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def self.loaded?
|
|
188
|
+
defined?(::HTTPX::Request)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def self.compatible?
|
|
192
|
+
super && version >= MINIMUM_VERSION
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def default_configuration
|
|
196
|
+
Configuration::Settings.new
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def patcher
|
|
200
|
+
Patcher
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|