httpx-patched 1.6.2.1
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 +7 -0
- data/LICENSE.txt +191 -0
- data/README.md +162 -0
- data/doc/release_notes/0_0_1.md +7 -0
- data/doc/release_notes/0_0_2.md +9 -0
- data/doc/release_notes/0_0_3.md +9 -0
- data/doc/release_notes/0_0_4.md +7 -0
- data/doc/release_notes/0_0_5.md +5 -0
- data/doc/release_notes/0_10_0.md +66 -0
- data/doc/release_notes/0_10_1.md +37 -0
- data/doc/release_notes/0_10_2.md +5 -0
- data/doc/release_notes/0_11_0.md +74 -0
- data/doc/release_notes/0_11_1.md +5 -0
- data/doc/release_notes/0_11_2.md +5 -0
- data/doc/release_notes/0_11_3.md +5 -0
- data/doc/release_notes/0_12_0.md +55 -0
- data/doc/release_notes/0_13_0.md +58 -0
- data/doc/release_notes/0_13_1.md +5 -0
- data/doc/release_notes/0_13_2.md +9 -0
- data/doc/release_notes/0_14_0.md +79 -0
- data/doc/release_notes/0_14_1.md +7 -0
- data/doc/release_notes/0_14_2.md +6 -0
- data/doc/release_notes/0_14_3.md +5 -0
- data/doc/release_notes/0_14_4.md +5 -0
- data/doc/release_notes/0_14_5.md +11 -0
- data/doc/release_notes/0_15_0.md +53 -0
- data/doc/release_notes/0_15_1.md +8 -0
- data/doc/release_notes/0_15_2.md +9 -0
- data/doc/release_notes/0_15_3.md +5 -0
- data/doc/release_notes/0_15_4.md +5 -0
- data/doc/release_notes/0_16_0.md +93 -0
- data/doc/release_notes/0_16_1.md +5 -0
- data/doc/release_notes/0_17_0.md +49 -0
- data/doc/release_notes/0_18_0.md +69 -0
- data/doc/release_notes/0_18_1.md +12 -0
- data/doc/release_notes/0_18_2.md +10 -0
- data/doc/release_notes/0_18_3.md +7 -0
- data/doc/release_notes/0_18_4.md +14 -0
- data/doc/release_notes/0_18_5.md +10 -0
- data/doc/release_notes/0_18_6.md +5 -0
- data/doc/release_notes/0_18_7.md +5 -0
- data/doc/release_notes/0_19_0.md +39 -0
- data/doc/release_notes/0_19_1.md +5 -0
- data/doc/release_notes/0_19_2.md +7 -0
- data/doc/release_notes/0_19_3.md +6 -0
- data/doc/release_notes/0_19_4.md +14 -0
- data/doc/release_notes/0_19_5.md +13 -0
- data/doc/release_notes/0_19_6.md +5 -0
- data/doc/release_notes/0_19_7.md +5 -0
- data/doc/release_notes/0_19_8.md +5 -0
- data/doc/release_notes/0_1_0.md +9 -0
- data/doc/release_notes/0_20_0.md +36 -0
- data/doc/release_notes/0_20_1.md +5 -0
- data/doc/release_notes/0_20_2.md +7 -0
- data/doc/release_notes/0_20_3.md +6 -0
- data/doc/release_notes/0_20_4.md +17 -0
- data/doc/release_notes/0_20_5.md +3 -0
- data/doc/release_notes/0_21_0.md +96 -0
- data/doc/release_notes/0_21_1.md +12 -0
- data/doc/release_notes/0_22_0.md +13 -0
- data/doc/release_notes/0_22_1.md +11 -0
- data/doc/release_notes/0_22_2.md +5 -0
- data/doc/release_notes/0_22_3.md +55 -0
- data/doc/release_notes/0_22_4.md +6 -0
- data/doc/release_notes/0_22_5.md +6 -0
- data/doc/release_notes/0_23_0.md +42 -0
- data/doc/release_notes/0_23_1.md +5 -0
- data/doc/release_notes/0_23_2.md +5 -0
- data/doc/release_notes/0_23_3.md +6 -0
- data/doc/release_notes/0_23_4.md +5 -0
- data/doc/release_notes/0_24_0.md +48 -0
- data/doc/release_notes/0_24_1.md +12 -0
- data/doc/release_notes/0_24_2.md +12 -0
- data/doc/release_notes/0_24_3.md +12 -0
- data/doc/release_notes/0_24_4.md +18 -0
- data/doc/release_notes/0_24_5.md +6 -0
- data/doc/release_notes/0_24_6.md +5 -0
- data/doc/release_notes/0_24_7.md +10 -0
- data/doc/release_notes/0_2_0.md +5 -0
- data/doc/release_notes/0_2_1.md +16 -0
- data/doc/release_notes/0_3_0.md +12 -0
- data/doc/release_notes/0_3_1.md +6 -0
- data/doc/release_notes/0_4_0.md +51 -0
- data/doc/release_notes/0_4_1.md +3 -0
- data/doc/release_notes/0_5_0.md +15 -0
- data/doc/release_notes/0_5_1.md +14 -0
- data/doc/release_notes/0_6_0.md +5 -0
- data/doc/release_notes/0_6_1.md +6 -0
- data/doc/release_notes/0_6_2.md +6 -0
- data/doc/release_notes/0_6_3.md +13 -0
- data/doc/release_notes/0_6_4.md +21 -0
- data/doc/release_notes/0_6_5.md +22 -0
- data/doc/release_notes/0_6_6.md +19 -0
- data/doc/release_notes/0_6_7.md +5 -0
- data/doc/release_notes/0_7_0.md +46 -0
- data/doc/release_notes/0_8_0.md +27 -0
- data/doc/release_notes/0_8_1.md +8 -0
- data/doc/release_notes/0_8_2.md +7 -0
- data/doc/release_notes/0_9_0.md +38 -0
- data/doc/release_notes/1_0_0.md +60 -0
- data/doc/release_notes/1_0_1.md +5 -0
- data/doc/release_notes/1_0_2.md +7 -0
- data/doc/release_notes/1_1_0.md +32 -0
- data/doc/release_notes/1_1_1.md +17 -0
- data/doc/release_notes/1_1_2.md +12 -0
- data/doc/release_notes/1_1_3.md +18 -0
- data/doc/release_notes/1_1_4.md +6 -0
- data/doc/release_notes/1_1_5.md +12 -0
- data/doc/release_notes/1_2_0.md +49 -0
- data/doc/release_notes/1_2_1.md +6 -0
- data/doc/release_notes/1_2_2.md +10 -0
- data/doc/release_notes/1_2_3.md +16 -0
- data/doc/release_notes/1_2_4.md +8 -0
- data/doc/release_notes/1_2_5.md +7 -0
- data/doc/release_notes/1_2_6.md +13 -0
- 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/doc/release_notes/1_5_0.md +126 -0
- data/doc/release_notes/1_5_1.md +6 -0
- data/doc/release_notes/1_6_0.md +50 -0
- data/doc/release_notes/1_6_1.md +17 -0
- data/doc/release_notes/1_6_2.md +11 -0
- data/lib/httpx/adapters/datadog.rb +359 -0
- data/lib/httpx/adapters/faraday.rb +303 -0
- data/lib/httpx/adapters/sentry.rb +121 -0
- data/lib/httpx/adapters/webmock.rb +175 -0
- data/lib/httpx/altsvc.rb +163 -0
- data/lib/httpx/base64.rb +27 -0
- data/lib/httpx/buffer.rb +61 -0
- data/lib/httpx/callbacks.rb +35 -0
- data/lib/httpx/chainable.rb +106 -0
- data/lib/httpx/connection/http1.rb +399 -0
- data/lib/httpx/connection/http2.rb +468 -0
- data/lib/httpx/connection.rb +954 -0
- data/lib/httpx/domain_name.rb +145 -0
- data/lib/httpx/errors.rb +111 -0
- data/lib/httpx/extensions.rb +59 -0
- data/lib/httpx/headers.rb +176 -0
- data/lib/httpx/io/ssl.rb +163 -0
- data/lib/httpx/io/tcp.rb +239 -0
- data/lib/httpx/io/udp.rb +62 -0
- data/lib/httpx/io/unix.rb +71 -0
- data/lib/httpx/io.rb +11 -0
- data/lib/httpx/loggable.rb +56 -0
- data/lib/httpx/options.rb +463 -0
- data/lib/httpx/parser/http1.rb +186 -0
- data/lib/httpx/plugins/auth/basic.rb +20 -0
- data/lib/httpx/plugins/auth/digest.rb +102 -0
- data/lib/httpx/plugins/auth/ntlm.rb +35 -0
- data/lib/httpx/plugins/auth/socks5.rb +22 -0
- data/lib/httpx/plugins/auth.rb +25 -0
- data/lib/httpx/plugins/aws_sdk_authentication.rb +111 -0
- data/lib/httpx/plugins/aws_sigv4.rb +239 -0
- data/lib/httpx/plugins/basic_auth.rb +29 -0
- data/lib/httpx/plugins/brotli.rb +50 -0
- data/lib/httpx/plugins/callbacks.rb +127 -0
- data/lib/httpx/plugins/circuit_breaker/circuit.rb +100 -0
- data/lib/httpx/plugins/circuit_breaker/circuit_store.rb +53 -0
- data/lib/httpx/plugins/circuit_breaker.rb +147 -0
- data/lib/httpx/plugins/content_digest.rb +204 -0
- data/lib/httpx/plugins/cookies/cookie.rb +174 -0
- data/lib/httpx/plugins/cookies/jar.rb +95 -0
- data/lib/httpx/plugins/cookies/set_cookie_parser.rb +143 -0
- data/lib/httpx/plugins/cookies.rb +107 -0
- data/lib/httpx/plugins/digest_auth.rb +67 -0
- data/lib/httpx/plugins/expect.rb +120 -0
- data/lib/httpx/plugins/fiber_concurrency.rb +195 -0
- data/lib/httpx/plugins/follow_redirects.rb +233 -0
- data/lib/httpx/plugins/grpc/call.rb +63 -0
- data/lib/httpx/plugins/grpc/grpc_encoding.rb +90 -0
- data/lib/httpx/plugins/grpc/message.rb +55 -0
- data/lib/httpx/plugins/grpc.rb +282 -0
- data/lib/httpx/plugins/h2c.rb +127 -0
- data/lib/httpx/plugins/internal_telemetry.rb +107 -0
- data/lib/httpx/plugins/ntlm_auth.rb +62 -0
- data/lib/httpx/plugins/oauth.rb +183 -0
- data/lib/httpx/plugins/persistent.rb +82 -0
- data/lib/httpx/plugins/proxy/http.rb +184 -0
- data/lib/httpx/plugins/proxy/socks4.rb +135 -0
- data/lib/httpx/plugins/proxy/socks5.rb +194 -0
- data/lib/httpx/plugins/proxy/ssh.rb +94 -0
- data/lib/httpx/plugins/proxy.rb +349 -0
- data/lib/httpx/plugins/push_promise.rb +81 -0
- data/lib/httpx/plugins/query.rb +35 -0
- data/lib/httpx/plugins/rate_limiter.rb +55 -0
- data/lib/httpx/plugins/response_cache/file_store.rb +140 -0
- data/lib/httpx/plugins/response_cache/store.rb +33 -0
- data/lib/httpx/plugins/response_cache.rb +333 -0
- data/lib/httpx/plugins/retries.rb +230 -0
- data/lib/httpx/plugins/ssrf_filter.rb +145 -0
- data/lib/httpx/plugins/stream.rb +183 -0
- data/lib/httpx/plugins/stream_bidi.rb +315 -0
- data/lib/httpx/plugins/upgrade/h2.rb +64 -0
- data/lib/httpx/plugins/upgrade.rb +86 -0
- data/lib/httpx/plugins/webdav.rb +86 -0
- data/lib/httpx/plugins/xml.rb +76 -0
- data/lib/httpx/pmatch_extensions.rb +33 -0
- data/lib/httpx/pool.rb +190 -0
- data/lib/httpx/punycode.rb +22 -0
- data/lib/httpx/request/body.rb +158 -0
- data/lib/httpx/request.rb +328 -0
- data/lib/httpx/resolver/entry.rb +30 -0
- data/lib/httpx/resolver/https.rb +256 -0
- data/lib/httpx/resolver/multi.rb +102 -0
- data/lib/httpx/resolver/native.rb +547 -0
- data/lib/httpx/resolver/resolver.rb +173 -0
- data/lib/httpx/resolver/system.rb +255 -0
- data/lib/httpx/resolver.rb +189 -0
- data/lib/httpx/response/body.rb +242 -0
- data/lib/httpx/response/buffer.rb +115 -0
- data/lib/httpx/response.rb +304 -0
- data/lib/httpx/selector.rb +282 -0
- data/lib/httpx/session.rb +612 -0
- data/lib/httpx/session_extensions.rb +30 -0
- data/lib/httpx/timers.rb +133 -0
- data/lib/httpx/transcoder/body.rb +43 -0
- data/lib/httpx/transcoder/chunker.rb +115 -0
- data/lib/httpx/transcoder/deflate.rb +37 -0
- data/lib/httpx/transcoder/form.rb +68 -0
- data/lib/httpx/transcoder/gzip.rb +71 -0
- data/lib/httpx/transcoder/json.rb +71 -0
- data/lib/httpx/transcoder/multipart/decoder.rb +141 -0
- data/lib/httpx/transcoder/multipart/encoder.rb +120 -0
- data/lib/httpx/transcoder/multipart/mime_type_detector.rb +78 -0
- data/lib/httpx/transcoder/multipart/part.rb +35 -0
- data/lib/httpx/transcoder/multipart.rb +31 -0
- data/lib/httpx/transcoder/utils/body_reader.rb +46 -0
- data/lib/httpx/transcoder/utils/deflater.rb +75 -0
- data/lib/httpx/transcoder.rb +91 -0
- data/lib/httpx/utils.rb +75 -0
- data/lib/httpx/version.rb +5 -0
- data/lib/httpx.rb +66 -0
- data/sig/altsvc.rbs +33 -0
- data/sig/buffer.rbs +27 -0
- data/sig/callbacks.rbs +15 -0
- data/sig/chainable.rbs +55 -0
- data/sig/connection/http1.rbs +85 -0
- data/sig/connection/http2.rbs +116 -0
- data/sig/connection.rbs +169 -0
- data/sig/domain_name.rbs +17 -0
- data/sig/errors.rbs +69 -0
- data/sig/headers.rbs +49 -0
- data/sig/httpx.rbs +27 -0
- data/sig/io/ssl.rbs +27 -0
- data/sig/io/tcp.rbs +72 -0
- data/sig/io/udp.rbs +25 -0
- data/sig/io/unix.rbs +26 -0
- data/sig/io.rbs +3 -0
- data/sig/loggable.rbs +17 -0
- data/sig/options.rbs +202 -0
- data/sig/parser/http1.rbs +59 -0
- data/sig/plugins/auth/basic.rbs +17 -0
- data/sig/plugins/auth/digest.rbs +25 -0
- data/sig/plugins/auth/ntlm.rbs +20 -0
- data/sig/plugins/auth/socks5.rbs +18 -0
- data/sig/plugins/auth.rbs +13 -0
- data/sig/plugins/aws_sdk_authentication.rbs +43 -0
- data/sig/plugins/aws_sigv4.rbs +78 -0
- data/sig/plugins/basic_auth.rbs +15 -0
- data/sig/plugins/brotli.rbs +22 -0
- data/sig/plugins/callbacks.rbs +38 -0
- data/sig/plugins/circuit_breaker.rbs +71 -0
- data/sig/plugins/compression.rbs +57 -0
- data/sig/plugins/content_digest.rbs +51 -0
- data/sig/plugins/cookies/cookie.rbs +55 -0
- data/sig/plugins/cookies/jar.rbs +26 -0
- data/sig/plugins/cookies/set_cookie_parser.rbs +22 -0
- data/sig/plugins/cookies.rbs +28 -0
- data/sig/plugins/digest_auth.rbs +21 -0
- data/sig/plugins/expect.rbs +15 -0
- data/sig/plugins/fiber_concurrency.rbs +51 -0
- data/sig/plugins/follow_redirects.rbs +47 -0
- data/sig/plugins/grpc/call.rbs +23 -0
- data/sig/plugins/grpc/grpc_encoding.rbs +37 -0
- data/sig/plugins/grpc/message.rbs +17 -0
- data/sig/plugins/grpc.rbs +65 -0
- data/sig/plugins/h2c.rbs +27 -0
- data/sig/plugins/ntlm_auth.rbs +21 -0
- data/sig/plugins/oauth.rbs +68 -0
- data/sig/plugins/persistent.rbs +14 -0
- data/sig/plugins/proxy/http.rbs +30 -0
- data/sig/plugins/proxy/socks4.rbs +37 -0
- data/sig/plugins/proxy/socks5.rbs +49 -0
- data/sig/plugins/proxy/ssh.rbs +18 -0
- data/sig/plugins/proxy.rbs +70 -0
- data/sig/plugins/push_promise.rbs +23 -0
- data/sig/plugins/query.rbs +18 -0
- data/sig/plugins/rate_limiter.rbs +13 -0
- data/sig/plugins/response_cache/file_store.rbs +19 -0
- data/sig/plugins/response_cache/store.rbs +13 -0
- data/sig/plugins/response_cache.rbs +86 -0
- data/sig/plugins/retries.rbs +66 -0
- data/sig/plugins/ssrf_filter.rbs +26 -0
- data/sig/plugins/stream.rbs +54 -0
- data/sig/plugins/stream_bidi.rbs +68 -0
- data/sig/plugins/upgrade/h2.rbs +9 -0
- data/sig/plugins/upgrade.rbs +29 -0
- data/sig/plugins/webdav.rbs +23 -0
- data/sig/plugins/xml.rbs +37 -0
- data/sig/pool.rbs +51 -0
- data/sig/punycode.rbs +5 -0
- data/sig/request/body.rbs +34 -0
- data/sig/request.rbs +88 -0
- data/sig/resolver/entry.rbs +13 -0
- data/sig/resolver/https.rbs +45 -0
- data/sig/resolver/multi.rbs +32 -0
- data/sig/resolver/native.rbs +74 -0
- data/sig/resolver/resolver.rbs +64 -0
- data/sig/resolver/system.rbs +34 -0
- data/sig/resolver.rbs +48 -0
- data/sig/response/body.rbs +52 -0
- data/sig/response/buffer.rbs +23 -0
- data/sig/response.rbs +103 -0
- data/sig/selector.rbs +68 -0
- data/sig/session.rbs +104 -0
- data/sig/timers.rbs +54 -0
- data/sig/transcoder/body.rbs +24 -0
- data/sig/transcoder/chunker.rbs +49 -0
- data/sig/transcoder/deflate.rbs +12 -0
- data/sig/transcoder/form.rbs +34 -0
- data/sig/transcoder/gzip.rbs +27 -0
- data/sig/transcoder/json.rbs +28 -0
- data/sig/transcoder/multipart.rbs +103 -0
- data/sig/transcoder/utils/body_reader.rbs +15 -0
- data/sig/transcoder/utils/deflater.rbs +28 -0
- data/sig/transcoder.rbs +43 -0
- data/sig/utils.rbs +19 -0
- metadata +518 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "datadog/tracing/contrib/integration"
|
|
4
|
+
require "datadog/tracing/contrib/configuration/settings"
|
|
5
|
+
require "datadog/tracing/contrib/patcher"
|
|
6
|
+
|
|
7
|
+
module Datadog::Tracing
|
|
8
|
+
module Contrib
|
|
9
|
+
module HTTPX
|
|
10
|
+
DATADOG_VERSION = defined?(::DDTrace) ? ::DDTrace::VERSION : ::Datadog::VERSION
|
|
11
|
+
|
|
12
|
+
METADATA_MODULE = Datadog::Tracing::Metadata
|
|
13
|
+
|
|
14
|
+
TYPE_OUTBOUND = Datadog::Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
|
|
15
|
+
|
|
16
|
+
TAG_BASE_SERVICE = if Gem::Version.new(DATADOG_VERSION::STRING) < Gem::Version.new("1.15.0")
|
|
17
|
+
"_dd.base_service"
|
|
18
|
+
else
|
|
19
|
+
Datadog::Tracing::Contrib::Ext::Metadata::TAG_BASE_SERVICE
|
|
20
|
+
end
|
|
21
|
+
TAG_PEER_HOSTNAME = Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME
|
|
22
|
+
|
|
23
|
+
TAG_KIND = Datadog::Tracing::Metadata::Ext::TAG_KIND
|
|
24
|
+
TAG_CLIENT = Datadog::Tracing::Metadata::Ext::SpanKind::TAG_CLIENT
|
|
25
|
+
TAG_COMPONENT = Datadog::Tracing::Metadata::Ext::TAG_COMPONENT
|
|
26
|
+
TAG_OPERATION = Datadog::Tracing::Metadata::Ext::TAG_OPERATION
|
|
27
|
+
TAG_URL = Datadog::Tracing::Metadata::Ext::HTTP::TAG_URL
|
|
28
|
+
TAG_METHOD = Datadog::Tracing::Metadata::Ext::HTTP::TAG_METHOD
|
|
29
|
+
TAG_TARGET_HOST = Datadog::Tracing::Metadata::Ext::NET::TAG_TARGET_HOST
|
|
30
|
+
TAG_TARGET_PORT = Datadog::Tracing::Metadata::Ext::NET::TAG_TARGET_PORT
|
|
31
|
+
|
|
32
|
+
TAG_STATUS_CODE = Datadog::Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE
|
|
33
|
+
|
|
34
|
+
# HTTPX Datadog Plugin
|
|
35
|
+
#
|
|
36
|
+
# Enables tracing for httpx requests.
|
|
37
|
+
#
|
|
38
|
+
# A span will be created for each request transaction; the span is created lazily only when
|
|
39
|
+
# buffering a request, and it is fed the start time stored inside the tracer object.
|
|
40
|
+
#
|
|
41
|
+
module Plugin
|
|
42
|
+
module RequestTracer
|
|
43
|
+
extend Contrib::HttpAnnotationHelper
|
|
44
|
+
|
|
45
|
+
module_function
|
|
46
|
+
|
|
47
|
+
SPAN_REQUEST = "httpx.request"
|
|
48
|
+
|
|
49
|
+
# initializes tracing on the +request+.
|
|
50
|
+
def call(request)
|
|
51
|
+
return unless configuration(request).enabled
|
|
52
|
+
|
|
53
|
+
span = nil
|
|
54
|
+
|
|
55
|
+
# request objects are reused, when already buffered requests get rerouted to a different
|
|
56
|
+
# connection due to connection issues, or when they already got a response, but need to
|
|
57
|
+
# be retried. In such situations, the original span needs to be extended for the former,
|
|
58
|
+
# while a new is required for the latter.
|
|
59
|
+
request.on(:idle) do
|
|
60
|
+
span = nil
|
|
61
|
+
end
|
|
62
|
+
# the span is initialized when the request is buffered in the parser, which is the closest
|
|
63
|
+
# one gets to actually sending the request.
|
|
64
|
+
request.on(:headers) do
|
|
65
|
+
next if span
|
|
66
|
+
|
|
67
|
+
span = initialize_span(request, now)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
request.on(:response) do |response|
|
|
71
|
+
span = initialize_span(request, request.init_time) if !span && request.init_time
|
|
72
|
+
|
|
73
|
+
finish(response, span)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def finish(response, span)
|
|
78
|
+
if response.is_a?(::HTTPX::ErrorResponse)
|
|
79
|
+
span.set_error(response.error)
|
|
80
|
+
else
|
|
81
|
+
span.set_tag(TAG_STATUS_CODE, response.status.to_s)
|
|
82
|
+
|
|
83
|
+
span.set_error(::HTTPX::HTTPError.new(response)) if response.status >= 400 && response.status <= 599
|
|
84
|
+
|
|
85
|
+
span.set_tags(
|
|
86
|
+
Datadog.configuration.tracing.header_tags.response_tags(response.headers.to_h)
|
|
87
|
+
) if Datadog.configuration.tracing.respond_to?(:header_tags)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
span.finish
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# return a span initialized with the +@request+ state.
|
|
94
|
+
def initialize_span(request, start_time)
|
|
95
|
+
verb = request.verb
|
|
96
|
+
uri = request.uri
|
|
97
|
+
|
|
98
|
+
config = configuration(request)
|
|
99
|
+
|
|
100
|
+
span = create_span(request, config, start_time)
|
|
101
|
+
|
|
102
|
+
span.resource = verb
|
|
103
|
+
|
|
104
|
+
# Tag original global service name if not used
|
|
105
|
+
span.set_tag(TAG_BASE_SERVICE, Datadog.configuration.service) if span.service != Datadog.configuration.service
|
|
106
|
+
|
|
107
|
+
span.set_tag(TAG_KIND, TAG_CLIENT)
|
|
108
|
+
|
|
109
|
+
span.set_tag(TAG_COMPONENT, "httpx")
|
|
110
|
+
span.set_tag(TAG_OPERATION, "request")
|
|
111
|
+
|
|
112
|
+
span.set_tag(TAG_URL, request.path)
|
|
113
|
+
span.set_tag(TAG_METHOD, verb)
|
|
114
|
+
|
|
115
|
+
span.set_tag(TAG_TARGET_HOST, uri.host)
|
|
116
|
+
span.set_tag(TAG_TARGET_PORT, uri.port)
|
|
117
|
+
|
|
118
|
+
span.set_tag(TAG_PEER_HOSTNAME, uri.host)
|
|
119
|
+
|
|
120
|
+
# Tag as an external peer service
|
|
121
|
+
# span.set_tag(TAG_PEER_SERVICE, span.service)
|
|
122
|
+
|
|
123
|
+
if config[:distributed_tracing]
|
|
124
|
+
propagate_trace_http(
|
|
125
|
+
Datadog::Tracing.active_trace,
|
|
126
|
+
request.headers
|
|
127
|
+
)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Set analytics sample rate
|
|
131
|
+
if Contrib::Analytics.enabled?(config[:analytics_enabled])
|
|
132
|
+
Contrib::Analytics.set_sample_rate(span, config[:analytics_sample_rate])
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
span.set_tags(
|
|
136
|
+
Datadog.configuration.tracing.header_tags.request_tags(request.headers.to_h)
|
|
137
|
+
) if Datadog.configuration.tracing.respond_to?(:header_tags)
|
|
138
|
+
|
|
139
|
+
span
|
|
140
|
+
rescue StandardError => e
|
|
141
|
+
Datadog.logger.error("error preparing span for http request: #{e}")
|
|
142
|
+
Datadog.logger.error(e.backtrace)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def now
|
|
146
|
+
::Datadog::Core::Utils::Time.now.utc
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def configuration(request)
|
|
150
|
+
Datadog.configuration.tracing[:httpx, request.uri.host]
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
if Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("2.0.0")
|
|
154
|
+
def propagate_trace_http(trace, headers)
|
|
155
|
+
Datadog::Tracing::Contrib::HTTP.inject(trace, headers)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def create_span(request, configuration, start_time)
|
|
159
|
+
Datadog::Tracing.trace(
|
|
160
|
+
SPAN_REQUEST,
|
|
161
|
+
service: service_name(request.uri.host, configuration),
|
|
162
|
+
type: TYPE_OUTBOUND,
|
|
163
|
+
start_time: start_time
|
|
164
|
+
)
|
|
165
|
+
end
|
|
166
|
+
else
|
|
167
|
+
def propagate_trace_http(trace, headers)
|
|
168
|
+
Datadog::Tracing::Propagation::HTTP.inject!(trace.to_digest, headers)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def create_span(request, configuration, start_time)
|
|
172
|
+
Datadog::Tracing.trace(
|
|
173
|
+
SPAN_REQUEST,
|
|
174
|
+
service: service_name(request.uri.host, configuration),
|
|
175
|
+
span_type: TYPE_OUTBOUND,
|
|
176
|
+
start_time: start_time
|
|
177
|
+
)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
module RequestMethods
|
|
183
|
+
attr_accessor :init_time
|
|
184
|
+
|
|
185
|
+
# intercepts request initialization to inject the tracing logic.
|
|
186
|
+
def initialize(*)
|
|
187
|
+
super
|
|
188
|
+
|
|
189
|
+
@init_time = nil
|
|
190
|
+
|
|
191
|
+
return unless Datadog::Tracing.enabled?
|
|
192
|
+
|
|
193
|
+
RequestTracer.call(self)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def response=(*)
|
|
197
|
+
# init_time should be set when it's send to a connection.
|
|
198
|
+
# However, there are situations where connection initialization fails.
|
|
199
|
+
# Example is the :ssrf_filter plugin, which raises an error on
|
|
200
|
+
# initialize if the host is an IP which matches against the known set.
|
|
201
|
+
# in such cases, we'll just set here right here.
|
|
202
|
+
@init_time ||= ::Datadog::Core::Utils::Time.now.utc
|
|
203
|
+
|
|
204
|
+
super
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
module ConnectionMethods
|
|
209
|
+
def initialize(*)
|
|
210
|
+
super
|
|
211
|
+
|
|
212
|
+
@init_time = ::Datadog::Core::Utils::Time.now.utc
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def send(request)
|
|
216
|
+
request.init_time ||= @init_time
|
|
217
|
+
|
|
218
|
+
super
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
module Configuration
|
|
224
|
+
# Default settings for httpx
|
|
225
|
+
#
|
|
226
|
+
class Settings < Datadog::Tracing::Contrib::Configuration::Settings
|
|
227
|
+
DEFAULT_ERROR_HANDLER = lambda do |response|
|
|
228
|
+
Datadog::Ext::HTTP::ERROR_RANGE.cover?(response.status)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
option :service_name, default: "httpx"
|
|
232
|
+
option :distributed_tracing, default: true
|
|
233
|
+
option :split_by_domain, default: false
|
|
234
|
+
|
|
235
|
+
if Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
|
|
236
|
+
option :enabled do |o|
|
|
237
|
+
o.type :bool
|
|
238
|
+
o.env "DD_TRACE_HTTPX_ENABLED"
|
|
239
|
+
o.default true
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
option :analytics_enabled do |o|
|
|
243
|
+
o.type :bool
|
|
244
|
+
o.env "DD_TRACE_HTTPX_ANALYTICS_ENABLED"
|
|
245
|
+
o.default false
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
option :analytics_sample_rate do |o|
|
|
249
|
+
o.type :float
|
|
250
|
+
o.env "DD_TRACE_HTTPX_ANALYTICS_SAMPLE_RATE"
|
|
251
|
+
o.default 1.0
|
|
252
|
+
end
|
|
253
|
+
else
|
|
254
|
+
option :enabled do |o|
|
|
255
|
+
o.default { env_to_bool("DD_TRACE_HTTPX_ENABLED", true) }
|
|
256
|
+
o.lazy
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
option :analytics_enabled do |o|
|
|
260
|
+
o.default { env_to_bool(%w[DD_TRACE_HTTPX_ANALYTICS_ENABLED DD_HTTPX_ANALYTICS_ENABLED], false) }
|
|
261
|
+
o.lazy
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
option :analytics_sample_rate do |o|
|
|
265
|
+
o.default { env_to_float(%w[DD_TRACE_HTTPX_ANALYTICS_SAMPLE_RATE DD_HTTPX_ANALYTICS_SAMPLE_RATE], 1.0) }
|
|
266
|
+
o.lazy
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
if defined?(Datadog::Tracing::Contrib::SpanAttributeSchema)
|
|
271
|
+
option :service_name do |o|
|
|
272
|
+
o.default do
|
|
273
|
+
Datadog::Tracing::Contrib::SpanAttributeSchema.fetch_service_name(
|
|
274
|
+
"DD_TRACE_HTTPX_SERVICE_NAME",
|
|
275
|
+
"httpx"
|
|
276
|
+
)
|
|
277
|
+
end
|
|
278
|
+
o.lazy unless Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
|
|
279
|
+
end
|
|
280
|
+
else
|
|
281
|
+
option :service_name do |o|
|
|
282
|
+
o.default do
|
|
283
|
+
ENV.fetch("DD_TRACE_HTTPX_SERVICE_NAME", "httpx")
|
|
284
|
+
end
|
|
285
|
+
o.lazy unless Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
option :distributed_tracing, default: true
|
|
290
|
+
|
|
291
|
+
if Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.15.0")
|
|
292
|
+
option :error_handler do |o|
|
|
293
|
+
o.type :proc
|
|
294
|
+
o.default_proc(&DEFAULT_ERROR_HANDLER)
|
|
295
|
+
end
|
|
296
|
+
elsif Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
|
|
297
|
+
option :error_handler do |o|
|
|
298
|
+
o.type :proc
|
|
299
|
+
o.experimental_default_proc(&DEFAULT_ERROR_HANDLER)
|
|
300
|
+
end
|
|
301
|
+
else
|
|
302
|
+
option :error_handler, default: DEFAULT_ERROR_HANDLER
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Patcher enables patching of 'httpx' with datadog components.
|
|
308
|
+
#
|
|
309
|
+
module Patcher
|
|
310
|
+
include Datadog::Tracing::Contrib::Patcher
|
|
311
|
+
|
|
312
|
+
module_function
|
|
313
|
+
|
|
314
|
+
def target_version
|
|
315
|
+
Integration.version
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# loads a session instannce with the datadog plugin, and replaces the
|
|
319
|
+
# base HTTPX::Session with the patched session class.
|
|
320
|
+
def patch
|
|
321
|
+
datadog_session = ::HTTPX.plugin(Plugin)
|
|
322
|
+
|
|
323
|
+
::HTTPX.send(:remove_const, :Session)
|
|
324
|
+
::HTTPX.send(:const_set, :Session, datadog_session.class)
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# Datadog Integration for HTTPX.
|
|
329
|
+
#
|
|
330
|
+
class Integration
|
|
331
|
+
include Contrib::Integration
|
|
332
|
+
|
|
333
|
+
MINIMUM_VERSION = Gem::Version.new("0.10.2")
|
|
334
|
+
|
|
335
|
+
register_as :httpx
|
|
336
|
+
|
|
337
|
+
def self.version
|
|
338
|
+
Gem.loaded_specs["httpx"] && Gem.loaded_specs["httpx"].version
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def self.loaded?
|
|
342
|
+
defined?(::HTTPX::Request)
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def self.compatible?
|
|
346
|
+
super && version >= MINIMUM_VERSION
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def new_configuration
|
|
350
|
+
Configuration::Settings.new
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def patcher
|
|
354
|
+
Patcher
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "delegate"
|
|
4
|
+
require "httpx"
|
|
5
|
+
require "faraday"
|
|
6
|
+
|
|
7
|
+
module Faraday
|
|
8
|
+
class Adapter
|
|
9
|
+
class HTTPX < Faraday::Adapter
|
|
10
|
+
def initialize(app = nil, opts = {}, &block)
|
|
11
|
+
@connection = @bind = nil
|
|
12
|
+
super(app, opts, &block)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module RequestMixin
|
|
16
|
+
def build_connection(env)
|
|
17
|
+
return @connection if @connection
|
|
18
|
+
|
|
19
|
+
@connection = ::HTTPX.plugin(:persistent).plugin(ReasonPlugin)
|
|
20
|
+
@connection = @connection.with(@connection_options) unless @connection_options.empty?
|
|
21
|
+
connection_opts = options_from_env(env)
|
|
22
|
+
|
|
23
|
+
if (bind = env.request.bind)
|
|
24
|
+
@bind = TCPSocket.new(bind[:host], bind[:port])
|
|
25
|
+
connection_opts[:io] = @bind
|
|
26
|
+
end
|
|
27
|
+
@connection = @connection.with(connection_opts)
|
|
28
|
+
|
|
29
|
+
if (proxy = env.request.proxy)
|
|
30
|
+
proxy_options = { uri: proxy.uri }
|
|
31
|
+
proxy_options[:username] = proxy.user if proxy.user
|
|
32
|
+
proxy_options[:password] = proxy.password if proxy.password
|
|
33
|
+
|
|
34
|
+
@connection = @connection.plugin(:proxy).with(proxy: proxy_options)
|
|
35
|
+
end
|
|
36
|
+
@connection = @connection.plugin(OnDataPlugin) if env.request.stream_response?
|
|
37
|
+
|
|
38
|
+
@connection = @config_block.call(@connection) || @connection if @config_block
|
|
39
|
+
@connection
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def close
|
|
43
|
+
@connection.close if @connection
|
|
44
|
+
@bind.close if @bind
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def connect(env, &blk)
|
|
50
|
+
connection(env, &blk)
|
|
51
|
+
rescue ::HTTPX::TLSError => e
|
|
52
|
+
raise Faraday::SSLError, e
|
|
53
|
+
rescue Errno::ECONNABORTED,
|
|
54
|
+
Errno::ECONNREFUSED,
|
|
55
|
+
Errno::ECONNRESET,
|
|
56
|
+
Errno::EHOSTUNREACH,
|
|
57
|
+
Errno::EINVAL,
|
|
58
|
+
Errno::ENETUNREACH,
|
|
59
|
+
Errno::EPIPE,
|
|
60
|
+
::HTTPX::ConnectionError => e
|
|
61
|
+
raise Faraday::ConnectionFailed, e
|
|
62
|
+
rescue ::HTTPX::TimeoutError => e
|
|
63
|
+
raise Faraday::TimeoutError, e
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def build_request(env)
|
|
67
|
+
meth = env[:method]
|
|
68
|
+
|
|
69
|
+
request_options = {
|
|
70
|
+
headers: env.request_headers,
|
|
71
|
+
body: env.body,
|
|
72
|
+
**options_from_env(env),
|
|
73
|
+
}
|
|
74
|
+
[meth.to_s.upcase, env.url, request_options]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def options_from_env(env)
|
|
78
|
+
timeout_options = {}
|
|
79
|
+
req_opts = env.request
|
|
80
|
+
if (sec = request_timeout(:read, req_opts))
|
|
81
|
+
timeout_options[:read_timeout] = sec
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if (sec = request_timeout(:write, req_opts))
|
|
85
|
+
timeout_options[:write_timeout] = sec
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
if (sec = request_timeout(:open, req_opts))
|
|
89
|
+
timeout_options[:connect_timeout] = sec
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
{
|
|
93
|
+
ssl: ssl_options_from_env(env),
|
|
94
|
+
timeout: timeout_options,
|
|
95
|
+
}
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
if defined?(::OpenSSL)
|
|
99
|
+
def ssl_options_from_env(env)
|
|
100
|
+
ssl_options = {}
|
|
101
|
+
|
|
102
|
+
unless env.ssl.verify.nil?
|
|
103
|
+
ssl_options[:verify_mode] = env.ssl.verify ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
ssl_options[:ca_file] = env.ssl.ca_file if env.ssl.ca_file
|
|
107
|
+
ssl_options[:ca_path] = env.ssl.ca_path if env.ssl.ca_path
|
|
108
|
+
ssl_options[:cert_store] = env.ssl.cert_store if env.ssl.cert_store
|
|
109
|
+
ssl_options[:cert] = env.ssl.client_cert if env.ssl.client_cert
|
|
110
|
+
ssl_options[:key] = env.ssl.client_key if env.ssl.client_key
|
|
111
|
+
ssl_options[:ssl_version] = env.ssl.version if env.ssl.version
|
|
112
|
+
ssl_options[:verify_depth] = env.ssl.verify_depth if env.ssl.verify_depth
|
|
113
|
+
ssl_options[:min_version] = env.ssl.min_version if env.ssl.min_version
|
|
114
|
+
ssl_options[:max_version] = env.ssl.max_version if env.ssl.max_version
|
|
115
|
+
ssl_options
|
|
116
|
+
end
|
|
117
|
+
else
|
|
118
|
+
# :nocov:
|
|
119
|
+
def ssl_options_from_env(*)
|
|
120
|
+
{}
|
|
121
|
+
end
|
|
122
|
+
# :nocov:
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
include RequestMixin
|
|
127
|
+
|
|
128
|
+
module OnDataPlugin
|
|
129
|
+
module RequestMethods
|
|
130
|
+
attr_writer :response_on_data
|
|
131
|
+
|
|
132
|
+
def response=(response)
|
|
133
|
+
super
|
|
134
|
+
|
|
135
|
+
return unless @response
|
|
136
|
+
|
|
137
|
+
return if @response.is_a?(::HTTPX::ErrorResponse)
|
|
138
|
+
|
|
139
|
+
@response.body.on_data = @response_on_data
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
module ResponseBodyMethods
|
|
144
|
+
attr_writer :on_data
|
|
145
|
+
|
|
146
|
+
def write(chunk)
|
|
147
|
+
return super unless @on_data
|
|
148
|
+
|
|
149
|
+
@on_data.call(chunk, chunk.bytesize)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
module ReasonPlugin
|
|
155
|
+
def self.load_dependencies(*)
|
|
156
|
+
require "net/http/status"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
module ResponseMethods
|
|
160
|
+
def reason
|
|
161
|
+
Net::HTTP::STATUS_CODES.fetch(@status, "Non-Standard status code")
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
class ParallelManager
|
|
167
|
+
class ResponseHandler < SimpleDelegator
|
|
168
|
+
attr_reader :env
|
|
169
|
+
|
|
170
|
+
def initialize(env)
|
|
171
|
+
@env = env
|
|
172
|
+
super
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def on_response(&blk)
|
|
176
|
+
if blk
|
|
177
|
+
@on_response = ->(response) do
|
|
178
|
+
blk.call(response)
|
|
179
|
+
end
|
|
180
|
+
self
|
|
181
|
+
else
|
|
182
|
+
@on_response
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def on_complete(&blk)
|
|
187
|
+
if blk
|
|
188
|
+
@on_complete = blk
|
|
189
|
+
self
|
|
190
|
+
else
|
|
191
|
+
@on_complete
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
include RequestMixin
|
|
197
|
+
|
|
198
|
+
def initialize(options)
|
|
199
|
+
@handlers = []
|
|
200
|
+
@connection_options = options
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def enqueue(request)
|
|
204
|
+
handler = ResponseHandler.new(request)
|
|
205
|
+
@handlers << handler
|
|
206
|
+
handler
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def run
|
|
210
|
+
return unless @handlers.last
|
|
211
|
+
|
|
212
|
+
env = @handlers.last.env
|
|
213
|
+
|
|
214
|
+
connect(env) do |session|
|
|
215
|
+
requests = @handlers.map { |handler| session.build_request(*build_request(handler.env)) }
|
|
216
|
+
|
|
217
|
+
if env.request.stream_response?
|
|
218
|
+
requests.each do |request|
|
|
219
|
+
request.response_on_data = env.request.on_data
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
responses = session.request(*requests)
|
|
224
|
+
Array(responses).each_with_index do |response, index|
|
|
225
|
+
handler = @handlers[index]
|
|
226
|
+
handler.on_response.call(response)
|
|
227
|
+
handler.on_complete.call(handler.env) if handler.on_complete
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
private
|
|
233
|
+
|
|
234
|
+
# from Faraday::Adapter#connection
|
|
235
|
+
def connection(env)
|
|
236
|
+
conn = build_connection(env)
|
|
237
|
+
return conn unless block_given?
|
|
238
|
+
|
|
239
|
+
yield conn
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# from Faraday::Adapter#request_timeout
|
|
243
|
+
def request_timeout(type, options)
|
|
244
|
+
key = Faraday::Adapter::TIMEOUT_KEYS[type]
|
|
245
|
+
options[key] || options[:timeout]
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
self.supports_parallel = true
|
|
250
|
+
|
|
251
|
+
class << self
|
|
252
|
+
def setup_parallel_manager(options = {})
|
|
253
|
+
ParallelManager.new(options)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def call(env)
|
|
258
|
+
super
|
|
259
|
+
if parallel?(env)
|
|
260
|
+
handler = env[:parallel_manager].enqueue(env)
|
|
261
|
+
handler.on_response do |response|
|
|
262
|
+
if response.is_a?(::HTTPX::Response)
|
|
263
|
+
save_response(env, response.status, response.body.to_s, response.headers, response.reason) do |response_headers|
|
|
264
|
+
response_headers.merge!(response.headers)
|
|
265
|
+
end
|
|
266
|
+
else
|
|
267
|
+
env[:error] = response.error
|
|
268
|
+
save_response(env, 0, "", {}, nil)
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
return handler
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
response = connect_and_request(env)
|
|
275
|
+
save_response(env, response.status, response.body.to_s, response.headers, response.reason) do |response_headers|
|
|
276
|
+
response_headers.merge!(response.headers)
|
|
277
|
+
end
|
|
278
|
+
@app.call(env)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
private
|
|
282
|
+
|
|
283
|
+
def connect_and_request(env)
|
|
284
|
+
connect(env) do |session|
|
|
285
|
+
request = session.build_request(*build_request(env))
|
|
286
|
+
|
|
287
|
+
request.response_on_data = env.request.on_data if env.request.stream_response?
|
|
288
|
+
|
|
289
|
+
response = session.request(request)
|
|
290
|
+
# do not call #raise_for_status for HTTP 4xx or 5xx, as faraday has a middleware for that.
|
|
291
|
+
response.raise_for_status unless response.is_a?(::HTTPX::Response)
|
|
292
|
+
response
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def parallel?(env)
|
|
297
|
+
env[:parallel_manager]
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
register_middleware httpx: HTTPX
|
|
302
|
+
end
|
|
303
|
+
end
|