httpx 0.10.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/README.md +11 -3
- data/doc/release_notes/0_11_0.md +76 -0
- data/lib/httpx/adapters/datadog.rb +205 -0
- data/lib/httpx/adapters/faraday.rb +0 -2
- data/lib/httpx/adapters/webmock.rb +123 -0
- data/lib/httpx/chainable.rb +1 -1
- data/lib/httpx/connection/http2.rb +4 -4
- data/lib/httpx/domain_name.rb +1 -3
- data/lib/httpx/errors.rb +2 -0
- data/lib/httpx/headers.rb +1 -0
- data/lib/httpx/io/ssl.rb +4 -8
- data/lib/httpx/io/udp.rb +1 -1
- data/lib/httpx/plugins/expect.rb +33 -8
- data/lib/httpx/plugins/multipart.rb +40 -35
- 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/proxy/socks5.rb +3 -2
- data/lib/httpx/plugins/push_promise.rb +2 -2
- data/lib/httpx/request.rb +21 -11
- data/lib/httpx/resolver.rb +7 -4
- data/lib/httpx/resolver/https.rb +4 -2
- data/lib/httpx/resolver/native.rb +10 -6
- data/lib/httpx/resolver/system.rb +1 -1
- data/lib/httpx/selector.rb +1 -0
- data/lib/httpx/session.rb +15 -18
- data/lib/httpx/transcoder.rb +6 -4
- data/lib/httpx/version.rb +1 -1
- data/sig/connection/http2.rbs +3 -4
- data/sig/headers.rbs +3 -0
- data/sig/plugins/multipart.rbs +27 -4
- data/sig/request.rbs +1 -1
- data/sig/resolver/https.rbs +2 -0
- data/sig/response.rbs +1 -1
- data/sig/session.rbs +1 -1
- data/sig/transcoder.rbs +2 -2
- data/sig/transcoder/body.rbs +2 -0
- data/sig/transcoder/form.rbs +7 -1
- data/sig/transcoder/json.rbs +3 -1
- metadata +9 -23
- data/sig/missing.rbs +0 -12
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/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
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/
|
4
|
+
[](https://gitlab.com/honeyryderchuck/httpx/pipelines?page=1&scope=all&ref=master)
|
5
5
|
[](https://honeyryderchuck.gitlab.io/httpx/coverage/#_AllFiles)
|
6
6
|
|
7
7
|
HTTPX is an HTTP client library for the Ruby programming language.
|
@@ -85,7 +85,15 @@ However if the server supports HTTP/1.1, it will try to use HTTP pipelining, fal
|
|
85
85
|
|
86
86
|
### Clean API
|
87
87
|
|
88
|
-
`
|
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
|
+
```
|
89
97
|
|
90
98
|
### Lightweight
|
91
99
|
|
@@ -135,7 +143,7 @@ Doesn't work with ruby 2.4.0 for Windows (see [#36](https://gitlab.com/honeyryde
|
|
135
143
|
|
136
144
|
* Discuss your contribution in an issue
|
137
145
|
* Fork it
|
138
|
-
* Make your changes, add some
|
146
|
+
* Make your changes, add some tests
|
139
147
|
* Ensure all tests pass (`bundle exec rake test`)
|
140
148
|
* Open a Merge Request (that's Pull Request in Github-ish)
|
141
149
|
* Wait for feedback
|
@@ -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,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
|
@@ -65,7 +65,6 @@ module Faraday
|
|
65
65
|
plugin(:compression)
|
66
66
|
plugin(:persistent)
|
67
67
|
|
68
|
-
# :nocov:
|
69
68
|
module ReasonPlugin
|
70
69
|
if RUBY_VERSION < "2.5"
|
71
70
|
def self.load_dependencies(*)
|
@@ -88,7 +87,6 @@ module Faraday
|
|
88
87
|
end
|
89
88
|
end
|
90
89
|
end
|
91
|
-
# :nocov:
|
92
90
|
plugin(ReasonPlugin)
|
93
91
|
end
|
94
92
|
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module WebMock
|
4
|
+
module HttpLibAdapters
|
5
|
+
if RUBY_VERSION < "2.5"
|
6
|
+
require "webrick/httpstatus"
|
7
|
+
HTTP_REASONS = WEBrick::HTTPStatus::StatusMessage
|
8
|
+
else
|
9
|
+
require "net/http/status"
|
10
|
+
HTTP_REASONS = Net::HTTP::STATUS_CODES
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# HTTPX plugin for webmock.
|
15
|
+
#
|
16
|
+
# Requests are "hijacked" at the session, before they're distributed to a connection.
|
17
|
+
#
|
18
|
+
module Plugin
|
19
|
+
module InstanceMethods
|
20
|
+
private
|
21
|
+
|
22
|
+
def send_requests(*requests, options)
|
23
|
+
request_signatures = requests.map do |request|
|
24
|
+
request_signature = _build_webmock_request_signature(request)
|
25
|
+
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
26
|
+
request_signature
|
27
|
+
end
|
28
|
+
|
29
|
+
responses = request_signatures.map do |request_signature|
|
30
|
+
WebMock::StubRegistry.instance.response_for_request(request_signature)
|
31
|
+
end
|
32
|
+
|
33
|
+
real_requests = {}
|
34
|
+
|
35
|
+
requests.each_with_index.each_with_object([request_signatures, responses]) do |(request, idx), (sig_reqs, mock_responses)|
|
36
|
+
if (webmock_response = mock_responses[idx])
|
37
|
+
mock_responses[idx] = _build_from_webmock_response(request, webmock_response)
|
38
|
+
WebMock::CallbackRegistry.invoke_callbacks({ lib: :httpx }, sig_reqs[idx], webmock_response)
|
39
|
+
log { "mocking #{request.uri} with #{mock_responses[idx].inspect}" }
|
40
|
+
elsif WebMock.net_connect_allowed?(sig_reqs[idx].uri)
|
41
|
+
log { "performing #{request.uri}" }
|
42
|
+
real_requests[request] = idx
|
43
|
+
else
|
44
|
+
raise WebMock::NetConnectNotAllowedError, sig_reqs[idx]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
unless real_requests.empty?
|
49
|
+
reqs = real_requests.keys
|
50
|
+
reqs.zip(super(*reqs, options)).each do |req, res|
|
51
|
+
idx = real_requests[req]
|
52
|
+
|
53
|
+
if WebMock::CallbackRegistry.any_callbacks?
|
54
|
+
webmock_response = _build_webmock_response(req, res)
|
55
|
+
WebMock::CallbackRegistry.invoke_callbacks(
|
56
|
+
{ lib: :httpx, real_request: true }, request_signatures[idx],
|
57
|
+
webmock_response
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
responses[idx] = res
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
responses
|
66
|
+
end
|
67
|
+
|
68
|
+
def _build_webmock_request_signature(request)
|
69
|
+
uri = WebMock::Util::URI.heuristic_parse(request.uri)
|
70
|
+
uri.path = uri.normalized_path.gsub("[^:]//", "/")
|
71
|
+
|
72
|
+
WebMock::RequestSignature.new(
|
73
|
+
request.verb,
|
74
|
+
uri.to_s,
|
75
|
+
body: request.body.each.to_a.join,
|
76
|
+
headers: request.headers.to_h
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
def _build_webmock_response(_request, response)
|
81
|
+
webmock_response = WebMock::Response.new
|
82
|
+
webmock_response.status = [response.status, HTTP_REASONS[response.status]]
|
83
|
+
webmock_response.body = response.body.to_s
|
84
|
+
webmock_response.headers = response.headers.to_h
|
85
|
+
webmock_response
|
86
|
+
end
|
87
|
+
|
88
|
+
def _build_from_webmock_response(request, webmock_response)
|
89
|
+
return ErrorResponse.new(request, webmock_response.exception, request.options) if webmock_response.exception
|
90
|
+
|
91
|
+
response = request.options.response_class.new(request,
|
92
|
+
webmock_response.status[0],
|
93
|
+
"2.0",
|
94
|
+
webmock_response.headers)
|
95
|
+
response << webmock_response.body.dup
|
96
|
+
response
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class HttpxAdapter < HttpLibAdapter
|
102
|
+
adapter_for :httpx
|
103
|
+
|
104
|
+
class << self
|
105
|
+
def enable!
|
106
|
+
@original_session = ::HTTPX::Session
|
107
|
+
|
108
|
+
webmock_session = ::HTTPX.plugin(Plugin)
|
109
|
+
|
110
|
+
::HTTPX.send(:remove_const, :Session)
|
111
|
+
::HTTPX.send(:const_set, :Session, webmock_session.class)
|
112
|
+
end
|
113
|
+
|
114
|
+
def disable!
|
115
|
+
return unless @original_session
|
116
|
+
|
117
|
+
HTTPX.send(:remove_const, :Session)
|
118
|
+
HTTPX.send(:const_set, :Session, @original_session)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|