added a global store for domains not supporting 100-continue

it's a pretty naive implementation, as it grows unbounded, and isn't
thread safe, mostly due to negligent cost of fake fetch.
This commit is contained in:
HoneyryderChuck 2021-01-12 20:44:50 +00:00
parent 49aa918fa2
commit e1ccae25f9
2 changed files with 28 additions and 14 deletions

View File

@ -10,6 +10,10 @@ module HTTPX
module Expect
EXPECT_TIMEOUT = 2
def self.no_expect_store
@no_expect_store ||= []
end
def self.extra_options(options)
Class.new(options.class) do
def_option(:expect_timeout) do |seconds|
@ -29,6 +33,18 @@ module HTTPX
end
module RequestMethods
def initialize(*)
super
return if @body.empty?
threshold = @options.expect_threshold_size
return if threshold && !@body.unbounded_body? && @body.bytesize < threshold
return if Expect.no_expect_store.include?(origin)
@headers["expect"] = "100-continue"
end
def response=(response)
if response && response.status == 100 &&
!@headers.key?("expect") &&
@ -42,28 +58,18 @@ module HTTPX
# so we have to reactivate it again.
@headers["expect"] = "100-continue"
@informational_status = 100
Expect.no_expect_store.delete(origin)
end
super
end
end
module RequestBodyMethods
def initialize(*, options)
super
return if @body.nil?
threshold = options.expect_threshold_size
return if threshold && !unbounded_body? && @body.bytesize < threshold
@headers["expect"] = "100-continue"
end
end
module ConnectionMethods
def send(request)
request.once(:expect) do
@timers.after(@options.expect_timeout) do
if request.state == :expect && !request.expects?
Expect.no_expect_store << request.origin
request.headers.delete("expect")
consume
end

View File

@ -20,12 +20,16 @@ module Requests
server = Expect100Server.new
th = Thread.new { server.start }
begin
http = HTTPX.plugin(:expect)
uri = build_uri("/delay?delay=4", server.origin)
response = HTTPX.plugin(:expect).post(uri, body: "helloworld")
response = http.post(uri, body: "helloworld")
verify_status(response, 200)
body = response.body.to_s
assert body == "echo: helloworld"
verify_header(response.instance_variable_get(:@request).headers, "expect", "100-continue")
next_request = http.build_request(:post, build_uri("/", server.origin), body: "helloworld")
verify_header(next_request.headers, "expect", "100-continue")
ensure
server.shutdown
th.join
@ -53,12 +57,16 @@ module Requests
server = Expect100Server.new
th = Thread.new { server.start }
begin
http = HTTPX.plugin(:expect)
uri = build_uri("/no-expect", server.origin)
response = HTTPX.plugin(:expect).post(uri, body: "helloworld")
response = http.post(uri, body: "helloworld")
verify_status(response, 200)
body = response.body.to_s
assert body == "echo: helloworld"
verify_no_header(response.instance_variable_get(:@request).headers, "expect")
next_request = http.build_request(:post, build_uri("/", server.origin), body: "helloworld")
verify_no_header(next_request.headers, "expect")
ensure
server.shutdown
th.join