httpx 0.22.4 → 0.23.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/doc/release_notes/0_22_5.md +6 -0
- data/doc/release_notes/0_23_0.md +42 -0
- data/lib/httpx/adapters/datadog.rb +12 -2
- data/lib/httpx/adapters/faraday.rb +1 -1
- data/lib/httpx/adapters/sentry.rb +15 -5
- data/lib/httpx/adapters/webmock.rb +2 -2
- data/lib/httpx/buffer.rb +4 -0
- data/lib/httpx/callbacks.rb +3 -3
- data/lib/httpx/chainable.rb +4 -4
- data/lib/httpx/connection/http1.rb +2 -2
- data/lib/httpx/connection/http2.rb +2 -3
- data/lib/httpx/connection.rb +31 -11
- data/lib/httpx/io/udp.rb +2 -0
- data/lib/httpx/io/unix.rb +1 -5
- data/lib/httpx/io.rb +0 -10
- data/lib/httpx/options.rb +16 -2
- data/lib/httpx/plugins/authentication/digest.rb +1 -1
- data/lib/httpx/plugins/aws_sdk_authentication.rb +1 -3
- data/lib/httpx/plugins/aws_sigv4.rb +1 -1
- data/lib/httpx/plugins/compression/brotli.rb +4 -4
- data/lib/httpx/plugins/compression/deflate.rb +12 -7
- data/lib/httpx/plugins/compression/gzip.rb +7 -5
- data/lib/httpx/plugins/compression.rb +9 -8
- data/lib/httpx/plugins/digest_authentication.rb +1 -4
- data/lib/httpx/plugins/follow_redirects.rb +1 -1
- data/lib/httpx/plugins/grpc/message.rb +3 -1
- data/lib/httpx/plugins/grpc.rb +3 -3
- data/lib/httpx/plugins/h2c.rb +5 -9
- data/lib/httpx/plugins/internal_telemetry.rb +16 -0
- data/lib/httpx/plugins/multipart.rb +14 -2
- data/lib/httpx/plugins/proxy/http.rb +4 -4
- data/lib/httpx/plugins/proxy.rb +65 -31
- data/lib/httpx/plugins/response_cache.rb +2 -2
- data/lib/httpx/plugins/retries.rb +49 -2
- data/lib/httpx/plugins/upgrade/h2.rb +3 -3
- data/lib/httpx/plugins/upgrade.rb +4 -7
- data/lib/httpx/plugins/webdav.rb +7 -7
- data/lib/httpx/pool.rb +7 -3
- data/lib/httpx/request.rb +23 -13
- data/lib/httpx/resolver/https.rb +37 -20
- data/lib/httpx/resolver/multi.rb +1 -6
- data/lib/httpx/resolver/native.rb +128 -36
- data/lib/httpx/resolver.rb +26 -14
- data/lib/httpx/response.rb +14 -16
- data/lib/httpx/session.rb +1 -0
- data/lib/httpx/transcoder/body.rb +0 -1
- data/lib/httpx/transcoder/chunker.rb +0 -1
- data/lib/httpx/transcoder/form.rb +0 -1
- data/lib/httpx/transcoder/json.rb +0 -1
- data/lib/httpx/transcoder/xml.rb +0 -1
- data/lib/httpx/transcoder.rb +0 -2
- data/lib/httpx/version.rb +1 -1
- data/lib/httpx.rb +0 -1
- data/sig/buffer.rbs +1 -0
- data/sig/chainable.rbs +3 -3
- data/sig/connection.rbs +17 -6
- data/sig/errors.rbs +9 -0
- data/sig/httpx.rbs +3 -3
- data/sig/io/ssl.rbs +17 -0
- data/sig/io/tcp.rbs +57 -0
- data/sig/io/udp.rbs +20 -0
- data/sig/io/unix.rbs +10 -0
- data/sig/options.rbs +5 -1
- data/sig/plugins/compression.rbs +6 -2
- data/sig/plugins/cookies/jar.rbs +2 -2
- data/sig/plugins/grpc.rbs +3 -3
- data/sig/plugins/h2c.rbs +1 -1
- data/sig/plugins/proxy.rbs +1 -5
- data/sig/plugins/response_cache.rbs +1 -1
- data/sig/plugins/retries.rbs +28 -8
- data/sig/plugins/upgrade.rbs +5 -3
- data/sig/request.rbs +6 -2
- data/sig/resolver/https.rbs +3 -1
- data/sig/resolver/native.rbs +7 -2
- data/sig/resolver/resolver.rbs +0 -2
- data/sig/resolver/system.rbs +2 -0
- data/sig/resolver.rbs +8 -4
- data/sig/response.rbs +6 -2
- data/sig/session.rbs +10 -10
- data/sig/transcoder/xml.rbs +1 -1
- data/sig/transcoder.rbs +4 -5
- metadata +11 -5
- data/lib/httpx/registry.rb +0 -85
- data/sig/registry.rbs +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71f84ab5eb126b7c22ceeabf6ef36935e678376ad79e3585a1c8af0cdadcb36c
|
4
|
+
data.tar.gz: 98169826112b92768e6592ec9dcc5a0ebf0dcc34f063a4480d17b4ee4bc3f345
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ebd7512c81d95e87284d5a622d473df66a618597b502eccb17cb7ec738364f46d2dec85b1b63940b6182356ccd11caaef0867f56f671320d3a9f9c04e6ad47b
|
7
|
+
data.tar.gz: e98bb305329b8982414eb95d2455ef436703ba328175ddd383170c68463aa7d1b83721ac9ffd74fdd91190b0ce055668eac8c67c23648ac7493dfdc01d96e3a6
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# 0.22.5
|
2
|
+
|
3
|
+
## Bugfixes
|
4
|
+
|
5
|
+
* `datadog` and `sentry` integrations did not account for `Connection#send` being possibly called multiple times (something possible for connection coalescing, max requests exhaustion, or Happy Eyeballs 2), and were registering multiple `on(:response)` callbacks. Requests are now marked when decorated the first time.
|
6
|
+
* Happy Eyeballs handshake "connect errors" routine is now taking both name resolution errors, as well as TLS handshake errors, into account, when the handshake fails.
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# 0.23.0
|
2
|
+
|
3
|
+
## Features
|
4
|
+
|
5
|
+
### `:retries` plugin: resumable requests
|
6
|
+
|
7
|
+
The `:retries` plugin will now support scenarios where, if the request being retried supports the `range` header, and a partial response has been already buffered, the retry will resume from there and only download the missing data.
|
8
|
+
|
9
|
+
#### HTTPX::ErrorResponse#response
|
10
|
+
|
11
|
+
As a result, ´HTTPX::ErrorResponse#response` has also been introduced; error responses may have an actual response. This happens in cases where the request failed **after** a partial response was initiated.
|
12
|
+
|
13
|
+
#### `:buffer_size` option
|
14
|
+
|
15
|
+
A nnew option, `:buffer_size`, can be used to tweak the buffers used by the read/write socket routines (16k by default, you can lower it in memory-constrained environments).
|
16
|
+
|
17
|
+
## Improvements
|
18
|
+
|
19
|
+
### `:native` resolver falls back to TCP for truncated messages
|
20
|
+
|
21
|
+
The `:native` resolver will repeat DNS queries to a nameserver via TCP when the first attempt is marked as truncated. This behaviour is both aligned with `getaddrinfo` and the `resolv` standard library.
|
22
|
+
|
23
|
+
This introduces a new `resolver_options` option, `:socket_type`, which can now be `:tcp` if it is to remain the default.
|
24
|
+
|
25
|
+
## Chore
|
26
|
+
|
27
|
+
### HTTPX.build_request should receive upcased string (i.e. "GET")
|
28
|
+
|
29
|
+
Functions which receive an HTTP verb should be given he verb in "upcased string" format now. The usage of symbols is still possible, but a deprecation warning will be emitted, and support will be removed in v1.0.0 .
|
30
|
+
|
31
|
+
### Remove HTTPX::Registry
|
32
|
+
|
33
|
+
These internal registries were a bit magical to use, difficult to debug, not thread-safe, and overall a nuisance when it came to type checking. While there is the possibility that someone was relying on it existing, nothing had ever been publicly documented.
|
34
|
+
|
35
|
+
## Bugfixes
|
36
|
+
|
37
|
+
* fixed proxy discovery using proxy env vars (`HTTPS_PROXY`, `NO_PROXY`...) being enabled/disabled based on first host uused in the session;
|
38
|
+
* fixed `:no_proxy` option usage inn the `:proxy` plugin.
|
39
|
+
* fixed `webmock` adapter to correctly disable it when `Webmock.disable!` is called.
|
40
|
+
* fixed bug in `:digest_authentication` plugin when enabled and no credentials were passed.
|
41
|
+
* fixed several bugs in the `sentry` adapter around breadcrumb handling.
|
42
|
+
* fixed `:native` resolver candidate calculation by putting absolute domain at the bottom of the list.
|
@@ -68,7 +68,7 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
|
|
68
68
|
|
69
69
|
@request.on(:response, &method(:finish))
|
70
70
|
|
71
|
-
verb = @request.verb
|
71
|
+
verb = @request.verb
|
72
72
|
uri = @request.uri
|
73
73
|
|
74
74
|
@span = build_span
|
@@ -158,9 +158,19 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
|
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
161
|
+
module RequestMethods
|
162
|
+
def __datadog_enable_trace!
|
163
|
+
return super if @__datadog_enable_trace
|
164
|
+
|
165
|
+
RequestTracer.new(self).call
|
166
|
+
@__datadog_enable_trace = true
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
161
170
|
module ConnectionMethods
|
162
171
|
def send(request)
|
163
|
-
|
172
|
+
request.__datadog_enable_trace!
|
173
|
+
|
164
174
|
super
|
165
175
|
end
|
166
176
|
end
|
@@ -43,8 +43,8 @@ module HTTPX::Plugins
|
|
43
43
|
|
44
44
|
request_info = extract_request_info(req)
|
45
45
|
|
46
|
-
data = if
|
47
|
-
{ error: res.message, **request_info }
|
46
|
+
data = if res.is_a?(HTTPX::ErrorResponse)
|
47
|
+
{ error: res.error.message, **request_info }
|
48
48
|
else
|
49
49
|
{ status: res.status, **request_info }
|
50
50
|
end
|
@@ -64,7 +64,7 @@ module HTTPX::Plugins
|
|
64
64
|
request_info = extract_request_info(req)
|
65
65
|
sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
|
66
66
|
if res.is_a?(HTTPX::ErrorResponse)
|
67
|
-
sentry_span.set_data(:error, res.message)
|
67
|
+
sentry_span.set_data(:error, res.error.message)
|
68
68
|
else
|
69
69
|
sentry_span.set_data(:status, res.status)
|
70
70
|
end
|
@@ -75,7 +75,7 @@ module HTTPX::Plugins
|
|
75
75
|
uri = req.uri
|
76
76
|
|
77
77
|
result = {
|
78
|
-
method: req.verb
|
78
|
+
method: req.verb,
|
79
79
|
}
|
80
80
|
|
81
81
|
if ::Sentry.configuration.send_default_pii
|
@@ -89,9 +89,19 @@ module HTTPX::Plugins
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
+
module RequestMethods
|
93
|
+
def __sentry_enable_trace!
|
94
|
+
return super if @__sentry_enable_trace
|
95
|
+
|
96
|
+
Tracer.call(self)
|
97
|
+
@__sentry_enable_trace = true
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
92
101
|
module ConnectionMethods
|
93
102
|
def send(request)
|
94
|
-
|
103
|
+
request.__sentry_enable_trace!
|
104
|
+
|
95
105
|
super
|
96
106
|
end
|
97
107
|
end
|
@@ -23,7 +23,7 @@ module WebMock
|
|
23
23
|
uri.path = uri.normalized_path.gsub("[^:]//", "/")
|
24
24
|
|
25
25
|
WebMock::RequestSignature.new(
|
26
|
-
request.verb,
|
26
|
+
request.verb.downcase.to_sym,
|
27
27
|
uri.to_s,
|
28
28
|
body: request.body.each.to_a.join,
|
29
29
|
headers: request.headers.to_h
|
@@ -122,7 +122,7 @@ module WebMock
|
|
122
122
|
|
123
123
|
class << self
|
124
124
|
def enable!
|
125
|
-
@original_session
|
125
|
+
@original_session ||= HTTPX::Session
|
126
126
|
|
127
127
|
webmock_session = HTTPX.plugin(Plugin)
|
128
128
|
|
data/lib/httpx/buffer.rb
CHANGED
data/lib/httpx/callbacks.rb
CHANGED
@@ -22,12 +22,12 @@ module HTTPX
|
|
22
22
|
callbacks(type).delete_if { |pr| :delete == pr.call(*args) } # rubocop:disable Style/YodaCondition
|
23
23
|
end
|
24
24
|
|
25
|
-
protected
|
26
|
-
|
27
25
|
def callbacks_for?(type)
|
28
|
-
@callbacks.key?(type) &&
|
26
|
+
@callbacks.key?(type) && @callbacks[type].any?
|
29
27
|
end
|
30
28
|
|
29
|
+
protected
|
30
|
+
|
31
31
|
def callbacks(type = nil)
|
32
32
|
return @callbacks unless type
|
33
33
|
|
data/lib/httpx/chainable.rb
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
module HTTPX
|
4
4
|
module Chainable
|
5
|
-
%
|
5
|
+
%w[head get post put delete trace options connect patch].each do |meth|
|
6
6
|
class_eval(<<-MOD, __FILE__, __LINE__ + 1)
|
7
|
-
def #{meth}(*uri, **options)
|
8
|
-
request(
|
9
|
-
end
|
7
|
+
def #{meth}(*uri, **options) # def get(*uri, **options)
|
8
|
+
request("#{meth.upcase}", uri, **options) # request("GET", uri, **options)
|
9
|
+
end # end
|
10
10
|
MOD
|
11
11
|
end
|
12
12
|
|
@@ -106,6 +106,7 @@ module HTTPX
|
|
106
106
|
|
107
107
|
def on_headers(h)
|
108
108
|
@request = @requests.first
|
109
|
+
|
109
110
|
return if @request.response
|
110
111
|
|
111
112
|
log(level: 2) { "headers received" }
|
@@ -312,7 +313,7 @@ module HTTPX
|
|
312
313
|
end
|
313
314
|
|
314
315
|
def join_headline(request)
|
315
|
-
"#{request.verb
|
316
|
+
"#{request.verb} #{request.path} HTTP/#{@version.join(".")}"
|
316
317
|
end
|
317
318
|
|
318
319
|
def join_headers(request)
|
@@ -367,5 +368,4 @@ module HTTPX
|
|
367
368
|
UPCASED[field] || field.split("-").map(&:capitalize).join("-")
|
368
369
|
end
|
369
370
|
end
|
370
|
-
Connection.register "http/1.1", Connection::HTTP1
|
371
371
|
end
|
@@ -208,7 +208,7 @@ module HTTPX
|
|
208
208
|
def set_protocol_headers(request)
|
209
209
|
{
|
210
210
|
":scheme" => request.scheme,
|
211
|
-
":method" => request.verb
|
211
|
+
":method" => request.verb,
|
212
212
|
":path" => request.path,
|
213
213
|
":authority" => request.authority,
|
214
214
|
}
|
@@ -317,7 +317,7 @@ module HTTPX
|
|
317
317
|
emit(:response, request, response)
|
318
318
|
else
|
319
319
|
response = request.response
|
320
|
-
if response && response.status == 421
|
320
|
+
if response && response.is_a?(Response) && response.status == 421
|
321
321
|
ex = MisdirectedRequestError.new(response)
|
322
322
|
ex.set_backtrace(caller)
|
323
323
|
emit(:error, request, ex)
|
@@ -412,5 +412,4 @@ module HTTPX
|
|
412
412
|
end
|
413
413
|
end
|
414
414
|
end
|
415
|
-
Connection.register "h2", Connection::HTTP2
|
416
415
|
end
|
data/lib/httpx/connection.rb
CHANGED
@@ -29,7 +29,6 @@ module HTTPX
|
|
29
29
|
#
|
30
30
|
class Connection
|
31
31
|
extend Forwardable
|
32
|
-
include Registry
|
33
32
|
include Loggable
|
34
33
|
include Callbacks
|
35
34
|
|
@@ -39,8 +38,6 @@ module HTTPX
|
|
39
38
|
require "httpx/connection/http2"
|
40
39
|
require "httpx/connection/http1"
|
41
40
|
|
42
|
-
BUFFER_SIZE = 1 << 14
|
43
|
-
|
44
41
|
def_delegator :@io, :closed?
|
45
42
|
|
46
43
|
def_delegator :@write_buffer, :empty?
|
@@ -57,15 +54,15 @@ module HTTPX
|
|
57
54
|
@origin = Utils.to_uri(uri.origin)
|
58
55
|
@options = Options.new(options)
|
59
56
|
@window_size = @options.window_size
|
60
|
-
@read_buffer = Buffer.new(
|
61
|
-
@write_buffer = Buffer.new(
|
57
|
+
@read_buffer = Buffer.new(@options.buffer_size)
|
58
|
+
@write_buffer = Buffer.new(@options.buffer_size)
|
62
59
|
@pending = []
|
63
60
|
on(:error, &method(:on_error))
|
64
61
|
if @options.io
|
65
62
|
# if there's an already open IO, get its
|
66
63
|
# peer address, and force-initiate the parser
|
67
64
|
transition(:already_open)
|
68
|
-
@io =
|
65
|
+
@io = build_socket
|
69
66
|
parser
|
70
67
|
else
|
71
68
|
transition(:idle)
|
@@ -84,7 +81,7 @@ module HTTPX
|
|
84
81
|
if @io
|
85
82
|
@io.add_addresses(addrs)
|
86
83
|
else
|
87
|
-
@io =
|
84
|
+
@io = build_socket(addrs)
|
88
85
|
end
|
89
86
|
end
|
90
87
|
|
@@ -104,7 +101,7 @@ module HTTPX
|
|
104
101
|
# was the result of coalescing. To prevent blind trust in the case where the
|
105
102
|
# origin came from an ORIGIN frame, we're going to verify the hostname with the
|
106
103
|
# SSL certificate
|
107
|
-
(@origins.size == 1 || @origin == uri.origin || (@io && @io.verify_hostname(uri.host)))
|
104
|
+
(@origins.size == 1 || @origin == uri.origin || (@io.is_a?(SSL) && @io.verify_hostname(uri.host)))
|
108
105
|
) && @options == options
|
109
106
|
) || (match_altsvcs?(uri) && match_altsvc_options?(uri, options))
|
110
107
|
end
|
@@ -118,7 +115,7 @@ module HTTPX
|
|
118
115
|
|
119
116
|
(
|
120
117
|
(open? && @origin == connection.origin) ||
|
121
|
-
!(@io.addresses & connection.addresses).empty?
|
118
|
+
!(@io.addresses & (connection.addresses || [])).empty?
|
122
119
|
) && @options == connection.options
|
123
120
|
end
|
124
121
|
|
@@ -453,7 +450,7 @@ module HTTPX
|
|
453
450
|
end
|
454
451
|
|
455
452
|
def build_parser(protocol = @io.protocol)
|
456
|
-
parser =
|
453
|
+
parser = self.class.parser_type(protocol).new(@write_buffer, @options)
|
457
454
|
set_parser_callbacks(parser)
|
458
455
|
parser
|
459
456
|
end
|
@@ -538,12 +535,13 @@ module HTTPX
|
|
538
535
|
# connect errors, exit gracefully
|
539
536
|
error = ConnectionError.new(e.message)
|
540
537
|
error.set_backtrace(e.backtrace)
|
541
|
-
connecting? &&
|
538
|
+
connecting? && callbacks_for?(:connect_error) ? emit(:connect_error, error) : handle_error(error)
|
542
539
|
@state = :closed
|
543
540
|
emit(:close)
|
544
541
|
rescue TLSError => e
|
545
542
|
# connect errors, exit gracefully
|
546
543
|
handle_error(e)
|
544
|
+
connecting? && callbacks_for?(:connect_error) ? emit(:connect_error, e) : handle_error(e)
|
547
545
|
@state = :closed
|
548
546
|
emit(:close)
|
549
547
|
end
|
@@ -595,6 +593,17 @@ module HTTPX
|
|
595
593
|
remove_instance_variable(:@timeout) if defined?(@timeout)
|
596
594
|
end
|
597
595
|
|
596
|
+
def build_socket(addrs = nil)
|
597
|
+
transport_type = case @type
|
598
|
+
when "tcp" then TCP
|
599
|
+
when "ssl" then SSL
|
600
|
+
when "unix" then UNIX
|
601
|
+
else
|
602
|
+
raise Error, "unsupported transport (#{@type})"
|
603
|
+
end
|
604
|
+
transport_type.new(@origin, addrs, @options)
|
605
|
+
end
|
606
|
+
|
598
607
|
def on_error(error)
|
599
608
|
if error.instance_of?(TimeoutError)
|
600
609
|
|
@@ -663,5 +672,16 @@ module HTTPX
|
|
663
672
|
error = error_type.new(request, request.response, read_timeout)
|
664
673
|
on_error(error)
|
665
674
|
end
|
675
|
+
|
676
|
+
class << self
|
677
|
+
def parser_type(protocol)
|
678
|
+
case protocol
|
679
|
+
when "h2" then HTTP2
|
680
|
+
when "http/1.1" then HTTP1
|
681
|
+
else
|
682
|
+
raise Error, "unsupported protocol (##{protocol})"
|
683
|
+
end
|
684
|
+
end
|
685
|
+
end
|
666
686
|
end
|
667
687
|
end
|
data/lib/httpx/io/udp.rb
CHANGED
data/lib/httpx/io/unix.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "forwardable"
|
4
|
-
|
5
3
|
module HTTPX
|
6
4
|
class UNIX < TCP
|
7
|
-
extend Forwardable
|
8
|
-
|
9
5
|
using URIExtensions
|
10
6
|
|
11
7
|
attr_reader :path
|
@@ -13,7 +9,7 @@ module HTTPX
|
|
13
9
|
alias_method :host, :path
|
14
10
|
|
15
11
|
def initialize(origin, addresses, options)
|
16
|
-
@addresses =
|
12
|
+
@addresses = []
|
17
13
|
@hostname = origin.host
|
18
14
|
@state = :idle
|
19
15
|
@options = Options.new(options)
|
data/lib/httpx/io.rb
CHANGED
@@ -5,13 +5,3 @@ require "httpx/io/udp"
|
|
5
5
|
require "httpx/io/tcp"
|
6
6
|
require "httpx/io/unix"
|
7
7
|
require "httpx/io/ssl"
|
8
|
-
|
9
|
-
module HTTPX
|
10
|
-
module IO
|
11
|
-
extend Registry
|
12
|
-
register "udp", UDP
|
13
|
-
register "unix", HTTPX::UNIX
|
14
|
-
register "tcp", TCP
|
15
|
-
register "ssl", SSL
|
16
|
-
end
|
17
|
-
end
|
data/lib/httpx/options.rb
CHANGED
@@ -4,6 +4,7 @@ require "socket"
|
|
4
4
|
|
5
5
|
module HTTPX
|
6
6
|
class Options
|
7
|
+
BUFFER_SIZE = 1 << 14
|
7
8
|
WINDOW_SIZE = 1 << 14 # 16K
|
8
9
|
MAX_BODY_THRESHOLD_SIZE = (1 << 10) * 112 # 112K
|
9
10
|
CONNECT_TIMEOUT = 60
|
@@ -41,6 +42,7 @@ module HTTPX
|
|
41
42
|
},
|
42
43
|
:headers => {},
|
43
44
|
:window_size => WINDOW_SIZE,
|
45
|
+
:buffer_size => BUFFER_SIZE,
|
44
46
|
:body_threshold_size => MAX_BODY_THRESHOLD_SIZE,
|
45
47
|
:request_class => Class.new(Request),
|
46
48
|
:response_class => Class.new(Response),
|
@@ -178,7 +180,19 @@ module HTTPX
|
|
178
180
|
end
|
179
181
|
|
180
182
|
def option_window_size(value)
|
181
|
-
Integer(value)
|
183
|
+
value = Integer(value)
|
184
|
+
|
185
|
+
raise TypeError, ":window_size must be positive" unless value.positive?
|
186
|
+
|
187
|
+
value
|
188
|
+
end
|
189
|
+
|
190
|
+
def option_buffer_size(value)
|
191
|
+
value = Integer(value)
|
192
|
+
|
193
|
+
raise TypeError, ":buffer_size must be positive" unless value.positive?
|
194
|
+
|
195
|
+
value
|
182
196
|
end
|
183
197
|
|
184
198
|
def option_body_threshold_size(value)
|
@@ -187,7 +201,7 @@ module HTTPX
|
|
187
201
|
|
188
202
|
def option_transport(value)
|
189
203
|
transport = value.to_s
|
190
|
-
raise TypeError, "
|
204
|
+
raise TypeError, "#{transport} is an unsupported transport type" unless %w[unix].include?(transport)
|
191
205
|
|
192
206
|
transport
|
193
207
|
end
|
@@ -5,13 +5,13 @@ module HTTPX
|
|
5
5
|
module Compression
|
6
6
|
module Brotli
|
7
7
|
class << self
|
8
|
-
def load_dependencies(
|
8
|
+
def load_dependencies(klass)
|
9
9
|
require "brotli"
|
10
|
+
klass.plugin(:compression)
|
10
11
|
end
|
11
12
|
|
12
|
-
def
|
13
|
-
|
14
|
-
klass.default_options.encodings.register "br", self
|
13
|
+
def extra_options(options)
|
14
|
+
options.merge(encodings: options.encodings.merge("br" => self))
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -4,14 +4,19 @@ module HTTPX
|
|
4
4
|
module Plugins
|
5
5
|
module Compression
|
6
6
|
module Deflate
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
class << self
|
8
|
+
def load_dependencies(_klass)
|
9
|
+
require "stringio"
|
10
|
+
require "zlib"
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
def configure(klass)
|
14
|
+
klass.plugin(:"compression/gzip")
|
15
|
+
end
|
16
|
+
|
17
|
+
def extra_options(options)
|
18
|
+
options.merge(encodings: options.encodings.merge("deflate" => self))
|
19
|
+
end
|
15
20
|
end
|
16
21
|
|
17
22
|
module Deflater
|
@@ -6,12 +6,14 @@ module HTTPX
|
|
6
6
|
module Plugins
|
7
7
|
module Compression
|
8
8
|
module GZIP
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
class << self
|
10
|
+
def load_dependencies(*)
|
11
|
+
require "zlib"
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
def extra_options(options)
|
15
|
+
options.merge(encodings: options.encodings.merge("gzip" => self))
|
16
|
+
end
|
15
17
|
end
|
16
18
|
|
17
19
|
class Deflater
|
@@ -20,10 +20,7 @@ module HTTPX
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def extra_options(options)
|
23
|
-
encodings
|
24
|
-
extend Registry
|
25
|
-
end
|
26
|
-
options.merge(encodings: encodings)
|
23
|
+
options.merge(encodings: {})
|
27
24
|
end
|
28
25
|
end
|
29
26
|
|
@@ -36,7 +33,7 @@ module HTTPX
|
|
36
33
|
end
|
37
34
|
|
38
35
|
def option_encodings(value)
|
39
|
-
raise TypeError, ":encodings must be
|
36
|
+
raise TypeError, ":encodings must be an Hash" unless value.is_a?(Hash)
|
40
37
|
|
41
38
|
value
|
42
39
|
end
|
@@ -49,7 +46,7 @@ module HTTPX
|
|
49
46
|
if @headers.key?("range")
|
50
47
|
@headers.delete("accept-encoding")
|
51
48
|
else
|
52
|
-
@headers["accept-encoding"] ||= @options.encodings.
|
49
|
+
@headers["accept-encoding"] ||= @options.encodings.keys
|
53
50
|
end
|
54
51
|
end
|
55
52
|
end
|
@@ -65,7 +62,9 @@ module HTTPX
|
|
65
62
|
@headers.get("content-encoding").each do |encoding|
|
66
63
|
next if encoding == "identity"
|
67
64
|
|
68
|
-
|
65
|
+
next unless options.encodings.key?(encoding)
|
66
|
+
|
67
|
+
@body = Encoder.new(@body, options.encodings[encoding].deflater)
|
69
68
|
end
|
70
69
|
@headers["content-length"] = @body.bytesize unless unbounded_body?
|
71
70
|
end
|
@@ -95,7 +94,9 @@ module HTTPX
|
|
95
94
|
@_inflaters = @headers.get("content-encoding").filter_map do |encoding|
|
96
95
|
next if encoding == "identity"
|
97
96
|
|
98
|
-
|
97
|
+
next unless @options.encodings.key?(encoding)
|
98
|
+
|
99
|
+
inflater = @options.encodings[encoding].inflater(compressed_length)
|
99
100
|
# do not uncompress if there is no decoder available. In fact, we can't reliably
|
100
101
|
# continue decompressing beyond that, so ignore.
|
101
102
|
break unless inflater
|
@@ -47,7 +47,9 @@ module HTTPX
|
|
47
47
|
data = message.byteslice(5..size + 5 - 1)
|
48
48
|
if compressed == 1
|
49
49
|
encodings.reverse_each do |algo|
|
50
|
-
|
50
|
+
next unless encoders.key?(algo)
|
51
|
+
|
52
|
+
inflater = encoders[algo].inflater(size)
|
51
53
|
data = inflater.inflate(data)
|
52
54
|
size = data.bytesize
|
53
55
|
end
|