httpx 1.2.3 → 1.2.5
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/doc/release_notes/1_2_4.md +8 -0
- data/doc/release_notes/1_2_5.md +7 -0
- data/lib/httpx/adapters/datadog.rb +140 -45
- data/lib/httpx/altsvc.rb +2 -2
- data/lib/httpx/connection/http1.rb +1 -1
- data/lib/httpx/connection.rb +3 -3
- data/lib/httpx/plugins/auth/digest.rb +2 -1
- data/lib/httpx/plugins/aws_sigv4.rb +2 -2
- data/lib/httpx/plugins/response_cache.rb +4 -1
- data/lib/httpx/plugins/stream.rb +10 -1
- data/lib/httpx/response.rb +5 -0
- data/lib/httpx/version.rb +1 -1
- data/sig/response.rbs +1 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e80b08847467e6ba67e57afef2787c2c617167624ae510e255dd23998b25210e
|
4
|
+
data.tar.gz: b11ea8d914872689bc1710680c9962b0362c3bf28b62f6e7209f7e2a54a34674
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fc7994fd3b460e267bce129fdcf6536d844fd5dd9695833c4075028cf128fe954c599ee96eacdf722756c6615c703c96f2df44628e34cd1964fee9f3f92e5e9
|
7
|
+
data.tar.gz: 04c4ad1bcf05a3ee96de206a05c294f29f90fa0698fb094b982027cb09db8969a99bd7a324af23dcec18d227fe9708947211fc31ae9e4cddfb4b4360df94aa99
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# 1.2.4
|
2
|
+
|
3
|
+
## Bugfixes
|
4
|
+
|
5
|
+
* fixed issue related to inability to buffer payload to error responses (which may happen on certain error handling situations).
|
6
|
+
* fixed recovery from a lost persistent connection leaving process due to ping being sent while still marked as inactive.
|
7
|
+
* fixed datadog integration, which was not generating new spans on retried requests (when `:retries` plugin is enabled).
|
8
|
+
* fixed splitting strings into key value pairs in cases where the value would contain a "=", such as in certain base64 payloads.
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# 1.2.5
|
2
|
+
|
3
|
+
## Bugfixes
|
4
|
+
|
5
|
+
* fix for usage of correct `last-modified` header in `response_cache` plugin.
|
6
|
+
* fix usage of decoding helper methods (i.e. `response.json`) with `response_cache` plugin.
|
7
|
+
* `stream` plugin: reverted back to yielding buffered payloads for streamed responses (broke `down` integration)
|
@@ -7,6 +7,8 @@ require "datadog/tracing/contrib/patcher"
|
|
7
7
|
module Datadog::Tracing
|
8
8
|
module Contrib
|
9
9
|
module HTTPX
|
10
|
+
DATADOG_VERSION = defined?(::DDTrace) ? ::DDTrace::VERSION : ::Datadog::VERSION
|
11
|
+
|
10
12
|
METADATA_MODULE = Datadog::Tracing::Metadata
|
11
13
|
|
12
14
|
TYPE_OUTBOUND = Datadog::Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
|
@@ -22,9 +24,10 @@ module Datadog::Tracing
|
|
22
24
|
|
23
25
|
# HTTPX Datadog Plugin
|
24
26
|
#
|
25
|
-
# Enables tracing for httpx requests.
|
26
|
-
#
|
27
|
-
#
|
27
|
+
# Enables tracing for httpx requests.
|
28
|
+
#
|
29
|
+
# A span will be created for each request transaction; the span is created lazily only when
|
30
|
+
# receiving a response, and it is fed the start time stored inside the tracer object.
|
28
31
|
#
|
29
32
|
module Plugin
|
30
33
|
class RequestTracer
|
@@ -32,82 +35,174 @@ module Datadog::Tracing
|
|
32
35
|
|
33
36
|
SPAN_REQUEST = "httpx.request"
|
34
37
|
|
38
|
+
# initializes the tracer object on the +request+.
|
35
39
|
def initialize(request)
|
36
40
|
@request = request
|
41
|
+
@start_time = nil
|
42
|
+
|
43
|
+
# request objects are reused, when already buffered requests get rerouted to a different
|
44
|
+
# connection due to connection issues, or when they already got a response, but need to
|
45
|
+
# be retried. In such situations, the original span needs to be extended for the former,
|
46
|
+
# while a new is required for the latter.
|
47
|
+
request.on(:idle) { reset }
|
48
|
+
# the span is initialized when the request is buffered in the parser, which is the closest
|
49
|
+
# one gets to actually sending the request.
|
50
|
+
request.on(:headers) { call }
|
37
51
|
end
|
38
52
|
|
39
|
-
|
40
|
-
|
53
|
+
# sets up the span start time, while preparing the on response callback.
|
54
|
+
def call(*args)
|
55
|
+
return if @start_time
|
56
|
+
|
57
|
+
start(*args)
|
58
|
+
|
59
|
+
@request.once(:response, &method(:finish))
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# just sets the span init time. It can be passed a +start_time+ in cases where
|
65
|
+
# this is collected outside the request transaction.
|
66
|
+
def start(start_time = now)
|
67
|
+
@start_time = start_time
|
68
|
+
end
|
69
|
+
|
70
|
+
# resets the start time for already finished request transactions.
|
71
|
+
def reset
|
72
|
+
return unless @start_time
|
73
|
+
|
74
|
+
start
|
75
|
+
end
|
41
76
|
|
42
|
-
|
77
|
+
# creates the span from the collected +@start_time+ to what the +response+ state
|
78
|
+
# contains. It also resets internal state to allow this object to be reused.
|
79
|
+
def finish(response)
|
80
|
+
return unless @start_time
|
81
|
+
|
82
|
+
span = initialize_span
|
43
83
|
|
84
|
+
return unless span
|
85
|
+
|
86
|
+
if response.is_a?(::HTTPX::ErrorResponse)
|
87
|
+
span.set_error(response.error)
|
88
|
+
else
|
89
|
+
span.set_tag(TAG_STATUS_CODE, response.status.to_s)
|
90
|
+
|
91
|
+
span.set_error(::HTTPX::HTTPError.new(response)) if response.status >= 400 && response.status <= 599
|
92
|
+
end
|
93
|
+
|
94
|
+
span.finish
|
95
|
+
ensure
|
96
|
+
@start_time = nil
|
97
|
+
end
|
98
|
+
|
99
|
+
# return a span initialized with the +@request+ state.
|
100
|
+
def initialize_span
|
44
101
|
verb = @request.verb
|
45
102
|
uri = @request.uri
|
46
103
|
|
47
|
-
|
48
|
-
SPAN_REQUEST,
|
49
|
-
service: service_name(@request.uri.host, configuration, Datadog.configuration_for(self)),
|
50
|
-
span_type: TYPE_OUTBOUND
|
51
|
-
)
|
104
|
+
span = create_span(@request)
|
52
105
|
|
53
|
-
|
106
|
+
span.resource = verb
|
54
107
|
|
55
108
|
# Add additional request specific tags to the span.
|
56
109
|
|
57
|
-
|
58
|
-
|
110
|
+
span.set_tag(TAG_URL, @request.path)
|
111
|
+
span.set_tag(TAG_METHOD, verb)
|
59
112
|
|
60
|
-
|
61
|
-
|
113
|
+
span.set_tag(TAG_TARGET_HOST, uri.host)
|
114
|
+
span.set_tag(TAG_TARGET_PORT, uri.port.to_s)
|
62
115
|
|
63
116
|
# Tag as an external peer service
|
64
|
-
|
117
|
+
span.set_tag(TAG_PEER_SERVICE, span.service)
|
65
118
|
|
66
|
-
|
67
|
-
|
119
|
+
if configuration[:distributed_tracing]
|
120
|
+
propagate_trace_http(
|
121
|
+
Datadog::Tracing.active_trace.to_digest,
|
122
|
+
@request.headers
|
123
|
+
)
|
124
|
+
end
|
68
125
|
|
69
126
|
# Set analytics sample rate
|
70
|
-
if Contrib::Analytics.enabled?(
|
71
|
-
Contrib::Analytics.set_sample_rate(
|
127
|
+
if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
|
128
|
+
Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
|
72
129
|
end
|
130
|
+
|
131
|
+
span
|
73
132
|
rescue StandardError => e
|
74
133
|
Datadog.logger.error("error preparing span for http request: #{e}")
|
75
134
|
Datadog.logger.error(e.backtrace)
|
76
135
|
end
|
77
136
|
|
78
|
-
def
|
79
|
-
|
137
|
+
def now
|
138
|
+
::Datadog::Core::Utils::Time.now.utc
|
139
|
+
end
|
80
140
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
@span.set_tag(TAG_STATUS_CODE, response.status.to_s)
|
141
|
+
def configuration
|
142
|
+
@configuration ||= Datadog.configuration.tracing[:httpx, @request.uri.host]
|
143
|
+
end
|
85
144
|
|
86
|
-
|
145
|
+
if Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("2.0.0.beta1")
|
146
|
+
def propagate_trace_http(digest, headers)
|
147
|
+
Datadog::Tracing::Contrib::HTTP.inject(digest, headers)
|
87
148
|
end
|
88
149
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
150
|
+
def create_span(request)
|
151
|
+
Datadog::Tracing.trace(
|
152
|
+
SPAN_REQUEST,
|
153
|
+
service: service_name(request.uri.host, configuration, Datadog.configuration_for(self)),
|
154
|
+
type: TYPE_OUTBOUND,
|
155
|
+
start_time: @start_time
|
156
|
+
)
|
157
|
+
end
|
158
|
+
else
|
159
|
+
def propagate_trace_http(digest, headers)
|
160
|
+
Datadog::Tracing::Propagation::HTTP.inject!(digest, headers)
|
161
|
+
end
|
93
162
|
|
94
|
-
|
95
|
-
|
163
|
+
def create_span(request)
|
164
|
+
Datadog::Tracing.trace(
|
165
|
+
SPAN_REQUEST,
|
166
|
+
service: service_name(request.uri.host, configuration, Datadog.configuration_for(self)),
|
167
|
+
span_type: TYPE_OUTBOUND,
|
168
|
+
start_time: @start_time
|
169
|
+
)
|
170
|
+
end
|
96
171
|
end
|
97
172
|
end
|
98
173
|
|
99
174
|
module RequestMethods
|
100
|
-
|
101
|
-
|
175
|
+
# intercepts request initialization to inject the tracing logic.
|
176
|
+
def initialize(*)
|
177
|
+
super
|
102
178
|
|
103
|
-
|
104
|
-
|
179
|
+
return unless Datadog::Tracing.enabled?
|
180
|
+
|
181
|
+
RequestTracer.new(self)
|
105
182
|
end
|
106
183
|
end
|
107
184
|
|
108
185
|
module ConnectionMethods
|
109
|
-
|
110
|
-
|
186
|
+
attr_reader :init_time
|
187
|
+
|
188
|
+
def initialize(*)
|
189
|
+
super
|
190
|
+
|
191
|
+
@init_time = ::Datadog::Core::Utils::Time.now.utc
|
192
|
+
end
|
193
|
+
|
194
|
+
# handles the case when the +error+ happened during name resolution, which meanns
|
195
|
+
# that the tracing logic hasn't been injected yet; in such cases, the approximate
|
196
|
+
# initial resolving time is collected from the connection, and used as span start time,
|
197
|
+
# and the tracing object in inserted before the on response callback is called.
|
198
|
+
def handle_error(error)
|
199
|
+
return super unless Datadog::Tracing.enabled?
|
200
|
+
|
201
|
+
return super unless error.respond_to?(:connection)
|
202
|
+
|
203
|
+
@pending.each do |request|
|
204
|
+
RequestTracer.new(request).call(error.connection.init_time)
|
205
|
+
end
|
111
206
|
|
112
207
|
super
|
113
208
|
end
|
@@ -126,7 +221,7 @@ module Datadog::Tracing
|
|
126
221
|
option :distributed_tracing, default: true
|
127
222
|
option :split_by_domain, default: false
|
128
223
|
|
129
|
-
if Gem::Version.new(
|
224
|
+
if Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
|
130
225
|
option :enabled do |o|
|
131
226
|
o.type :bool
|
132
227
|
o.env "DD_TRACE_HTTPX_ENABLED"
|
@@ -169,25 +264,25 @@ module Datadog::Tracing
|
|
169
264
|
"httpx"
|
170
265
|
)
|
171
266
|
end
|
172
|
-
o.lazy unless Gem::Version.new(
|
267
|
+
o.lazy unless Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
|
173
268
|
end
|
174
269
|
else
|
175
270
|
option :service_name do |o|
|
176
271
|
o.default do
|
177
272
|
ENV.fetch("DD_TRACE_HTTPX_SERVICE_NAME", "httpx")
|
178
273
|
end
|
179
|
-
o.lazy unless Gem::Version.new(
|
274
|
+
o.lazy unless Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
|
180
275
|
end
|
181
276
|
end
|
182
277
|
|
183
278
|
option :distributed_tracing, default: true
|
184
279
|
|
185
|
-
if Gem::Version.new(
|
280
|
+
if Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.15.0")
|
186
281
|
option :error_handler do |o|
|
187
282
|
o.type :proc
|
188
283
|
o.default_proc(&DEFAULT_ERROR_HANDLER)
|
189
284
|
end
|
190
|
-
elsif Gem::Version.new(
|
285
|
+
elsif Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
|
191
286
|
option :error_handler do |o|
|
192
287
|
o.type :proc
|
193
288
|
o.experimental_default_proc(&DEFAULT_ERROR_HANDLER)
|
data/lib/httpx/altsvc.rb
CHANGED
@@ -131,9 +131,9 @@ module HTTPX
|
|
131
131
|
scanner.skip(/;/)
|
132
132
|
break if scanner.eos? || scanner.scan(/ *, */)
|
133
133
|
end
|
134
|
-
alt_params = Hash[alt_params.map { |field| field.split("=") }]
|
134
|
+
alt_params = Hash[alt_params.map { |field| field.split("=", 2) }]
|
135
135
|
|
136
|
-
alt_proto, alt_authority = alt_service.split("=")
|
136
|
+
alt_proto, alt_authority = alt_service.split("=", 2)
|
137
137
|
alt_origin = parse_altsvc_origin(alt_proto, alt_authority)
|
138
138
|
return unless alt_origin
|
139
139
|
|
data/lib/httpx/connection.rb
CHANGED
@@ -48,10 +48,10 @@ module HTTPX
|
|
48
48
|
attr_accessor :family
|
49
49
|
|
50
50
|
def initialize(uri, options)
|
51
|
-
@origins = [uri.origin]
|
52
|
-
@origin = Utils.to_uri(uri.origin)
|
53
51
|
@options = Options.new(options)
|
54
52
|
@type = initialize_type(uri, @options)
|
53
|
+
@origins = [uri.origin]
|
54
|
+
@origin = Utils.to_uri(uri.origin)
|
55
55
|
@window_size = @options.window_size
|
56
56
|
@read_buffer = Buffer.new(@options.buffer_size)
|
57
57
|
@write_buffer = Buffer.new(@options.buffer_size)
|
@@ -241,8 +241,8 @@ module HTTPX
|
|
241
241
|
# for such cases, we want to ping for availability before deciding to shovel requests.
|
242
242
|
log(level: 3) { "keep alive timeout expired, pinging connection..." }
|
243
243
|
@pending << request
|
244
|
-
parser.ping
|
245
244
|
transition(:active) if @state == :inactive
|
245
|
+
parser.ping
|
246
246
|
return
|
247
247
|
end
|
248
248
|
|
@@ -30,7 +30,8 @@ module HTTPX
|
|
30
30
|
auth_info = authenticate[/^(\w+) (.*)/, 2]
|
31
31
|
|
32
32
|
params = auth_info.split(/ *, */)
|
33
|
-
.to_h { |val| val.split("="
|
33
|
+
.to_h { |val| val.split("=", 2) }
|
34
|
+
.transform_values { |v| v.delete("\"") }
|
34
35
|
nonce = params["nonce"]
|
35
36
|
nc = next_nonce
|
36
37
|
|
@@ -197,8 +197,8 @@ module HTTPX
|
|
197
197
|
params.each.with_index.sort do |a, b|
|
198
198
|
a, a_offset = a
|
199
199
|
b, b_offset = b
|
200
|
-
a_name, a_value = a.split("=")
|
201
|
-
b_name, b_value = b.split("=")
|
200
|
+
a_name, a_value = a.split("=", 2)
|
201
|
+
b_name, b_value = b.split("=", 2)
|
202
202
|
if a_name == b_name
|
203
203
|
if a_value == b_value
|
204
204
|
a_offset <=> b_offset
|
@@ -40,7 +40,7 @@ module HTTPX
|
|
40
40
|
# the Range and Content-Range headers MUST NOT cache 206 (Partial
|
41
41
|
# Content) responses.
|
42
42
|
response.status != 206 && (
|
43
|
-
response.headers.key?("etag") || response.headers.key?("last-modified
|
43
|
+
response.headers.key?("etag") || response.headers.key?("last-modified") || response.fresh?
|
44
44
|
)
|
45
45
|
end
|
46
46
|
|
@@ -102,6 +102,9 @@ module HTTPX
|
|
102
102
|
|
103
103
|
module ResponseMethods
|
104
104
|
def copy_from_cached(other)
|
105
|
+
# 304 responses do not have content-type, which are needed for decoding.
|
106
|
+
@headers = @headers.class.new(other.headers.merge(@headers))
|
107
|
+
|
105
108
|
@body = other.body.dup
|
106
109
|
|
107
110
|
@body.rewind
|
data/lib/httpx/plugins/stream.rb
CHANGED
@@ -16,9 +16,18 @@ module HTTPX
|
|
16
16
|
begin
|
17
17
|
@on_chunk = block
|
18
18
|
|
19
|
+
if @request.response
|
20
|
+
# if we've already started collecting the payload, yield it first
|
21
|
+
# before proceeding.
|
22
|
+
body = @request.response.body
|
23
|
+
|
24
|
+
body.each do |chunk|
|
25
|
+
on_chunk(chunk)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
19
29
|
response.raise_for_status
|
20
30
|
ensure
|
21
|
-
response.close if @response
|
22
31
|
@on_chunk = nil
|
23
32
|
end
|
24
33
|
end
|
data/lib/httpx/response.rb
CHANGED
data/lib/httpx/version.rb
CHANGED
data/sig/response.rbs
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: httpx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tiago Cardoso
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http-2-next
|
@@ -141,6 +141,8 @@ extra_rdoc_files:
|
|
141
141
|
- doc/release_notes/1_2_1.md
|
142
142
|
- doc/release_notes/1_2_2.md
|
143
143
|
- doc/release_notes/1_2_3.md
|
144
|
+
- doc/release_notes/1_2_4.md
|
145
|
+
- doc/release_notes/1_2_5.md
|
144
146
|
files:
|
145
147
|
- LICENSE.txt
|
146
148
|
- README.md
|
@@ -253,6 +255,8 @@ files:
|
|
253
255
|
- doc/release_notes/1_2_1.md
|
254
256
|
- doc/release_notes/1_2_2.md
|
255
257
|
- doc/release_notes/1_2_3.md
|
258
|
+
- doc/release_notes/1_2_4.md
|
259
|
+
- doc/release_notes/1_2_5.md
|
256
260
|
- lib/httpx.rb
|
257
261
|
- lib/httpx/adapters/datadog.rb
|
258
262
|
- lib/httpx/adapters/faraday.rb
|