Compare commits

..

No commits in common. "709101cf0ff6f047e54e95c330e30ac3cb962625" and "45c8dcb36b0332a26cbcc82072772db6761083d6" have entirely different histories.

18 changed files with 31 additions and 225 deletions

View File

@ -118,9 +118,6 @@ Style/HashSyntax:
Style/AndOr: Style/AndOr:
Enabled: False Enabled: False
Style/ArgumentsForwarding:
Enabled: False
Naming/MethodParameterName: Naming/MethodParameterName:
Enabled: false Enabled: false

View File

@ -4,7 +4,6 @@ module HTTPX
module Callbacks module Callbacks
def on(type, &action) def on(type, &action)
callbacks(type) << action callbacks(type) << action
self
end end
def once(type, &block) def once(type, &block)
@ -12,7 +11,6 @@ module HTTPX
block.call(*args, &callback) block.call(*args, &callback)
:delete :delete
end end
self
end end
def only(type, &block) def only(type, &block)

View File

@ -10,19 +10,6 @@ module HTTPX
MOD MOD
end end
%i[
connection_opened connection_closed
request_error
request_started request_body_chunk request_completed
response_started response_body_chunk response_completed
].each do |meth|
class_eval(<<-MOD, __FILE__, __LINE__ + 1)
def on_#{meth}(&blk) # def on_connection_opened(&blk)
on(:#{meth}, &blk) # on(:connection_opened, &blk)
end # end
MOD
end
def request(*args, **options) def request(*args, **options)
branch(default_options).request(*args, **options) branch(default_options).request(*args, **options)
end end
@ -69,12 +56,6 @@ module HTTPX
branch(default_options.merge(options), &blk) branch(default_options.merge(options), &blk)
end end
protected
def on(*args, &blk)
branch(default_options).on(*args, &blk)
end
private private
def default_options def default_options

View File

@ -133,42 +133,33 @@ module HTTPX
end end
def on_data(chunk) def on_data(chunk)
request = @request return unless @request
return unless request
log(color: :green) { "-> DATA: #{chunk.bytesize} bytes..." } log(color: :green) { "-> DATA: #{chunk.bytesize} bytes..." }
log(level: 2, color: :green) { "-> #{chunk.inspect}" } log(level: 2, color: :green) { "-> #{chunk.inspect}" }
response = request.response response = @request.response
response << chunk response << chunk
rescue StandardError => e
error_response = ErrorResponse.new(request, e, request.options)
request.response = error_response
dispatch
end end
def on_complete def on_complete
request = @request return unless @request
return unless request
log(level: 2) { "parsing complete" } log(level: 2) { "parsing complete" }
dispatch dispatch
end end
def dispatch def dispatch
request = @request if @request.expects?
if request.expects?
@parser.reset! @parser.reset!
return handle(request) return handle(@request)
end end
request = @request
@request = nil @request = nil
@requests.shift @requests.shift
response = request.response response = request.response
response.finish! unless response.is_a?(ErrorResponse) response.finish!
emit(:response, request, response) emit(:response, request, response)
if @parser.upgrade? if @parser.upgrade?
@ -178,11 +169,7 @@ module HTTPX
@parser.reset! @parser.reset!
@max_requests -= 1 @max_requests -= 1
if response.is_a?(ErrorResponse) manage_connection(response)
disable
else
manage_connection(response)
end
send(@pending.shift) unless @pending.empty? send(@pending.shift) unless @pending.empty?
end end

View File

@ -314,7 +314,6 @@ module HTTPX
ex = Error.new(stream.id, error) ex = Error.new(stream.id, error)
ex.set_backtrace(caller) ex.set_backtrace(caller)
response = ErrorResponse.new(request, ex, request.options) response = ErrorResponse.new(request, ex, request.options)
request.response = response
emit(:response, request, response) emit(:response, request, response)
else else
response = request.response response = request.response

View File

@ -38,10 +38,7 @@ module HTTPX
add_addresses(addresses) add_addresses(addresses)
end end
@ip_index = @addresses.size - 1 @ip_index = @addresses.size - 1
end # @io ||= build_socket
def socket
@io.to_io
end end
def add_addresses(addrs) def add_addresses(addrs)

View File

@ -170,7 +170,11 @@ module HTTPX
proxy = options.proxy proxy = options.proxy
return super unless proxy return super unless proxy
init_connection("tcp", uri, options) connection = options.connection_class.new("tcp", uri, options)
catch(:coalesced) do
pool.init_connection(connection, options)
connection
end
end end
def fetch_response(request, connections, options) def fetch_response(request, connections, options)

View File

@ -95,8 +95,6 @@ module HTTPX
return return
end end
@response = response @response = response
emit(:response_started, response)
end end
def path def path
@ -132,10 +130,8 @@ module HTTPX
return nil if @body.nil? return nil if @body.nil?
@drainer ||= @body.each @drainer ||= @body.each
chunk = @drainer.next.dup chunk = @drainer.next
chunk.dup
emit(:body_chunk, chunk)
chunk
rescue StopIteration rescue StopIteration
nil nil
rescue StandardError => e rescue StandardError => e

View File

@ -9,7 +9,6 @@ require "forwardable"
module HTTPX module HTTPX
class Response class Response
extend Forwardable extend Forwardable
include Callbacks
attr_reader :status, :headers, :body, :version attr_reader :status, :headers, :body, :version
@ -145,13 +144,9 @@ module HTTPX
def write(chunk) def write(chunk)
return if @state == :closed return if @state == :closed
size = chunk.bytesize @length += chunk.bytesize
@length += size
transition transition
@buffer.write(chunk) @buffer.write(chunk)
@response.emit(:chunk_received, chunk)
size
end end
def read(*args) def read(*args)

View File

@ -4,7 +4,6 @@ module HTTPX
class Session class Session
include Loggable include Loggable
include Chainable include Chainable
include Callbacks
EMPTY_HASH = {}.freeze EMPTY_HASH = {}.freeze
@ -46,31 +45,6 @@ module HTTPX
request = rklass.new(verb, uri, options.merge(persistent: @persistent)) request = rklass.new(verb, uri, options.merge(persistent: @persistent))
request.on(:response, &method(:on_response).curry(2)[request]) request.on(:response, &method(:on_response).curry(2)[request])
request.on(:promise, &method(:on_promise)) request.on(:promise, &method(:on_promise))
request.on(:headers) do
emit(:request_started, request)
end
request.on(:body_chunk) do |chunk|
emit(:request_body_chunk, request, chunk)
end
request.on(:done) do
emit(:request_completed, request)
end
request.on(:response_started) do |res|
if res.is_a?(Response)
emit(:response_started, request, res)
res.on(:chunk_received) do |chunk|
emit(:response_body_chunk, request, res, chunk)
end
else
emit(:request_error, request, res.error)
end
end
request.on(:response) do |res|
emit(:response_completed, request, res)
end
request request
end end
@ -200,16 +174,7 @@ module HTTPX
raise UnsupportedSchemeError, "#{uri}: #{uri.scheme}: unsupported URI scheme" raise UnsupportedSchemeError, "#{uri}: #{uri.scheme}: unsupported URI scheme"
end end
end end
init_connection(type, uri, options)
end
def init_connection(type, uri, options)
connection = options.connection_class.new(type, uri, options) connection = options.connection_class.new(type, uri, options)
connection.on(:open) do
emit(:connection_opened, connection.origin, connection.io.socket)
# only run close callback if it opened
connection.on(:close) { emit(:connection_closed, connection.origin, connection.io.socket) }
end
catch(:coalesced) do catch(:coalesced) do
pool.init_connection(connection, options) pool.init_connection(connection, options)
connection connection
@ -287,7 +252,6 @@ module HTTPX
super super
klass.instance_variable_set(:@default_options, @default_options) klass.instance_variable_set(:@default_options, @default_options)
klass.instance_variable_set(:@plugins, @plugins.dup) klass.instance_variable_set(:@plugins, @plugins.dup)
klass.instance_variable_set(:@callbacks, @callbacks.dup)
end end
def plugin(pl, options = nil, &block) def plugin(pl, options = nil, &block)

View File

@ -4,9 +4,9 @@ module HTTPX
end end
module Callbacks module Callbacks
def on: (Symbol) { (*untyped) -> void } -> self def on: (Symbol) { (*untyped) -> void } -> void
def once: (Symbol) { (*untyped) -> void } -> self def once: (Symbol) { (*untyped) -> void } -> void
def only: (Symbol) { (*untyped) -> void } -> self def only: (Symbol) { (*untyped) -> void } -> void
def emit: (Symbol, *untyped) -> void def emit: (Symbol, *untyped) -> void
def callbacks_for?: (Symbol) -> bool def callbacks_for?: (Symbol) -> bool

View File

@ -9,7 +9,6 @@ module HTTPX
class Response class Response
extend Forwardable extend Forwardable
include Callbacks
include _Response include _Response
include _ToS include _ToS

View File

@ -27,9 +27,9 @@ module HTTPX
def on_promise: (untyped, untyped) -> void def on_promise: (untyped, untyped) -> void
def fetch_response: (Request request, Array[Connection] connections, untyped options) -> response? def fetch_response: (Request request, Array[Connection] connections, untyped options) -> response?
def find_connection: (Request request, Array[Connection] connections, Options options) -> Connection def find_connection: (Request, Array[Connection] connections, Options options) -> Connection
def set_connection_callbacks: (Connection connection, Array[Connection] connections, Options options) -> void def set_connection_callbacks: (Connection, Array[Connection], Options) -> void
def build_altsvc_connection: (Connection existing_connection, Array[Connection] connections, URI::Generic alt_origin, String origin, Hash[String, String] alt_params, Options options) -> Connection? def build_altsvc_connection: (Connection existing_connection, Array[Connection] connections, URI::Generic alt_origin, String origin, Hash[String, String] alt_params, Options options) -> Connection?
@ -39,15 +39,13 @@ module HTTPX
| (verb, _Each[[uri, options]], Options) -> Array[Request] | (verb, _Each[[uri, options]], Options) -> Array[Request]
| (verb, _Each[uri], options) -> Array[Request] | (verb, _Each[uri], options) -> Array[Request]
def build_connection: (URI::HTTP | URI::HTTP uri, Options options) -> Connection def build_connection: (URI::HTTP | URI::HTTPS uri, Options options) -> Connection
def init_connection: (String type, URI::HTTP | URI::HTTP uri, Options options) -> Connection
def send_requests: (*Request) -> Array[response] def send_requests: (*Request) -> Array[response]
def _send_requests: (Array[Request] requests) -> Array[Connection] def _send_requests: (Array[Request]) -> Array[Connection]
def receive_requests: (Array[Request] requests, Array[Connection] connections) -> Array[response] def receive_requests: (Array[Request], Array[Connection]) -> Array[response]
attr_reader self.default_options: Options attr_reader self.default_options: Options
end end

View File

@ -13,7 +13,6 @@ class HTTPTest < Minitest::Test
include Headers include Headers
include ResponseBody include ResponseBody
include IO include IO
include Callbacks
include Errors if RUBY_ENGINE == "ruby" include Errors if RUBY_ENGINE == "ruby"
include AltSvc if ENV.key?("HTTPBIN_ALTSVC_HOST") include AltSvc if ENV.key?("HTTPBIN_ALTSVC_HOST")

View File

@ -11,7 +11,6 @@ class HTTPSTest < Minitest::Test
include Headers include Headers
include ResponseBody include ResponseBody
include IO include IO
include Callbacks
include Errors if RUBY_ENGINE == "ruby" include Errors if RUBY_ENGINE == "ruby"
include Resolvers if ENV.key?("HTTPX_RESOLVER_URI") include Resolvers if ENV.key?("HTTPX_RESOLVER_URI")
# TODO: uncomment as soon as nghttpx supports altsvc for HTTP/2 # TODO: uncomment as soon as nghttpx supports altsvc for HTTP/2

View File

@ -29,11 +29,4 @@ module HTTPHelpers
def origin(orig = httpbin) def origin(orig = httpbin)
"#{scheme}#{orig}" "#{scheme}#{orig}"
end end
def next_available_port
server = TCPServer.new("localhost", 0)
server.addr[1]
ensure
server.close
end
end end

View File

@ -1,92 +0,0 @@
# frozen_string_literal: true
require "resolv"
module Requests
using HTTPX::URIExtensions
module Callbacks
def test_callbacks_connection_opened
uri = URI(build_uri("/get"))
origin = ip = nil
response = HTTPX.on_connection_opened do |o, sock|
origin = o
ip = sock.remote_address.ip_address
end.get(uri)
verify_status(response, 200)
assert !origin.nil?
assert origin.to_s == uri.origin
assert !ip.nil?
assert Resolv.getaddresses(uri.host).include?(ip)
end
def test_callbacks_connection_closed
uri = URI(build_uri("/get"))
origin = nil
response = HTTPX.on_connection_closed do |o|
origin = o
end.get(uri)
verify_status(response, 200)
assert !origin.nil?
assert origin.to_s == uri.origin
end
def test_callbacks_request_error
uri = URI(build_uri("/get"))
error = nil
http = HTTPX.on_request_error { |_, err| error = err }
response = http.get(uri)
verify_status(response, 200)
assert error.nil?
unavailable_host = URI(origin("localhost"))
unavailable_host.port = next_available_port
response = http.get(unavailable_host.to_s)
verify_error_response(response, /Connection refused| not available/)
assert !error.nil?
assert error == response.error
end
def test_callbacks_request
uri = URI(build_uri("/post"))
started = completed = false
chunks = 0
http = HTTPX.on_request_started { |_| started = true }
.on_request_body_chunk { |_, _chunk| chunks += 1 }
.on_request_completed { |_| completed = true }
response = http.post(uri, body: "data")
verify_status(response, 200)
assert started
assert completed
assert chunks.positive?
end
def test_callbacks_response
uri = URI(build_uri("/get"))
started = completed = false
chunks = 0
http = HTTPX.on_response_started { |_, _| started = true }
.on_response_body_chunk { |_, _, _chunk| chunks += 1 }
.on_response_completed { |_, _| completed = true }
response = http.get(uri)
verify_status(response, 200)
assert started
assert completed
assert chunks.positive?
end
end
end

View File

@ -41,21 +41,13 @@ module Requests
# end # end
# end # end
ResponseErrorEmitter = Module.new do private
self::ResponseMethods = Module.new do
def <<(_)
raise "done with it"
end
end
end
def test_errors_mid_response_buffering def next_available_port
uri = URI(build_uri("/get")) server = TCPServer.new("localhost", 0)
HTTPX.plugin(SessionWithPool).plugin(ResponseErrorEmitter).wrap do |http| server.addr[1]
response = http.get(uri) ensure
verify_error_response(response, "done with it") server.close
assert http.pool.connections.empty?
end
end end
end end
end end