mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-07-15 00:00:55 -04:00
Compare commits
11 Commits
3bcf5bd5f6
...
8652d1978f
Author | SHA1 | Date | |
---|---|---|---|
|
8652d1978f | ||
|
5532d8eb73 | ||
|
ea61cce815 | ||
|
64903fca4e | ||
|
b07117e16e | ||
|
487cac6eef | ||
|
499a87a8f1 | ||
|
f744ae651b | ||
|
1b0327261f | ||
|
707e653883 | ||
|
73f0d609b0 |
@ -43,16 +43,6 @@ test jruby:
|
|||||||
script:
|
script:
|
||||||
./spec.sh jruby 9.0.0.0
|
./spec.sh jruby 9.0.0.0
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
test ruby 2/1:
|
|
||||||
<<: *test_settings
|
|
||||||
script:
|
|
||||||
./spec.sh ruby 2.1
|
|
||||||
test ruby 2/2:
|
|
||||||
<<: *test_settings
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
script:
|
|
||||||
./spec.sh ruby 2.2
|
|
||||||
test ruby 2/3:
|
test ruby 2/3:
|
||||||
<<: *test_settings
|
<<: *test_settings
|
||||||
script:
|
script:
|
||||||
|
6
doc/release_notes/0_22_5.md
Normal file
6
doc/release_notes/0_22_5.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# 0.22.5
|
||||||
|
|
||||||
|
## Bugfixes
|
||||||
|
|
||||||
|
* `datadog` and `sentry` integrations did not account for `Connection#send` being possibly called multiple times (something possible for connection coalescing, max requests exhaustion, or Happy Eyeballs 2), and were registering multiple `on(:response)` callbacks. Requests are now marked when decorated the first time.
|
||||||
|
* Happy Eyeballs handshake "connect errors" routine is now taking both name resolution errors, as well as TLS handshake errors, into account, when the handshake fails.
|
20
examples/happy_eyeballs.rb
Normal file
20
examples/happy_eyeballs.rb
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#
|
||||||
|
# From https://ipv6friday.org/blog/2012/11/happy-testing/
|
||||||
|
#
|
||||||
|
# The http server accessible via the test doamins is returning empty responses.
|
||||||
|
# If you want to verify that the correct IP family is being used to establish the connection,
|
||||||
|
# set HTTPX_DEBUG=2
|
||||||
|
#
|
||||||
|
require "httpx"
|
||||||
|
|
||||||
|
URLS = %w[http://badipv4.test.ipv6friday.org/] * 1
|
||||||
|
# URLS = %w[http://badipv6.test.ipv6friday.org/] * 1
|
||||||
|
|
||||||
|
responses = HTTPX.get(*URLS, ssl: { verify_mode: OpenSSL::SSL::VERIFY_NONE})
|
||||||
|
|
||||||
|
# responses = HTTPX.get(*URLS)
|
||||||
|
Array(responses).each(&:raise_for_status)
|
||||||
|
puts "Status: \n"
|
||||||
|
puts Array(responses).map(&:status)
|
||||||
|
puts "Payload: \n"
|
||||||
|
puts Array(responses).map(&:to_s)
|
@ -198,14 +198,14 @@ class DatadogTest < Minitest::Test
|
|||||||
assert span.get_tag("http.method") == verb
|
assert span.get_tag("http.method") == verb
|
||||||
assert span.get_tag("http.url") == uri.path
|
assert span.get_tag("http.url") == uri.path
|
||||||
|
|
||||||
error_tag = if defined?(::DDTrace) && ::DDTrace::VERSION::STRING >= "1.8.0"
|
error_tag = if defined?(::DDTrace) && Gem::Version.new(::DDTrace::VERSION::STRING) >= Gem::Version.new("1.8.0")
|
||||||
"error.message"
|
"error.message"
|
||||||
else
|
else
|
||||||
"error.msg"
|
"error.msg"
|
||||||
end
|
end
|
||||||
|
|
||||||
if error
|
if error
|
||||||
assert span.get_tag("error.type") == error
|
assert span.get_tag("error.type") == "HTTPX::NativeResolveError"
|
||||||
assert !span.get_tag(error_tag).nil?
|
assert !span.get_tag(error_tag).nil?
|
||||||
assert span.status == 1
|
assert span.status == 1
|
||||||
elsif response.status >= 400
|
elsif response.status >= 400
|
||||||
@ -241,7 +241,7 @@ class DatadogTest < Minitest::Test
|
|||||||
assert span.get_metric("_dd1.sr.eausr") == sample_rate
|
assert span.get_metric("_dd1.sr.eausr") == sample_rate
|
||||||
end
|
end
|
||||||
|
|
||||||
if defined?(::DDTrace) && ::DDTrace::VERSION::STRING >= "1.0.0"
|
if defined?(::DDTrace) && Gem::Version.new(::DDTrace::VERSION::STRING) >= Gem::Version.new("1.0.0")
|
||||||
|
|
||||||
def set_datadog(options = {}, &blk)
|
def set_datadog(options = {}, &blk)
|
||||||
Datadog.configure do |c|
|
Datadog.configure do |c|
|
||||||
@ -305,7 +305,7 @@ class DatadogTest < Minitest::Test
|
|||||||
# Retrieves and sorts all spans in the current tracer instance.
|
# Retrieves and sorts all spans in the current tracer instance.
|
||||||
# This method does not cache its results.
|
# This method does not cache its results.
|
||||||
def fetch_spans
|
def fetch_spans
|
||||||
spans = if defined?(::DDTrace) && ::DDTrace::VERSION::STRING >= "1.0.0"
|
spans = if defined?(::DDTrace) && Gem::Version.new(::DDTrace::VERSION::STRING) >= Gem::Version.new("1.0.0")
|
||||||
(tracer.instance_variable_get(:@traces) || []).map(&:spans)
|
(tracer.instance_variable_get(:@traces) || []).map(&:spans)
|
||||||
else
|
else
|
||||||
tracer.instance_variable_get(:@spans) || []
|
tracer.instance_variable_get(:@spans) || []
|
||||||
|
@ -158,9 +158,19 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module RequestMethods
|
||||||
|
def __datadog_enable_trace!
|
||||||
|
return super if @__datadog_enable_trace
|
||||||
|
|
||||||
|
RequestTracer.new(self).call
|
||||||
|
@__datadog_enable_trace = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
module ConnectionMethods
|
module ConnectionMethods
|
||||||
def send(request)
|
def send(request)
|
||||||
RequestTracer.new(request).call
|
request.__datadog_enable_trace!
|
||||||
|
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -89,9 +89,19 @@ module HTTPX::Plugins
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module RequestMethods
|
||||||
|
def __sentry_enable_trace!
|
||||||
|
return super if @__sentry_enable_trace
|
||||||
|
|
||||||
|
Tracer.call(self)
|
||||||
|
@__sentry_enable_trace = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
module ConnectionMethods
|
module ConnectionMethods
|
||||||
def send(request)
|
def send(request)
|
||||||
Tracer.call(request)
|
request.__sentry_enable_trace!
|
||||||
|
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -22,12 +22,12 @@ module HTTPX
|
|||||||
callbacks(type).delete_if { |pr| :delete == pr.call(*args) } # rubocop:disable Style/YodaCondition
|
callbacks(type).delete_if { |pr| :delete == pr.call(*args) } # rubocop:disable Style/YodaCondition
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def callbacks_for?(type)
|
def callbacks_for?(type)
|
||||||
@callbacks.key?(type) && !@callbacks[type].empty?
|
@callbacks.key?(type) && @callbacks[type].any?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
def callbacks(type = nil)
|
def callbacks(type = nil)
|
||||||
return @callbacks unless type
|
return @callbacks unless type
|
||||||
|
|
||||||
|
@ -538,12 +538,13 @@ module HTTPX
|
|||||||
# connect errors, exit gracefully
|
# connect errors, exit gracefully
|
||||||
error = ConnectionError.new(e.message)
|
error = ConnectionError.new(e.message)
|
||||||
error.set_backtrace(e.backtrace)
|
error.set_backtrace(e.backtrace)
|
||||||
connecting? && callbacks(:connect_error).any? ? emit(:connect_error, error) : handle_error(error)
|
connecting? && callbacks_for?(:connect_error) ? emit(:connect_error, error) : handle_error(error)
|
||||||
@state = :closed
|
@state = :closed
|
||||||
emit(:close)
|
emit(:close)
|
||||||
rescue TLSError => e
|
rescue TLSError => e
|
||||||
# connect errors, exit gracefully
|
# connect errors, exit gracefully
|
||||||
handle_error(e)
|
handle_error(e)
|
||||||
|
connecting? && callbacks_for?(:connect_error) ? emit(:connect_error, e) : handle_error(e)
|
||||||
@state = :closed
|
@state = :closed
|
||||||
emit(:close)
|
emit(:close)
|
||||||
end
|
end
|
||||||
|
@ -141,8 +141,9 @@ module HTTPX
|
|||||||
connection.once(:connect_error) do |err|
|
connection.once(:connect_error) do |err|
|
||||||
if new_connection.connecting?
|
if new_connection.connecting?
|
||||||
new_connection.merge(connection)
|
new_connection.merge(connection)
|
||||||
|
connection.force_reset
|
||||||
else
|
else
|
||||||
connection.handle_error(err)
|
connection.__send__(:handle_error, err)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -156,8 +157,9 @@ module HTTPX
|
|||||||
if connection.connecting?
|
if connection.connecting?
|
||||||
# main connection has the requests
|
# main connection has the requests
|
||||||
connection.merge(new_connection)
|
connection.merge(new_connection)
|
||||||
|
new_connection.force_reset
|
||||||
else
|
else
|
||||||
new_connection.handle_error(err)
|
new_connection.__send__(:handle_error, err)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -183,6 +185,8 @@ module HTTPX
|
|||||||
end
|
end
|
||||||
|
|
||||||
def on_resolver_error(connection, error)
|
def on_resolver_error(connection, error)
|
||||||
|
return connection.emit(:connect_error, error) if connection.connecting? && connection.callbacks_for?(:connect_error)
|
||||||
|
|
||||||
connection.emit(:error, error)
|
connection.emit(:error, error)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -64,12 +64,7 @@ module HTTPX
|
|||||||
end
|
end
|
||||||
|
|
||||||
def on_resolver_error(connection, error)
|
def on_resolver_error(connection, error)
|
||||||
@errors[connection] << error
|
emit(:error, connection, error)
|
||||||
|
|
||||||
return unless @errors[connection].size >= @resolvers.size
|
|
||||||
|
|
||||||
errors = @errors.delete(connection)
|
|
||||||
emit(:error, connection, errors.first)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_resolver_close(resolver)
|
def on_resolver_close(resolver)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module HTTPX
|
module HTTPX
|
||||||
VERSION = "0.22.4"
|
VERSION = "0.22.5"
|
||||||
end
|
end
|
||||||
|
@ -5,6 +5,8 @@ set -e
|
|||||||
export LANG=C.UTF-8
|
export LANG=C.UTF-8
|
||||||
export LANGUAGE=C.UTF-8
|
export LANGUAGE=C.UTF-8
|
||||||
|
|
||||||
|
ruby --version
|
||||||
|
|
||||||
RUBY_PLATFORM=`ruby -e 'puts RUBY_PLATFORM'`
|
RUBY_PLATFORM=`ruby -e 'puts RUBY_PLATFORM'`
|
||||||
RUBY_ENGINE=`ruby -e 'puts RUBY_ENGINE'`
|
RUBY_ENGINE=`ruby -e 'puts RUBY_ENGINE'`
|
||||||
IPTABLES=iptables-translate
|
IPTABLES=iptables-translate
|
||||||
@ -13,12 +15,6 @@ if [[ "$RUBY_ENGINE" = "truffleruby" ]]; then
|
|||||||
dnf install -y iptables iproute which file idn2 git xz
|
dnf install -y iptables iproute which file idn2 git xz
|
||||||
elif [[ "$RUBY_PLATFORM" = "java" ]]; then
|
elif [[ "$RUBY_PLATFORM" = "java" ]]; then
|
||||||
apt-get update && apt-get install -y build-essential iptables iproute2 file idn2 git
|
apt-get update && apt-get install -y build-essential iptables iproute2 file idn2 git
|
||||||
elif [[ ${RUBY_VERSION:0:3} = "2.1" ]]; then
|
|
||||||
apt-get update && apt-get install -y --force-yes libsodium-dev iptables iproute2 libmagic-dev shared-mime-info
|
|
||||||
IPTABLES=iptables
|
|
||||||
elif [[ ${RUBY_VERSION:0:3} = "2.2" ]]; then
|
|
||||||
apt-get update && apt-get install -y --force-yes iptables iproute2 libmagic-dev shared-mime-info
|
|
||||||
IPTABLES=iptables
|
|
||||||
elif [[ ${RUBY_VERSION:0:3} = "2.3" ]]; then
|
elif [[ ${RUBY_VERSION:0:3} = "2.3" ]]; then
|
||||||
# installing custom openssl
|
# installing custom openssl
|
||||||
apt-get update && apt-get install -y iptables iproute2 iptables-nftables-compat libmagic-dev shared-mime-info # openssl=1.0.2l openssl-dev=1.0.2l
|
apt-get update && apt-get install -y iptables iproute2 iptables-nftables-compat libmagic-dev shared-mime-info # openssl=1.0.2l openssl-dev=1.0.2l
|
||||||
|
Loading…
x
Reference in New Issue
Block a user