httpx 0.22.4 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|