httpx 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/httpx.rb +8 -2
- data/lib/httpx/adapters/faraday.rb +203 -0
- data/lib/httpx/altsvc.rb +4 -0
- data/lib/httpx/callbacks.rb +1 -4
- data/lib/httpx/chainable.rb +4 -3
- data/lib/httpx/connection.rb +326 -104
- data/lib/httpx/{channel → connection}/http1.rb +29 -15
- data/lib/httpx/{channel → connection}/http2.rb +12 -6
- data/lib/httpx/errors.rb +2 -0
- data/lib/httpx/headers.rb +4 -1
- data/lib/httpx/io/ssl.rb +5 -1
- data/lib/httpx/io/tcp.rb +13 -7
- data/lib/httpx/io/udp.rb +1 -0
- data/lib/httpx/io/unix.rb +1 -0
- data/lib/httpx/loggable.rb +34 -9
- data/lib/httpx/options.rb +57 -31
- data/lib/httpx/parser/http1.rb +8 -0
- data/lib/httpx/plugins/authentication.rb +4 -0
- data/lib/httpx/plugins/basic_authentication.rb +4 -0
- data/lib/httpx/plugins/compression.rb +22 -5
- data/lib/httpx/plugins/cookies.rb +89 -36
- data/lib/httpx/plugins/digest_authentication.rb +45 -26
- data/lib/httpx/plugins/follow_redirects.rb +61 -62
- data/lib/httpx/plugins/h2c.rb +78 -39
- data/lib/httpx/plugins/multipart.rb +5 -0
- data/lib/httpx/plugins/persistent.rb +29 -0
- data/lib/httpx/plugins/proxy.rb +125 -78
- data/lib/httpx/plugins/proxy/http.rb +31 -27
- data/lib/httpx/plugins/proxy/socks4.rb +30 -24
- data/lib/httpx/plugins/proxy/socks5.rb +49 -39
- data/lib/httpx/plugins/proxy/ssh.rb +81 -0
- data/lib/httpx/plugins/push_promise.rb +18 -9
- data/lib/httpx/plugins/retries.rb +43 -15
- data/lib/httpx/pool.rb +159 -0
- data/lib/httpx/registry.rb +2 -0
- data/lib/httpx/request.rb +10 -0
- data/lib/httpx/resolver.rb +2 -1
- data/lib/httpx/resolver/https.rb +62 -56
- data/lib/httpx/resolver/native.rb +48 -37
- data/lib/httpx/resolver/resolver_mixin.rb +16 -11
- data/lib/httpx/resolver/system.rb +11 -7
- data/lib/httpx/response.rb +24 -10
- data/lib/httpx/selector.rb +32 -39
- data/lib/httpx/{client.rb → session.rb} +99 -62
- data/lib/httpx/timeout.rb +7 -15
- data/lib/httpx/transcoder/body.rb +4 -0
- data/lib/httpx/transcoder/chunker.rb +4 -0
- data/lib/httpx/version.rb +1 -1
- metadata +10 -8
- data/lib/httpx/channel.rb +0 -367
@@ -3,7 +3,7 @@
|
|
3
3
|
require "httpx/parser/http1"
|
4
4
|
|
5
5
|
module HTTPX
|
6
|
-
class
|
6
|
+
class Connection::HTTP1
|
7
7
|
include Callbacks
|
8
8
|
include Loggable
|
9
9
|
|
@@ -39,7 +39,7 @@ module HTTPX
|
|
39
39
|
@parser << data
|
40
40
|
end
|
41
41
|
|
42
|
-
def send(request
|
42
|
+
def send(request)
|
43
43
|
if @max_requests.positive? &&
|
44
44
|
@requests.size >= @max_concurrent_requests
|
45
45
|
@pending << request
|
@@ -79,11 +79,11 @@ module HTTPX
|
|
79
79
|
return if @request.response
|
80
80
|
|
81
81
|
log(level: 2) { "headers received" }
|
82
|
-
headers = @options.headers_class.new(h)
|
83
|
-
response = @options.response_class.new(@request,
|
84
|
-
|
85
|
-
|
86
|
-
|
82
|
+
headers = @request.options.headers_class.new(h)
|
83
|
+
response = @request.options.response_class.new(@request,
|
84
|
+
@parser.status_code,
|
85
|
+
@parser.http_version.join("."),
|
86
|
+
headers)
|
87
87
|
log(color: :yellow) { "-> HEADLINE: #{response.status} HTTP/#{@parser.http_version.join(".")}" }
|
88
88
|
log(color: :yellow) { response.headers.each.map { |f, v| "-> HEADER: #{f}: #{v}" }.join("\n") }
|
89
89
|
|
@@ -93,6 +93,7 @@ module HTTPX
|
|
93
93
|
|
94
94
|
def on_trailers(h)
|
95
95
|
return unless @request
|
96
|
+
|
96
97
|
response = @request.response
|
97
98
|
log(level: 2) { "trailer headers received" }
|
98
99
|
|
@@ -102,6 +103,7 @@ module HTTPX
|
|
102
103
|
|
103
104
|
def on_data(chunk)
|
104
105
|
return unless @request
|
106
|
+
|
105
107
|
log(color: :green) { "-> DATA: #{chunk.bytesize} bytes..." }
|
106
108
|
log(level: 2, color: :green) { "-> #{chunk.inspect}" }
|
107
109
|
response = @request.response
|
@@ -111,6 +113,7 @@ module HTTPX
|
|
111
113
|
|
112
114
|
def on_complete
|
113
115
|
return unless @request
|
116
|
+
|
114
117
|
log(level: 2) { "parsing complete" }
|
115
118
|
dispatch
|
116
119
|
end
|
@@ -140,9 +143,7 @@ module HTTPX
|
|
140
143
|
|
141
144
|
def handle_error(ex)
|
142
145
|
if @pipelining
|
143
|
-
|
144
|
-
emit(:reset)
|
145
|
-
throw(:called)
|
146
|
+
disable
|
146
147
|
else
|
147
148
|
@requests.each do |request|
|
148
149
|
emit(:error, request, ex)
|
@@ -158,6 +159,7 @@ module HTTPX
|
|
158
159
|
when /keep\-alive/i
|
159
160
|
keep_alive = response.headers["keep-alive"]
|
160
161
|
return unless keep_alive
|
162
|
+
|
161
163
|
parameters = Hash[keep_alive.split(/ *, */).map do |pair|
|
162
164
|
pair.split(/ *= */)
|
163
165
|
end]
|
@@ -166,16 +168,27 @@ module HTTPX
|
|
166
168
|
keep_alive_timeout = parameters["timeout"].to_i
|
167
169
|
emit(:timeout, keep_alive_timeout)
|
168
170
|
end
|
169
|
-
|
170
|
-
when /close/i, nil
|
171
|
-
disable_pipelining
|
171
|
+
when /close/i
|
172
172
|
@max_requests = Float::INFINITY
|
173
|
-
|
173
|
+
disable
|
174
|
+
when nil
|
175
|
+
# In HTTP/1.1, it's keep alive by default
|
176
|
+
return if response.version == "1.1"
|
177
|
+
|
178
|
+
@max_requests = Float::INFINITY
|
179
|
+
disable
|
174
180
|
end
|
175
181
|
end
|
176
182
|
|
183
|
+
def disable
|
184
|
+
disable_pipelining
|
185
|
+
emit(:reset)
|
186
|
+
throw(:called)
|
187
|
+
end
|
188
|
+
|
177
189
|
def disable_pipelining
|
178
190
|
return if @requests.empty?
|
191
|
+
|
179
192
|
@requests.each { |r| r.transition(:idle) }
|
180
193
|
# server doesn't handle pipelining, and probably
|
181
194
|
# doesn't support keep-alive. Fallback to send only
|
@@ -226,6 +239,7 @@ module HTTPX
|
|
226
239
|
|
227
240
|
def join_body(request)
|
228
241
|
return if request.empty?
|
242
|
+
|
229
243
|
while (chunk = request.drain_body)
|
230
244
|
log(color: :green) { "<- DATA: #{chunk.bytesize} bytes..." }
|
231
245
|
log(level: 2, color: :green) { "<- #{chunk.inspect}" }
|
@@ -243,5 +257,5 @@ module HTTPX
|
|
243
257
|
UPCASED[field] || field.to_s.split("-").map(&:capitalize).join("-")
|
244
258
|
end
|
245
259
|
end
|
246
|
-
|
260
|
+
Connection.register "http/1.1", Connection::HTTP1
|
247
261
|
end
|
@@ -4,7 +4,7 @@ require "io/wait"
|
|
4
4
|
require "http/2"
|
5
5
|
|
6
6
|
module HTTPX
|
7
|
-
class
|
7
|
+
class Connection::HTTP2
|
8
8
|
include Callbacks
|
9
9
|
include Loggable
|
10
10
|
|
@@ -158,6 +158,8 @@ module HTTPX
|
|
158
158
|
end
|
159
159
|
|
160
160
|
def join_body(stream, request)
|
161
|
+
return if request.empty?
|
162
|
+
|
161
163
|
chunk = @drains.delete(request) || request.drain_body
|
162
164
|
while chunk
|
163
165
|
next_chunk = request.drain_body
|
@@ -181,8 +183,8 @@ module HTTPX
|
|
181
183
|
h.map { |k, v| "<- HEADER: #{k}: #{v}" }.join("\n")
|
182
184
|
end
|
183
185
|
_, status = h.shift
|
184
|
-
headers =
|
185
|
-
response =
|
186
|
+
headers = request.options.headers_class.new(h)
|
187
|
+
response = request.options.response_class.new(request, status, "2.0", headers)
|
186
188
|
request.response = response
|
187
189
|
@streams[request] = stream
|
188
190
|
end
|
@@ -195,6 +197,7 @@ module HTTPX
|
|
195
197
|
|
196
198
|
def on_stream_close(stream, request, error)
|
197
199
|
return handle(request, stream) if request.expects?
|
200
|
+
|
198
201
|
if error
|
199
202
|
ex = Error.new(stream.id, error)
|
200
203
|
ex.set_backtrace(caller)
|
@@ -230,9 +233,12 @@ module HTTPX
|
|
230
233
|
if error
|
231
234
|
ex = Error.new(0, error)
|
232
235
|
ex.set_backtrace(caller)
|
233
|
-
|
236
|
+
@streams.each_key do |request|
|
237
|
+
emit(:error, request, ex)
|
238
|
+
end
|
234
239
|
end
|
235
240
|
return unless @connection.state == :closed && @connection.active_stream_count.zero?
|
241
|
+
|
236
242
|
emit(:close)
|
237
243
|
end
|
238
244
|
|
@@ -269,7 +275,7 @@ module HTTPX
|
|
269
275
|
end
|
270
276
|
|
271
277
|
def on_promise(stream)
|
272
|
-
emit(:promise,
|
278
|
+
emit(:promise, @streams.key(stream.parent), stream)
|
273
279
|
end
|
274
280
|
|
275
281
|
def respond_to_missing?(meth, *args)
|
@@ -284,5 +290,5 @@ module HTTPX
|
|
284
290
|
end
|
285
291
|
end
|
286
292
|
end
|
287
|
-
|
293
|
+
Connection.register "h2", Connection::HTTP2
|
288
294
|
end
|
data/lib/httpx/errors.rb
CHANGED
data/lib/httpx/headers.rb
CHANGED
@@ -7,6 +7,7 @@ module HTTPX
|
|
7
7
|
class << self
|
8
8
|
def new(headers = nil)
|
9
9
|
return headers if headers.is_a?(self)
|
10
|
+
|
10
11
|
super
|
11
12
|
end
|
12
13
|
end
|
@@ -14,6 +15,7 @@ module HTTPX
|
|
14
15
|
def initialize(headers = nil)
|
15
16
|
@headers = {}
|
16
17
|
return unless headers
|
18
|
+
|
17
19
|
headers.each do |field, value|
|
18
20
|
array_value(value).each do |v|
|
19
21
|
add(downcased(field), v)
|
@@ -44,7 +46,6 @@ module HTTPX
|
|
44
46
|
# ignore what the +other+ headers has. Otherwise, set
|
45
47
|
#
|
46
48
|
def merge(other)
|
47
|
-
# TODO: deep-copy
|
48
49
|
headers = dup
|
49
50
|
other.each do |field, value|
|
50
51
|
headers[field] = value
|
@@ -64,6 +65,7 @@ module HTTPX
|
|
64
65
|
#
|
65
66
|
def []=(field, value)
|
66
67
|
return unless value
|
68
|
+
|
67
69
|
@headers[downcased(field)] = array_value(value)
|
68
70
|
end
|
69
71
|
|
@@ -94,6 +96,7 @@ module HTTPX
|
|
94
96
|
#
|
95
97
|
def each
|
96
98
|
return enum_for(__method__) { @headers.size } unless block_given?
|
99
|
+
|
97
100
|
@headers.each do |field, value|
|
98
101
|
yield(field, value.join(", ")) unless value.empty?
|
99
102
|
end
|
data/lib/httpx/io/ssl.rb
CHANGED
@@ -31,6 +31,7 @@ module HTTPX
|
|
31
31
|
def verify_hostname(host)
|
32
32
|
return false if @ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE
|
33
33
|
return false if @io.peer_cert.nil?
|
34
|
+
|
34
35
|
OpenSSL::SSL.verify_certificate_identity(@io.peer_cert, host)
|
35
36
|
end
|
36
37
|
|
@@ -54,6 +55,7 @@ module HTTPX
|
|
54
55
|
end
|
55
56
|
return if @state == :negotiated ||
|
56
57
|
@state != :connected
|
58
|
+
|
57
59
|
unless @io.is_a?(OpenSSL::SSL::SSLSocket)
|
58
60
|
@io = OpenSSL::SSL::SSLSocket.new(@io, @ctx)
|
59
61
|
@io.hostname = @hostname
|
@@ -112,8 +114,10 @@ module HTTPX
|
|
112
114
|
|
113
115
|
def log_transition_state(nextstate)
|
114
116
|
return super unless nextstate == :negotiated
|
117
|
+
|
115
118
|
server_cert = @io.peer_cert
|
116
|
-
"
|
119
|
+
"#{super}\n\n" \
|
120
|
+
"SSL connection using #{@io.ssl_version} / #{Array(@io.cipher).first}\n" \
|
117
121
|
"ALPN, server accepted to use #{protocol}\n" \
|
118
122
|
"Server certificate:\n" \
|
119
123
|
" subject: #{server_cert.subject}\n" \
|
data/lib/httpx/io/tcp.rb
CHANGED
@@ -13,28 +13,29 @@ module HTTPX
|
|
13
13
|
|
14
14
|
alias_method :host, :ip
|
15
15
|
|
16
|
-
def initialize(
|
16
|
+
def initialize(origin, addresses, options)
|
17
17
|
@state = :idle
|
18
|
-
@hostname =
|
18
|
+
@hostname = origin.host
|
19
19
|
@addresses = addresses
|
20
|
-
@ip_index = @addresses.size - 1
|
21
20
|
@options = Options.new(options)
|
22
21
|
@fallback_protocol = @options.fallback_protocol
|
23
|
-
@port =
|
22
|
+
@port = origin.port
|
24
23
|
if @options.io
|
25
24
|
@io = case @options.io
|
26
25
|
when Hash
|
27
|
-
@
|
28
|
-
@options.io[@ip] || @options.io["#{@ip}:#{@port}"]
|
26
|
+
@options.io[origin.authority]
|
29
27
|
else
|
30
|
-
@ip = @hostname
|
31
28
|
@options.io
|
32
29
|
end
|
30
|
+
_, _, _, @ip = @io.addr
|
31
|
+
@addresses ||= [@ip]
|
32
|
+
@ip_index = @addresses.size - 1
|
33
33
|
unless @io.nil?
|
34
34
|
@keep_open = true
|
35
35
|
@state = :connected
|
36
36
|
end
|
37
37
|
else
|
38
|
+
@ip_index = @addresses.size - 1
|
38
39
|
@ip = @addresses[@ip_index]
|
39
40
|
end
|
40
41
|
@io ||= build_socket
|
@@ -54,6 +55,7 @@ module HTTPX
|
|
54
55
|
|
55
56
|
def connect
|
56
57
|
return unless closed?
|
58
|
+
|
57
59
|
begin
|
58
60
|
if @io.closed?
|
59
61
|
transition(:idle)
|
@@ -65,6 +67,7 @@ module HTTPX
|
|
65
67
|
transition(:connected)
|
66
68
|
rescue Errno::EHOSTUNREACH => e
|
67
69
|
raise e if @ip_index <= 0
|
70
|
+
|
68
71
|
@ip_index -= 1
|
69
72
|
retry
|
70
73
|
rescue Errno::EINPROGRESS,
|
@@ -96,6 +99,7 @@ module HTTPX
|
|
96
99
|
ret = @io.read_nonblock(size, buffer, exception: false)
|
97
100
|
return 0 if ret == :wait_readable
|
98
101
|
return if ret.nil?
|
102
|
+
|
99
103
|
buffer.bytesize
|
100
104
|
end
|
101
105
|
|
@@ -103,6 +107,7 @@ module HTTPX
|
|
103
107
|
siz = @io.write_nonblock(buffer, exception: false)
|
104
108
|
return 0 if siz == :wait_writable
|
105
109
|
return if siz.nil?
|
110
|
+
|
106
111
|
buffer.slice!(0, siz)
|
107
112
|
siz
|
108
113
|
end
|
@@ -110,6 +115,7 @@ module HTTPX
|
|
110
115
|
|
111
116
|
def close
|
112
117
|
return if @keep_open || closed?
|
118
|
+
|
113
119
|
begin
|
114
120
|
@io.close
|
115
121
|
ensure
|
data/lib/httpx/io/udp.rb
CHANGED
data/lib/httpx/io/unix.rb
CHANGED
data/lib/httpx/loggable.rb
CHANGED
@@ -3,22 +3,47 @@
|
|
3
3
|
module HTTPX
|
4
4
|
module Loggable
|
5
5
|
COLORS = {
|
6
|
-
black:
|
7
|
-
red:
|
8
|
-
green:
|
9
|
-
yellow:
|
10
|
-
blue:
|
6
|
+
black: 30,
|
7
|
+
red: 31,
|
8
|
+
green: 32,
|
9
|
+
yellow: 33,
|
10
|
+
blue: 34,
|
11
11
|
magenta: 35,
|
12
|
-
cyan:
|
13
|
-
white:
|
12
|
+
cyan: 36,
|
13
|
+
white: 37,
|
14
14
|
}.freeze
|
15
15
|
|
16
16
|
def log(level: @options.debug_level, label: "", color: nil, &msg)
|
17
17
|
return unless @options.debug
|
18
18
|
return unless @options.debug_level >= level
|
19
|
+
|
20
|
+
debug_stream = @options.debug
|
21
|
+
|
19
22
|
message = (+label << msg.call << "\n")
|
20
|
-
message = "\e[#{COLORS[color]}m#{message}\e[0m" if
|
21
|
-
|
23
|
+
message = "\e[#{COLORS[color]}m#{message}\e[0m" if debug_stream.respond_to?(:isatty) && debug_stream.isatty
|
24
|
+
debug_stream << message
|
25
|
+
end
|
26
|
+
|
27
|
+
if !Exception.instance_methods.include?(:full_message)
|
28
|
+
|
29
|
+
def log_exception(ex, level: @options.debug_level, label: "", color: nil)
|
30
|
+
return unless @options.debug
|
31
|
+
return unless @options.debug_level >= level
|
32
|
+
|
33
|
+
message = +"#{ex.message} (#{ex.class})"
|
34
|
+
message << "\n" << ex.backtrace.join("\n") unless ex.backtrace.nil?
|
35
|
+
log(level: level, label: label, color: color) { message }
|
36
|
+
end
|
37
|
+
|
38
|
+
else
|
39
|
+
|
40
|
+
def log_exception(ex, level: @options.debug_level, label: "", color: nil)
|
41
|
+
return unless @options.debug
|
42
|
+
return unless @options.debug_level >= level
|
43
|
+
|
44
|
+
log(level: level, label: label, color: color) { ex.full_message }
|
45
|
+
end
|
46
|
+
|
22
47
|
end
|
23
48
|
end
|
24
49
|
end
|
data/lib/httpx/options.rb
CHANGED
@@ -16,6 +16,7 @@ module HTTPX
|
|
16
16
|
# let enhanced options go through
|
17
17
|
return options if self == Options && options.class > self
|
18
18
|
return options if options.is_a?(self)
|
19
|
+
|
19
20
|
super
|
20
21
|
end
|
21
22
|
|
@@ -31,31 +32,35 @@ module HTTPX
|
|
31
32
|
protected :"#{name}="
|
32
33
|
|
33
34
|
define_method(:"with_#{name}") do |value|
|
34
|
-
|
35
|
+
other = dup
|
36
|
+
other.send(:"#{name}=", other.instance_exec(value, &interpreter))
|
37
|
+
other
|
35
38
|
end
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
39
42
|
def initialize(options = {})
|
40
43
|
defaults = {
|
41
|
-
:debug
|
42
|
-
:debug_level
|
43
|
-
:ssl
|
44
|
-
:http2_settings
|
45
|
-
:fallback_protocol
|
46
|
-
:timeout
|
47
|
-
:headers
|
48
|
-
:max_concurrent_requests
|
49
|
-
:window_size
|
50
|
-
:body_threshold_size
|
51
|
-
:request_class
|
52
|
-
:response_class
|
53
|
-
:headers_class
|
54
|
-
:request_body_class
|
55
|
-
:response_body_class
|
56
|
-
:
|
57
|
-
:
|
58
|
-
:
|
44
|
+
:debug => ENV.key?("HTTPX_DEBUG") ? $stderr : nil,
|
45
|
+
:debug_level => (ENV["HTTPX_DEBUG"] || 1).to_i,
|
46
|
+
:ssl => {},
|
47
|
+
:http2_settings => { settings_enable_push: 0 },
|
48
|
+
:fallback_protocol => "http/1.1",
|
49
|
+
:timeout => Timeout.new,
|
50
|
+
:headers => {},
|
51
|
+
:max_concurrent_requests => MAX_CONCURRENT_REQUESTS,
|
52
|
+
:window_size => WINDOW_SIZE,
|
53
|
+
:body_threshold_size => MAX_BODY_THRESHOLD_SIZE,
|
54
|
+
:request_class => Class.new(Request),
|
55
|
+
:response_class => Class.new(Response),
|
56
|
+
:headers_class => Class.new(Headers),
|
57
|
+
:request_body_class => Class.new(Request::Body),
|
58
|
+
:response_body_class => Class.new(Response::Body),
|
59
|
+
:connection_class => Class.new(Connection),
|
60
|
+
:transport => nil,
|
61
|
+
:transport_options => nil,
|
62
|
+
:persistent => false,
|
63
|
+
:resolver_class => (ENV["HTTPX_RESOLVER"] || :native).to_sym,
|
59
64
|
}
|
60
65
|
|
61
66
|
defaults.merge!(options)
|
@@ -74,6 +79,7 @@ module HTTPX
|
|
74
79
|
def_option(:max_concurrent_requests) do |num|
|
75
80
|
max = Integer(num)
|
76
81
|
raise Error, ":max_concurrent_requests must be positive" unless max.positive?
|
82
|
+
|
77
83
|
self.max_concurrent_requests = max
|
78
84
|
end
|
79
85
|
|
@@ -88,18 +94,27 @@ module HTTPX
|
|
88
94
|
def_option(:transport) do |tr|
|
89
95
|
transport = tr.to_s
|
90
96
|
raise Error, "#{transport} is an unsupported transport type" unless IO.registry.key?(transport)
|
97
|
+
|
91
98
|
self.transport = transport
|
92
99
|
end
|
93
100
|
|
94
101
|
%w[
|
95
102
|
params form json body
|
96
103
|
follow ssl http2_settings
|
97
|
-
request_class response_class headers_class request_body_class response_body_class
|
104
|
+
request_class response_class headers_class request_body_class response_body_class connection_class
|
98
105
|
io fallback_protocol debug debug_level transport_options resolver_class resolver_options
|
106
|
+
persistent
|
99
107
|
].each do |method_name|
|
100
108
|
def_option(method_name)
|
101
109
|
end
|
102
110
|
|
111
|
+
def ==(other)
|
112
|
+
ivars = instance_variables | other.instance_variables
|
113
|
+
ivars.all? do |ivar|
|
114
|
+
instance_variable_get(ivar) == other.instance_variable_get(ivar)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
103
118
|
def merge(other)
|
104
119
|
h1 = to_hash
|
105
120
|
h2 = other.to_hash
|
@@ -123,17 +138,28 @@ module HTTPX
|
|
123
138
|
Hash[*hash_pairs]
|
124
139
|
end
|
125
140
|
|
126
|
-
def
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
141
|
+
def initialize_dup(other)
|
142
|
+
self.headers = other.headers.dup
|
143
|
+
self.ssl = other.ssl.dup
|
144
|
+
self.request_class = other.request_class.dup
|
145
|
+
self.response_class = other.response_class.dup
|
146
|
+
self.headers_class = other.headers_class.dup
|
147
|
+
self.request_body_class = other.request_body_class.dup
|
148
|
+
self.response_body_class = other.response_body_class.dup
|
149
|
+
self.connection_class = other.connection_class.dup
|
150
|
+
end
|
151
|
+
|
152
|
+
def freeze
|
153
|
+
super
|
154
|
+
|
155
|
+
headers.freeze
|
156
|
+
ssl.freeze
|
157
|
+
request_class.freeze
|
158
|
+
response_class.freeze
|
159
|
+
headers_class.freeze
|
160
|
+
request_body_class.freeze
|
161
|
+
response_body_class.freeze
|
162
|
+
connection_class.freeze
|
137
163
|
end
|
138
164
|
|
139
165
|
protected
|