mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-10-17 00:02:49 -04:00
Merge branch 'fix-altsvc' into 'master'
Fix ALTSVC parsing See merge request honeyryderchuck/httpx!44
This commit is contained in:
commit
032769ccf1
@ -10,7 +10,6 @@ services:
|
|||||||
- HTTPX_SOCKS4A_PROXY=socks4a://socksproxy:8080
|
- HTTPX_SOCKS4A_PROXY=socks4a://socksproxy:8080
|
||||||
- HTTPX_SOCKS5_PROXY=socks5://socksproxy:8080
|
- HTTPX_SOCKS5_PROXY=socks5://socksproxy:8080
|
||||||
- HTTPX_SSH_PROXY=ssh://sshproxy:22
|
- HTTPX_SSH_PROXY=ssh://sshproxy:22
|
||||||
- PARALLEL=1
|
|
||||||
- N=6 # minitest workers
|
- N=6 # minitest workers
|
||||||
- CI=1
|
- CI=1
|
||||||
- JEKYLL_ENV=production
|
- JEKYLL_ENV=production
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "strscan"
|
||||||
|
|
||||||
module HTTPX
|
module HTTPX
|
||||||
module AltSvc
|
module AltSvc
|
||||||
@altsvc_mutex = Mutex.new
|
@altsvc_mutex = Mutex.new
|
||||||
@ -49,9 +51,18 @@ module HTTPX
|
|||||||
def parse(altsvc)
|
def parse(altsvc)
|
||||||
return enum_for(__method__, altsvc) unless block_given?
|
return enum_for(__method__, altsvc) unless block_given?
|
||||||
|
|
||||||
alt_origins, *alt_params = altsvc.split(/ *; */)
|
scanner = StringScanner.new(altsvc)
|
||||||
alt_params = Hash[alt_params.map { |field| field.split("=") }]
|
until scanner.eos?
|
||||||
alt_origins.split(/ *, */).each do |alt_origin|
|
alt_origin = scanner.scan(/[^=]+=("[^"]+"|[^;,]+)/)
|
||||||
|
|
||||||
|
alt_params = []
|
||||||
|
loop do
|
||||||
|
alt_param = scanner.scan(/[^=]+=("[^"]+"|[^;,]+)/)
|
||||||
|
alt_params << alt_param.strip if alt_param
|
||||||
|
scanner.skip(/;/)
|
||||||
|
break if scanner.eos? || scanner.scan(/ *, */)
|
||||||
|
end
|
||||||
|
alt_params = Hash[alt_params.map { |field| field.split("=") }]
|
||||||
yield(parse_altsvc_origin(alt_origin), alt_params)
|
yield(parse_altsvc_origin(alt_origin), alt_params)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -46,8 +46,6 @@ module HTTPX
|
|||||||
|
|
||||||
attr_reader :origin, :state, :pending, :options
|
attr_reader :origin, :state, :pending, :options
|
||||||
|
|
||||||
attr_reader :timeout
|
|
||||||
|
|
||||||
def initialize(type, uri, options)
|
def initialize(type, uri, options)
|
||||||
@type = type
|
@type = type
|
||||||
@origins = [uri.origin]
|
@origins = [uri.origin]
|
||||||
@ -188,7 +186,6 @@ module HTTPX
|
|||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
@timeout = @timeout_threshold
|
|
||||||
case @state
|
case @state
|
||||||
when :closed
|
when :closed
|
||||||
return
|
return
|
||||||
@ -202,6 +199,14 @@ module HTTPX
|
|||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def timeout
|
||||||
|
return @timeout if defined?(@timeout)
|
||||||
|
|
||||||
|
return @options.timeout.connect_timeout if @state == :idle
|
||||||
|
|
||||||
|
@options.timeout.operation_timeout
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def consume
|
def consume
|
||||||
@ -289,8 +294,8 @@ module HTTPX
|
|||||||
transition(:open)
|
transition(:open)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
parser.on(:timeout) do |timeout|
|
parser.on(:timeout) do |tout|
|
||||||
@timeout = timeout
|
@timeout = tout
|
||||||
end
|
end
|
||||||
parser.on(:error) do |request, ex|
|
parser.on(:error) do |request, ex|
|
||||||
case ex
|
case ex
|
||||||
@ -307,8 +312,6 @@ module HTTPX
|
|||||||
case nextstate
|
case nextstate
|
||||||
when :idle
|
when :idle
|
||||||
@error = nil
|
@error = nil
|
||||||
@timeout_threshold = @options.timeout.connect_timeout
|
|
||||||
@timeout = @timeout_threshold
|
|
||||||
when :open
|
when :open
|
||||||
return if @state == :closed
|
return if @state == :closed
|
||||||
|
|
||||||
@ -316,8 +319,6 @@ module HTTPX
|
|||||||
return unless @io.connected?
|
return unless @io.connected?
|
||||||
|
|
||||||
send_pending
|
send_pending
|
||||||
@timeout_threshold = @options.timeout.operation_timeout
|
|
||||||
@timeout = @timeout_threshold
|
|
||||||
emit(:open)
|
emit(:open)
|
||||||
when :closing
|
when :closing
|
||||||
return unless @state == :open
|
return unless @state == :open
|
||||||
@ -327,11 +328,10 @@ module HTTPX
|
|||||||
|
|
||||||
@io.close
|
@io.close
|
||||||
@read_buffer.clear
|
@read_buffer.clear
|
||||||
|
remove_instance_variable(:@timeout) if defined?(@timeout)
|
||||||
when :already_open
|
when :already_open
|
||||||
nextstate = :open
|
nextstate = :open
|
||||||
send_pending
|
send_pending
|
||||||
@timeout_threshold = @options.timeout.operation_timeout
|
|
||||||
@timeout = @timeout_threshold
|
|
||||||
end
|
end
|
||||||
@state = nextstate
|
@state = nextstate
|
||||||
rescue Errno::EHOSTUNREACH
|
rescue Errno::EHOSTUNREACH
|
||||||
|
@ -81,8 +81,11 @@ module HTTPX
|
|||||||
return reset_timer unless @started
|
return reset_timer unless @started
|
||||||
|
|
||||||
@time_left -= (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @started)
|
@time_left -= (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @started)
|
||||||
raise TotalTimeoutError.new(@total_timeout, "Timed out after #{@total_timeout} seconds") if no_time_left?
|
if no_time_left?
|
||||||
|
reset_counter
|
||||||
|
raise TotalTimeoutError.new(@total_timeout, "Timed out after #{@total_timeout} seconds")
|
||||||
|
end
|
||||||
|
ensure
|
||||||
reset_timer
|
reset_timer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -5,14 +5,38 @@ require_relative "test_helper"
|
|||||||
class AltSvcTest < Minitest::Test
|
class AltSvcTest < Minitest::Test
|
||||||
include HTTPX
|
include HTTPX
|
||||||
|
|
||||||
def test_parse
|
def test_altsvc_parse_svc
|
||||||
assert [["h2=alt.example.com", {}]], AltSvc.parse("h2=alt.example.com").to_a
|
assert [["h2=alt.example.com", {}]], AltSvc.parse("h2=alt.example.com").to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_altsvc_parse_svc_with_port
|
||||||
assert [["h2=alt.example.com:8000", {}]], AltSvc.parse("h2=\"alt.example.com:8000\"").to_a
|
assert [["h2=alt.example.com:8000", {}]], AltSvc.parse("h2=\"alt.example.com:8000\"").to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_altsvc_parse_svcs
|
||||||
assert [["h2=alt.example.com:8000", {}], ["h2=:8000", {}]],
|
assert [["h2=alt.example.com:8000", {}], ["h2=:8000", {}]],
|
||||||
AltSvc.parse("h2=\"alt.example.com:8000\", h2=\":443\"").to_a
|
AltSvc.parse("h2=\"alt.example.com:8000\", h2=\":443\"").to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_altsvc_parse_svc_prop
|
||||||
assert [["h2=alt.example.com:8000'", { "ma" => "60" }]],
|
assert [["h2=alt.example.com:8000'", { "ma" => "60" }]],
|
||||||
AltSvc.parse("h2=\"alt.example.com:8000\"; ma=60").to_a
|
AltSvc.parse("h2=\"alt.example.com:8000\"; ma=60").to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_altsvc_parse_svc_props
|
||||||
assert [["h2=alt.example.com:8000", { "persist" => "1" }]],
|
assert [["h2=alt.example.com:8000", { "persist" => "1" }]],
|
||||||
AltSvc.parse("h2=\"alt.example.com:8000\"; ma=60; persist=1").to_a
|
AltSvc.parse("h2=\"alt.example.com:8000\"; ma=60; persist=1").to_a
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_altsvc_parse_svc_with_versions
|
||||||
|
assert [["quic=:443", { "ma" => "2592000", "v" => "46,43,39" }]],
|
||||||
|
AltSvc.parse("quic=\":443\"; ma=2592000; v=\"46,43,39\"").to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_altsvc_parse_svcs_with_props
|
||||||
|
assert [["quic=:443", { "ma" => "2592000", "v" => "46,43" }],
|
||||||
|
["h3-Q046=:443", { "ma" => "2592000" }],
|
||||||
|
["h3-Q043=:443", { "ma" => "2592000" }]],
|
||||||
|
AltSvc.parse("quic=\":443\"; ma=2592000; v=\"46,43\",h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000").to_a
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user