Compare commits

...

8 Commits

Author SHA1 Message Date
HoneyryderChuck
b1fc1907ab Merge branch 'issue-286' into 'master'
https resolver: try remaining candidates on domain not found

Closes #286

See merge request os85/httpx!319
2024-01-03 22:22:19 +00:00
HoneyryderChuck
c1a25d34d3 Merge branch 'pin-rubocop' into 'master'
Pin RuboCop

See merge request os85/httpx!316
2024-01-03 15:57:24 +00:00
HoneyryderChuck
5a9113e445 https resolver: try remaining candidates on domain not found
in the face of multiple dns name candidates, the https was not behaving as the native resolver on recursively trying them on receiving domain not found types of errors
2024-01-03 15:51:40 +00:00
HoneyryderChuck
cc4b8d4c9e Merge branch 'github-34' into 'master'
fix Response#content_type doc

See merge request os85/httpx!318
2024-01-03 15:10:37 +00:00
HoneyryderChuck
890d4b8d50 linting test names 2024-01-03 14:26:09 +00:00
Earlopain
76737b3b99
Pin rubocop 2024-01-03 12:36:23 +01:00
HoneyryderChuck
31ec7a2ecf doc improvements 2023-12-27 14:51:09 +00:00
HoneyryderChuck
2e32aa6707 fix Response#content_type doc
https://github.com/HoneyryderChuck/httpx/issues/34
2023-12-27 14:49:55 +00:00
10 changed files with 36 additions and 11 deletions

View File

@ -55,9 +55,9 @@ group :test do
end end
group :lint do group :lint do
gem "rubocop" gem "rubocop", "~> 1.59.0"
gem "rubocop-md" gem "rubocop-md"
gem "rubocop-performance" gem "rubocop-performance", "~> 1.19.0"
end end
group :coverage do group :coverage do

View File

@ -3,6 +3,14 @@
require "forwardable" require "forwardable"
module HTTPX module HTTPX
# Internal class to abstract a string buffer, by wrapping a string and providing the
# minimum possible API and functionality required.
#
# buffer = Buffer.new(640)
# buffer.full? #=> false
# buffer << "aa"
# buffer.capacity #=> 638
#
class Buffer class Buffer
extend Forwardable extend Forwardable

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
module HTTPX module HTTPX
# Session mixin, implements most of the APIs that the users call.
# delegates to a default session when extended.
module Chainable module Chainable
%w[head get post put delete trace options connect patch].each do |meth| %w[head get post put delete trace options connect patch].each do |meth|
class_eval(<<-MOD, __FILE__, __LINE__ + 1) class_eval(<<-MOD, __FILE__, __LINE__ + 1)
@ -10,6 +12,7 @@ module HTTPX
MOD MOD
end end
# delegates to the default session (see HTTPX::Session#request).
def request(*args, **options) def request(*args, **options)
branch(default_options).request(*args, **options) branch(default_options).request(*args, **options)
end end
@ -18,10 +21,12 @@ module HTTPX
with(headers: { "accept" => String(type) }) with(headers: { "accept" => String(type) })
end end
# delegates to the default session (see HTTPX::Session#wrap).
def wrap(&blk) def wrap(&blk)
branch(default_options).wrap(&blk) branch(default_options).wrap(&blk)
end end
# returns a new instance loaded with the +pl+ plugin and +options+.
def plugin(pl, options = nil, &blk) def plugin(pl, options = nil, &blk)
klass = is_a?(S) ? self.class : Session klass = is_a?(S) ? self.class : Session
klass = Class.new(klass) klass = Class.new(klass)
@ -29,16 +34,19 @@ module HTTPX
klass.plugin(pl, options, &blk).new klass.plugin(pl, options, &blk).new
end end
# returns a new instance loaded with +options+.
def with(options, &blk) def with(options, &blk)
branch(default_options.merge(options), &blk) branch(default_options.merge(options), &blk)
end end
private private
# returns default instance of HTTPX::Options.
def default_options def default_options
@options || Session.default_options @options || Session.default_options
end end
# returns a default instance of HTTPX::Session.
def branch(options, &blk) def branch(options, &blk)
return self.class.new(options, &blk) if is_a?(S) return self.class.new(options, &blk) if is_a?(S)

View File

@ -700,7 +700,7 @@ module HTTPX
interval = @timers.after(timeout, callback) interval = @timers.after(timeout, callback)
Array(finish_events).each do |event| Array(finish_events).each do |event|
# clean up reques timeouts if the connection errors out # clean up request timeouts if the connection errors out
request.once(event) do request.once(event) do
if @intervals.include?(interval) if @intervals.include?(interval)
interval.delete(callback) interval.delete(callback)

View File

@ -99,7 +99,7 @@ module HTTPX
# :compress_request_body :: whether to auto-decompress response body (defaults to <tt>true</tt>) # :compress_request_body :: whether to auto-decompress response body (defaults to <tt>true</tt>)
# :timeout :: hash of timeout configurations (supports <tt>:connect_timeout</tt>, <tt>:settings_timeout</tt>, # :timeout :: hash of timeout configurations (supports <tt>:connect_timeout</tt>, <tt>:settings_timeout</tt>,
# <tt>:operation_timeout</tt>, <tt>:keep_alive_timeout</tt>, <tt>:read_timeout</tt>, <tt>:write_timeout</tt> # <tt>:operation_timeout</tt>, <tt>:keep_alive_timeout</tt>, <tt>:read_timeout</tt>, <tt>:write_timeout</tt>
# and <tt>:request_timeout</tt> # and <tt>:request_timeout</tt>
# :headers :: hash of HTTP headers (ex: <tt>{ "x-custom-foo" => "bar" }</tt>) # :headers :: hash of HTTP headers (ex: <tt>{ "x-custom-foo" => "bar" }</tt>)
# :window_size :: number of bytes to read from a socket # :window_size :: number of bytes to read from a socket
# :buffer_size :: internal read and write buffer size in bytes # :buffer_size :: internal read and write buffer size in bytes

View File

@ -138,9 +138,14 @@ module HTTPX
# Indicates no such domain was found. # Indicates no such domain was found.
host = @requests.delete(request) host = @requests.delete(request)
connection = reset_hostname(host) connection = reset_hostname(host, reset_candidates: false)
emit_resolve_error(connection) unless @queries.value?(connection)
emit_resolve_error(connection)
return
end
resolve
when :dns_error when :dns_error
host = @requests.delete(request) host = @requests.delete(request)
connection = reset_hostname(host) connection = reset_hostname(host)

View File

@ -70,9 +70,10 @@ module HTTPX
@body.write(data) @body.write(data)
end end
# returns the response mime type, as per what's declared in the content-type header. # returns the HTTPX::ContentType for the response, as per what's declared in the content-type header.
# #
# response.content_type #=> "text/plain" # response.content_type #=> #<HTTPX::ContentType:xxx @header_value="text/plain">
# response.content_type.mime_type #=> "text/plain"
def content_type def content_type
@content_type ||= ContentType.new(@headers["content-type"]) @content_type ||= ContentType.new(@headers["content-type"])
end end

View File

@ -166,6 +166,7 @@ module HTTPX
private private
# prepares inflaters for the advertised encodings in "content-encoding" header.
def initialize_inflaters def initialize_inflaters
@inflaters = nil @inflaters = nil
@ -187,6 +188,7 @@ module HTTPX
end end
end end
# passes the +chunk+ through all inflaters to decode it.
def decode_chunk(chunk) def decode_chunk(chunk)
@inflaters.reverse_each do |inflater| @inflaters.reverse_each do |inflater|
chunk = inflater.call(chunk) chunk = inflater.call(chunk)
@ -195,6 +197,7 @@ module HTTPX
chunk chunk
end end
# tries transitioning the body STM to the +nextstate+.
def transition(nextstate) def transition(nextstate)
case nextstate case nextstate
when :open when :open

View File

@ -39,7 +39,7 @@ class HTTP1ParserTest < Minitest::Test
JSON.parse(File.read(File.expand_path("support/responses.json", __dir__))).each do |res_json| JSON.parse(File.read(File.expand_path("support/responses.json", __dir__))).each do |res_json|
res_json["headers"] ||= {} res_json["headers"] ||= {}
define_method "test_parse_response_#{res_json["name"]}" do define_method :"test_parse_response_#{res_json["name"]}" do
observer = RequestObserver.new observer = RequestObserver.new
parser = observer.parser parser = observer.parser
begin begin

View File

@ -45,7 +45,7 @@ module Requests
end end
%w[SHA1 SHA2 SHA256 SHA384 SHA512 RMD160].each do |alg| %w[SHA1 SHA2 SHA256 SHA384 SHA512 RMD160].each do |alg|
define_method "test_plugin_digest_auth_#{alg}" do define_method :"test_plugin_digest_auth_#{alg}" do
session = HTTPX.plugin(:digest_auth).with_headers("cookie" => "fake=fake_value") session = HTTPX.plugin(:digest_auth).with_headers("cookie" => "fake=fake_value")
response = session.digest_auth(user, pass).get("#{digest_auth_uri}/#{alg}") response = session.digest_auth(user, pass).get("#{digest_auth_uri}/#{alg}")
verify_status(response, 200) verify_status(response, 200)
@ -56,7 +56,7 @@ module Requests
end end
%w[MD5 SHA1].each do |alg| %w[MD5 SHA1].each do |alg|
define_method "test_plugin_digest_auth_#{alg}_sess" do define_method :"test_plugin_digest_auth_#{alg}_sess" do
start_test_servlet(DigestServer, algorithm: "#{alg}-sess") do |server| start_test_servlet(DigestServer, algorithm: "#{alg}-sess") do |server|
uri = "#{server.origin}/" uri = "#{server.origin}/"
session = HTTPX.plugin(:digest_auth).with_headers("cookie" => "fake=fake_value") session = HTTPX.plugin(:digest_auth).with_headers("cookie" => "fake=fake_value")