httpx 1.2.6 → 1.4.4
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/README.md +1 -2
- data/doc/release_notes/1_3_0.md +18 -0
- data/doc/release_notes/1_3_1.md +17 -0
- data/doc/release_notes/1_3_2.md +6 -0
- data/doc/release_notes/1_3_3.md +5 -0
- data/doc/release_notes/1_3_4.md +6 -0
- data/doc/release_notes/1_4_0.md +43 -0
- data/doc/release_notes/1_4_1.md +19 -0
- data/doc/release_notes/1_4_2.md +20 -0
- data/doc/release_notes/1_4_3.md +11 -0
- data/doc/release_notes/1_4_4.md +14 -0
- data/lib/httpx/adapters/datadog.rb +56 -80
- data/lib/httpx/adapters/faraday.rb +5 -2
- data/lib/httpx/adapters/webmock.rb +24 -8
- data/lib/httpx/callbacks.rb +2 -7
- data/lib/httpx/chainable.rb +3 -1
- data/lib/httpx/connection/http1.rb +11 -7
- data/lib/httpx/connection/http2.rb +57 -34
- data/lib/httpx/connection.rb +270 -71
- data/lib/httpx/errors.rb +15 -4
- data/lib/httpx/io/ssl.rb +6 -3
- data/lib/httpx/io/tcp.rb +1 -1
- data/lib/httpx/io/unix.rb +1 -1
- data/lib/httpx/loggable.rb +17 -10
- data/lib/httpx/options.rb +30 -23
- data/lib/httpx/plugins/aws_sdk_authentication.rb +3 -0
- data/lib/httpx/plugins/aws_sigv4.rb +36 -17
- data/lib/httpx/plugins/callbacks.rb +13 -2
- data/lib/httpx/plugins/circuit_breaker.rb +11 -5
- data/lib/httpx/plugins/content_digest.rb +202 -0
- data/lib/httpx/plugins/cookies.rb +9 -6
- data/lib/httpx/plugins/digest_auth.rb +3 -0
- data/lib/httpx/plugins/expect.rb +10 -4
- data/lib/httpx/plugins/follow_redirects.rb +68 -33
- data/lib/httpx/plugins/grpc/grpc_encoding.rb +2 -0
- data/lib/httpx/plugins/grpc.rb +2 -2
- data/lib/httpx/plugins/h2c.rb +23 -20
- data/lib/httpx/plugins/internal_telemetry.rb +48 -1
- data/lib/httpx/plugins/oauth.rb +1 -1
- data/lib/httpx/plugins/persistent.rb +16 -0
- data/lib/httpx/plugins/proxy/http.rb +19 -16
- data/lib/httpx/plugins/proxy/socks4.rb +1 -1
- data/lib/httpx/plugins/proxy/socks5.rb +1 -1
- data/lib/httpx/plugins/proxy.rb +96 -85
- data/lib/httpx/plugins/retries.rb +28 -10
- data/lib/httpx/plugins/ssrf_filter.rb +4 -1
- data/lib/httpx/plugins/stream.rb +42 -18
- data/lib/httpx/plugins/upgrade.rb +5 -10
- data/lib/httpx/plugins/webdav.rb +6 -0
- data/lib/httpx/plugins/xml.rb +76 -0
- data/lib/httpx/pool.rb +73 -244
- data/lib/httpx/request/body.rb +50 -55
- data/lib/httpx/request.rb +77 -14
- data/lib/httpx/resolver/https.rb +17 -20
- data/lib/httpx/resolver/multi.rb +34 -16
- data/lib/httpx/resolver/native.rb +140 -61
- data/lib/httpx/resolver/resolver.rb +64 -19
- data/lib/httpx/resolver/system.rb +32 -16
- data/lib/httpx/resolver.rb +21 -14
- data/lib/httpx/response/body.rb +12 -1
- data/lib/httpx/response.rb +16 -9
- data/lib/httpx/selector.rb +170 -91
- data/lib/httpx/session.rb +282 -139
- data/lib/httpx/timers.rb +17 -2
- data/lib/httpx/transcoder/body.rb +15 -29
- data/lib/httpx/transcoder/form.rb +2 -0
- data/lib/httpx/transcoder/gzip.rb +0 -3
- data/lib/httpx/transcoder/json.rb +16 -2
- data/lib/httpx/transcoder/multipart/encoder.rb +11 -2
- data/lib/httpx/transcoder/multipart/part.rb +1 -1
- data/lib/httpx/transcoder/utils/deflater.rb +7 -4
- data/lib/httpx/transcoder.rb +0 -1
- data/lib/httpx/version.rb +1 -1
- data/lib/httpx.rb +20 -21
- data/sig/callbacks.rbs +2 -3
- data/sig/chainable.rbs +6 -2
- data/sig/connection/http1.rbs +2 -2
- data/sig/connection/http2.rbs +22 -18
- data/sig/connection.rbs +40 -9
- data/sig/errors.rbs +9 -3
- data/sig/httpx.rbs +3 -3
- data/sig/io/tcp.rbs +1 -1
- data/sig/io/unix.rbs +1 -1
- data/sig/loggable.rbs +4 -2
- data/sig/options.rbs +8 -13
- data/sig/plugins/aws_sigv4.rbs +8 -2
- data/sig/plugins/content_digest.rbs +51 -0
- data/sig/plugins/cookies/cookie.rbs +9 -0
- data/sig/plugins/follow_redirects.rbs +1 -1
- data/sig/plugins/grpc/call.rbs +4 -0
- data/sig/plugins/persistent.rbs +4 -1
- data/sig/plugins/proxy/http.rbs +3 -0
- data/sig/plugins/proxy/socks5.rbs +11 -3
- data/sig/plugins/proxy.rbs +18 -9
- data/sig/plugins/push_promise.rbs +6 -3
- data/sig/plugins/rate_limiter.rbs +2 -0
- data/sig/plugins/retries.rbs +1 -1
- data/sig/plugins/ssrf_filter.rbs +26 -0
- data/sig/plugins/stream.rbs +3 -0
- data/sig/plugins/webdav.rbs +23 -0
- data/sig/plugins/xml.rbs +37 -0
- data/sig/pool.rbs +27 -33
- data/sig/request/body.rbs +4 -10
- data/sig/request.rbs +14 -1
- data/sig/resolver/multi.rbs +26 -1
- data/sig/resolver/native.rbs +6 -3
- data/sig/resolver/resolver.rbs +22 -3
- data/sig/resolver.rbs +5 -1
- data/sig/response/body.rbs +2 -2
- data/sig/response/buffer.rbs +2 -2
- data/sig/response.rbs +9 -4
- data/sig/selector.rbs +31 -4
- data/sig/session.rbs +54 -20
- data/sig/timers.rbs +15 -4
- data/sig/transcoder/body.rbs +2 -4
- data/sig/transcoder/chunker.rbs +1 -1
- data/sig/transcoder/deflate.rbs +1 -0
- data/sig/transcoder/form.rbs +8 -0
- data/sig/transcoder/gzip.rbs +4 -1
- data/sig/transcoder/json.rbs +1 -1
- data/sig/transcoder/multipart.rbs +6 -4
- data/sig/transcoder/utils/body_reader.rbs +3 -3
- data/sig/transcoder/utils/deflater.rbs +2 -3
- metadata +32 -14
- data/lib/httpx/session2.rb +0 -23
- data/lib/httpx/transcoder/utils/inflater.rb +0 -19
- data/lib/httpx/transcoder/xml.rb +0 -52
- data/sig/transcoder/utils/inflater.rbs +0 -12
- data/sig/transcoder/xml.rbs +0 -22
@@ -4,12 +4,17 @@ module HTTPX
|
|
4
4
|
InsecureRedirectError = Class.new(Error)
|
5
5
|
module Plugins
|
6
6
|
#
|
7
|
-
# This plugin adds support for following redirect (status 30X) responses.
|
7
|
+
# This plugin adds support for automatically following redirect (status 30X) responses.
|
8
8
|
#
|
9
|
-
# It has
|
10
|
-
# will return the last redirect response. It will **not** raise an exception.
|
9
|
+
# It has a default upper bound of followed redirects (see *MAX_REDIRECTS* and the *max_redirects* option),
|
10
|
+
# after which it will return the last redirect response. It will **not** raise an exception.
|
11
11
|
#
|
12
|
-
# It
|
12
|
+
# It doesn't follow insecure redirects (https -> http) by default (see *follow_insecure_redirects*).
|
13
|
+
#
|
14
|
+
# It doesn't propagate authorization related headers to requests redirecting to different origins
|
15
|
+
# (see *allow_auth_to_other_origins*) to override.
|
16
|
+
#
|
17
|
+
# It allows customization of when to redirect via the *redirect_on* callback option).
|
13
18
|
#
|
14
19
|
# https://gitlab.com/os85/httpx/wikis/Follow-Redirects
|
15
20
|
#
|
@@ -20,6 +25,14 @@ module HTTPX
|
|
20
25
|
|
21
26
|
using URIExtensions
|
22
27
|
|
28
|
+
# adds support for the following options:
|
29
|
+
#
|
30
|
+
# :max_redirects :: max number of times a request will be redirected (defaults to <tt>3</tt>).
|
31
|
+
# :follow_insecure_redirects :: whether redirects to an "http://" URI, when coming from an "https//", are allowed
|
32
|
+
# (defaults to <tt>false</tt>).
|
33
|
+
# :allow_auth_to_other_origins :: whether auth-related headers, such as "Authorization", are propagated on redirection
|
34
|
+
# (defaults to <tt>false</tt>).
|
35
|
+
# :redirect_on :: optional callback which receives the redirect location and can halt the redirect chain if it returns <tt>false</tt>.
|
23
36
|
module OptionsMethods
|
24
37
|
def option_max_redirects(value)
|
25
38
|
num = Integer(value)
|
@@ -44,15 +57,16 @@ module HTTPX
|
|
44
57
|
end
|
45
58
|
|
46
59
|
module InstanceMethods
|
60
|
+
# returns a session with the *max_redirects* option set to +n+
|
47
61
|
def max_redirects(n)
|
48
62
|
with(max_redirects: n.to_i)
|
49
63
|
end
|
50
64
|
|
51
65
|
private
|
52
66
|
|
53
|
-
def fetch_response(request,
|
67
|
+
def fetch_response(request, selector, options)
|
54
68
|
redirect_request = request.redirect_request
|
55
|
-
response = super(redirect_request,
|
69
|
+
response = super(redirect_request, selector, options)
|
56
70
|
return unless response
|
57
71
|
|
58
72
|
max_redirects = redirect_request.max_redirects
|
@@ -71,40 +85,40 @@ module HTTPX
|
|
71
85
|
# build redirect request
|
72
86
|
request_body = redirect_request.body
|
73
87
|
redirect_method = "GET"
|
88
|
+
redirect_params = {}
|
74
89
|
|
75
90
|
if response.status == 305 && options.respond_to?(:proxy)
|
76
91
|
request_body.rewind
|
77
92
|
# The requested resource MUST be accessed through the proxy given by
|
78
93
|
# the Location field. The Location field gives the URI of the proxy.
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
94
|
+
redirect_options = options.merge(headers: redirect_request.headers,
|
95
|
+
proxy: { uri: redirect_uri },
|
96
|
+
max_redirects: max_redirects - 1)
|
97
|
+
|
98
|
+
redirect_params[:body] = request_body
|
83
99
|
redirect_uri = redirect_request.uri
|
84
|
-
options =
|
100
|
+
options = redirect_options
|
85
101
|
else
|
86
102
|
redirect_headers = redirect_request_headers(redirect_request.uri, redirect_uri, request.headers, options)
|
87
|
-
|
88
|
-
|
103
|
+
redirect_opts = Hash[options]
|
104
|
+
redirect_params[:max_redirects] = max_redirects - 1
|
89
105
|
|
90
106
|
unless request_body.empty?
|
91
107
|
if response.status == 307
|
92
108
|
# The method and the body of the original request are reused to perform the redirected request.
|
93
109
|
redirect_method = redirect_request.verb
|
94
110
|
request_body.rewind
|
95
|
-
|
111
|
+
redirect_params[:body] = request_body
|
96
112
|
else
|
97
113
|
# redirects are **ALWAYS** GET, so remove body-related headers
|
98
114
|
REQUEST_BODY_HEADERS.each do |h|
|
99
115
|
redirect_headers.delete(h)
|
100
116
|
end
|
101
|
-
|
117
|
+
redirect_params[:body] = nil
|
102
118
|
end
|
103
119
|
end
|
104
120
|
|
105
|
-
|
106
|
-
|
107
|
-
retry_options = options.class.new(retry_opts)
|
121
|
+
options = options.class.new(redirect_opts.merge(headers: redirect_headers.to_h))
|
108
122
|
end
|
109
123
|
|
110
124
|
redirect_uri = Utils.to_uri(redirect_uri)
|
@@ -114,34 +128,42 @@ module HTTPX
|
|
114
128
|
redirect_uri.scheme == "http"
|
115
129
|
error = InsecureRedirectError.new(redirect_uri.to_s)
|
116
130
|
error.set_backtrace(caller)
|
117
|
-
return ErrorResponse.new(request, error
|
131
|
+
return ErrorResponse.new(request, error)
|
118
132
|
end
|
119
133
|
|
120
|
-
retry_request = build_request(redirect_method, redirect_uri,
|
134
|
+
retry_request = build_request(redirect_method, redirect_uri, redirect_params, options)
|
121
135
|
|
122
136
|
request.redirect_request = retry_request
|
123
137
|
|
124
|
-
|
138
|
+
redirect_after = response.headers["retry-after"]
|
125
139
|
|
126
|
-
if
|
140
|
+
if redirect_after
|
127
141
|
# Servers send the "Retry-After" header field to indicate how long the
|
128
142
|
# user agent ought to wait before making a follow-up request.
|
129
143
|
# When sent with any 3xx (Redirection) response, Retry-After indicates
|
130
144
|
# the minimum time that the user agent is asked to wait before issuing
|
131
145
|
# the redirected request.
|
132
146
|
#
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
147
|
+
redirect_after = Utils.parse_retry_after(redirect_after)
|
148
|
+
|
149
|
+
retry_start = Utils.now
|
150
|
+
log { "redirecting after #{redirect_after} secs..." }
|
151
|
+
selector.after(redirect_after) do
|
152
|
+
if request.response
|
153
|
+
# request has terminated abruptly meanwhile
|
154
|
+
retry_request.emit(:response, request.response)
|
155
|
+
else
|
156
|
+
log { "redirecting (elapsed time: #{Utils.elapsed_time(retry_start)})!!" }
|
157
|
+
send_request(retry_request, selector, options)
|
158
|
+
end
|
138
159
|
end
|
139
160
|
else
|
140
|
-
send_request(retry_request,
|
161
|
+
send_request(retry_request, selector, options)
|
141
162
|
end
|
142
163
|
nil
|
143
164
|
end
|
144
165
|
|
166
|
+
# :nodoc:
|
145
167
|
def redirect_request_headers(original_uri, redirect_uri, headers, options)
|
146
168
|
headers = headers.dup
|
147
169
|
|
@@ -149,14 +171,14 @@ module HTTPX
|
|
149
171
|
|
150
172
|
return headers unless headers.key?("authorization")
|
151
173
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
end
|
174
|
+
return headers if original_uri.origin == redirect_uri.origin
|
175
|
+
|
176
|
+
headers.delete("authorization")
|
156
177
|
|
157
178
|
headers
|
158
179
|
end
|
159
180
|
|
181
|
+
# :nodoc:
|
160
182
|
def __get_location_from_response(response)
|
161
183
|
# @type var location_uri: http_uri
|
162
184
|
location_uri = URI(response.headers["location"])
|
@@ -166,12 +188,15 @@ module HTTPX
|
|
166
188
|
end
|
167
189
|
|
168
190
|
module RequestMethods
|
191
|
+
# returns the top-most original HTTPX::Request from the redirect chain
|
169
192
|
attr_accessor :root_request
|
170
193
|
|
194
|
+
# returns the follow-up redirect request, or itself
|
171
195
|
def redirect_request
|
172
196
|
@redirect_request || self
|
173
197
|
end
|
174
198
|
|
199
|
+
# sets the follow-up redirect request
|
175
200
|
def redirect_request=(req)
|
176
201
|
@redirect_request = req
|
177
202
|
req.root_request = @root_request || self
|
@@ -179,7 +204,7 @@ module HTTPX
|
|
179
204
|
end
|
180
205
|
|
181
206
|
def response
|
182
|
-
return super unless @redirect_request
|
207
|
+
return super unless @redirect_request && @response.nil?
|
183
208
|
|
184
209
|
@redirect_request.response
|
185
210
|
end
|
@@ -188,6 +213,16 @@ module HTTPX
|
|
188
213
|
@options.max_redirects || MAX_REDIRECTS
|
189
214
|
end
|
190
215
|
end
|
216
|
+
|
217
|
+
module ConnectionMethods
|
218
|
+
private
|
219
|
+
|
220
|
+
def set_request_request_timeout(request)
|
221
|
+
return unless request.root_request.nil?
|
222
|
+
|
223
|
+
super
|
224
|
+
end
|
225
|
+
end
|
191
226
|
end
|
192
227
|
register_plugin :follow_redirects, FollowRedirects
|
193
228
|
end
|
data/lib/httpx/plugins/grpc.rb
CHANGED
@@ -110,10 +110,10 @@ module HTTPX
|
|
110
110
|
end
|
111
111
|
|
112
112
|
module RequestBodyMethods
|
113
|
-
def initialize(
|
113
|
+
def initialize(*, **)
|
114
114
|
super
|
115
115
|
|
116
|
-
if (compression = headers["grpc-encoding"])
|
116
|
+
if (compression = @headers["grpc-encoding"])
|
117
117
|
deflater_body = self.class.initialize_deflater_body(@body, compression)
|
118
118
|
@body = Transcoder::GRPCEncoding.encode(deflater_body || @body, compressed: !deflater_body.nil?)
|
119
119
|
else
|
data/lib/httpx/plugins/h2c.rb
CHANGED
@@ -25,26 +25,6 @@ module HTTPX
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
module InstanceMethods
|
29
|
-
def send_requests(*requests)
|
30
|
-
upgrade_request, *remainder = requests
|
31
|
-
|
32
|
-
return super unless VALID_H2C_VERBS.include?(upgrade_request.verb) && upgrade_request.scheme == "http"
|
33
|
-
|
34
|
-
connection = pool.find_connection(upgrade_request.uri, upgrade_request.options)
|
35
|
-
|
36
|
-
return super if connection && connection.upgrade_protocol == "h2c"
|
37
|
-
|
38
|
-
# build upgrade request
|
39
|
-
upgrade_request.headers.add("connection", "upgrade")
|
40
|
-
upgrade_request.headers.add("connection", "http2-settings")
|
41
|
-
upgrade_request.headers["upgrade"] = "h2c"
|
42
|
-
upgrade_request.headers["http2-settings"] = HTTP2Next::Client.settings_header(upgrade_request.options.http2_settings)
|
43
|
-
|
44
|
-
super(upgrade_request, *remainder)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
28
|
class H2CParser < Connection::HTTP2
|
49
29
|
def upgrade(request, response)
|
50
30
|
# skip checks, it is assumed that this is the first
|
@@ -65,6 +45,29 @@ module HTTPX
|
|
65
45
|
module ConnectionMethods
|
66
46
|
using URIExtensions
|
67
47
|
|
48
|
+
def initialize(*)
|
49
|
+
super
|
50
|
+
@h2c_handshake = false
|
51
|
+
end
|
52
|
+
|
53
|
+
def send(request)
|
54
|
+
return super if @h2c_handshake
|
55
|
+
|
56
|
+
return super unless VALID_H2C_VERBS.include?(request.verb) && request.scheme == "http"
|
57
|
+
|
58
|
+
return super if @upgrade_protocol == "h2c"
|
59
|
+
|
60
|
+
@h2c_handshake = true
|
61
|
+
|
62
|
+
# build upgrade request
|
63
|
+
request.headers.add("connection", "upgrade")
|
64
|
+
request.headers.add("connection", "http2-settings")
|
65
|
+
request.headers["upgrade"] = "h2c"
|
66
|
+
request.headers["http2-settings"] = ::HTTP2::Client.settings_header(request.options.http2_settings)
|
67
|
+
|
68
|
+
super
|
69
|
+
end
|
70
|
+
|
68
71
|
def upgrade_to_h2c(request, response)
|
69
72
|
prev_parser = @parser
|
70
73
|
|
@@ -13,6 +13,12 @@ module HTTPX
|
|
13
13
|
# by the end user in $http_init_time, different diff metrics can be shown. The "point of time" is calculated
|
14
14
|
# using the monotonic clock.
|
15
15
|
module InternalTelemetry
|
16
|
+
DEBUG_LEVEL = 3
|
17
|
+
|
18
|
+
def self.extra_options(options)
|
19
|
+
options.merge(debug_level: 3)
|
20
|
+
end
|
21
|
+
|
16
22
|
module TrackTimeMethods
|
17
23
|
private
|
18
24
|
|
@@ -28,7 +34,19 @@ module HTTPX
|
|
28
34
|
after_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
29
35
|
# $http_init_time = after_time
|
30
36
|
elapsed = after_time - prev_time
|
31
|
-
|
37
|
+
# klass = self.class
|
38
|
+
|
39
|
+
# until (class_name = klass.name)
|
40
|
+
# klass = klass.superclass
|
41
|
+
# end
|
42
|
+
log(
|
43
|
+
level: DEBUG_LEVEL,
|
44
|
+
color: :red,
|
45
|
+
debug_level: @options ? @options.debug_level : DEBUG_LEVEL,
|
46
|
+
debug: nil
|
47
|
+
) do
|
48
|
+
"[ELAPSED TIME]: #{label}: #{elapsed} (ms)" << "\e[0m"
|
49
|
+
end
|
32
50
|
end
|
33
51
|
end
|
34
52
|
|
@@ -76,10 +94,19 @@ module HTTPX
|
|
76
94
|
meter_elapsed_time("Session -> response") if response
|
77
95
|
response
|
78
96
|
end
|
97
|
+
|
98
|
+
def coalesce_connections(conn1, conn2, selector, *)
|
99
|
+
result = super
|
100
|
+
|
101
|
+
meter_elapsed_time("Connection##{conn2.object_id} coalescing to Connection##{conn1.object_id}") if result
|
102
|
+
|
103
|
+
result
|
104
|
+
end
|
79
105
|
end
|
80
106
|
|
81
107
|
module RequestMethods
|
82
108
|
def self.included(klass)
|
109
|
+
klass.prepend Loggable
|
83
110
|
klass.prepend TrackTimeMethods
|
84
111
|
super
|
85
112
|
end
|
@@ -103,6 +130,26 @@ module HTTPX
|
|
103
130
|
meter_elapsed_time("Connection##{object_id}[#{@origin}]: #{state} -> #{nextstate}") if nextstate == @state
|
104
131
|
end
|
105
132
|
end
|
133
|
+
|
134
|
+
module PoolMethods
|
135
|
+
def self.included(klass)
|
136
|
+
klass.prepend Loggable
|
137
|
+
klass.prepend TrackTimeMethods
|
138
|
+
super
|
139
|
+
end
|
140
|
+
|
141
|
+
def checkout_connection(request_uri, options)
|
142
|
+
super.tap do |connection|
|
143
|
+
meter_elapsed_time("Pool##{object_id}: checked out connection for Connection##{connection.object_id}[#{connection.origin}]}")
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def checkin_connection(connection)
|
148
|
+
super.tap do
|
149
|
+
meter_elapsed_time("Pool##{object_id}: checked in connection for Connection##{connection.object_id}[#{connection.origin}]}")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
106
153
|
end
|
107
154
|
register_plugin :internal_telemetry, InternalTelemetry
|
108
155
|
end
|
data/lib/httpx/plugins/oauth.rb
CHANGED
@@ -155,7 +155,7 @@ module HTTPX
|
|
155
155
|
with(oauth_session: oauth_session.merge(access_token: access_token, refresh_token: refresh_token))
|
156
156
|
end
|
157
157
|
|
158
|
-
def build_request(
|
158
|
+
def build_request(*)
|
159
159
|
request = super
|
160
160
|
|
161
161
|
return request if request.headers.key?("authorization")
|
@@ -30,6 +30,22 @@ module HTTPX
|
|
30
30
|
def self.extra_options(options)
|
31
31
|
options.merge(persistent: true)
|
32
32
|
end
|
33
|
+
|
34
|
+
module InstanceMethods
|
35
|
+
private
|
36
|
+
|
37
|
+
def get_current_selector
|
38
|
+
super(&nil) || begin
|
39
|
+
return unless block_given?
|
40
|
+
|
41
|
+
default = yield
|
42
|
+
|
43
|
+
set_current_selector(default)
|
44
|
+
|
45
|
+
default
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
33
49
|
end
|
34
50
|
register_plugin :persistent, Persistent
|
35
51
|
end
|
@@ -23,24 +23,19 @@ module HTTPX
|
|
23
23
|
with(proxy: opts.merge(scheme: "ntlm"))
|
24
24
|
end
|
25
25
|
|
26
|
-
def fetch_response(request,
|
26
|
+
def fetch_response(request, selector, options)
|
27
27
|
response = super
|
28
28
|
|
29
29
|
if response &&
|
30
30
|
response.is_a?(Response) &&
|
31
31
|
response.status == 407 &&
|
32
32
|
!request.headers.key?("proxy-authorization") &&
|
33
|
-
response.headers.key?("proxy-authenticate")
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
request.headers["proxy-authorization"] =
|
40
|
-
connection.options.proxy.authenticate(request, response.headers["proxy-authenticate"])
|
41
|
-
send_request(request, connections)
|
42
|
-
return
|
43
|
-
end
|
33
|
+
response.headers.key?("proxy-authenticate") && options.proxy.can_authenticate?(response.headers["proxy-authenticate"])
|
34
|
+
request.transition(:idle)
|
35
|
+
request.headers["proxy-authorization"] =
|
36
|
+
options.proxy.authenticate(request, response.headers["proxy-authenticate"])
|
37
|
+
send_request(request, selector, options)
|
38
|
+
return
|
44
39
|
end
|
45
40
|
|
46
41
|
response
|
@@ -69,7 +64,14 @@ module HTTPX
|
|
69
64
|
parser = @parser
|
70
65
|
parser.extend(ProxyParser)
|
71
66
|
parser.on(:response, &method(:__http_on_connect))
|
72
|
-
parser.on(:close)
|
67
|
+
parser.on(:close) do |force|
|
68
|
+
next unless @parser
|
69
|
+
|
70
|
+
if force
|
71
|
+
reset
|
72
|
+
emit(:terminate)
|
73
|
+
end
|
74
|
+
end
|
73
75
|
parser.on(:reset) do
|
74
76
|
if parser.empty?
|
75
77
|
reset
|
@@ -90,8 +92,9 @@ module HTTPX
|
|
90
92
|
|
91
93
|
case @state
|
92
94
|
when :connecting
|
93
|
-
@parser
|
95
|
+
parser = @parser
|
94
96
|
@parser = nil
|
97
|
+
parser.close
|
95
98
|
when :idle
|
96
99
|
@parser.callbacks.clear
|
97
100
|
set_parser_callbacks(@parser)
|
@@ -163,8 +166,8 @@ module HTTPX
|
|
163
166
|
end
|
164
167
|
|
165
168
|
class ConnectRequest < Request
|
166
|
-
def initialize(uri,
|
167
|
-
super("CONNECT", uri,
|
169
|
+
def initialize(uri, options)
|
170
|
+
super("CONNECT", uri, options)
|
168
171
|
@headers.delete("accept")
|
169
172
|
end
|
170
173
|
|