expect plugin

this plugin sets all body requests to send the expect-100 header before
sending any payload, a la curl. It recovers from 417 as well.
This commit is contained in:
HoneyryderChuck 2020-03-07 23:40:59 +00:00
parent 6e15b15bda
commit 926ad27011
6 changed files with 81 additions and 11 deletions

View File

@ -0,0 +1,39 @@
# frozen_string_literal: true
module HTTPX
module Plugins
#
# This plugin makes all HTTP/1.1 requests with a body send the "Expect: 100-continue".
#
# https://gitlab.com/honeyryderchuck/httpx/wikis/Expect#expect
#
module Expect
module RequestBodyMethods
def initialize(*)
super
return if @body.nil?
@headers["expect"] = "100-continue"
end
end
module InstanceMethods
def fetch_response(request, connections, options)
response = @responses.delete(request)
return unless response
if response.status == 417 && request.headers.key?("expect")
request.headers.delete("expect")
request.transition(:idle)
connection = find_connection(request, connections, options)
connection.send(request)
return
end
response
end
end
end
register_plugin :expect, Expect
end
end

View File

@ -54,6 +54,7 @@ module HTTPX
def fetch_response(request, connections, options)
response = @responses.delete(request)
return unless response
if response.status == 417 && request.headers.key?("expect")
request.headers.delete("expect")
request.transition(:idle)

View File

@ -24,6 +24,7 @@ class HTTPTest < Minitest::Test
include Plugins::H2C
include Plugins::Retries
include Plugins::Multipart
include Plugins::Expect
def test_verbose_log
log = StringIO.new

View File

@ -24,6 +24,7 @@ class HTTPSTest < Minitest::Test
include Plugins::PushPromise if OpenSSL::SSL::SSLContext.instance_methods.include?(:alpn_protocols)
include Plugins::Retries
include Plugins::Multipart
include Plugins::Expect
def test_connection_coalescing
coalesced_origin = "https://#{ENV["HTTPBIN_COALESCING_HOST"]}"

View File

@ -0,0 +1,39 @@
# frozen_string_literal: true
module Requests
module Plugins
module Expect
def test_plugin_expect_100_form_params
uri = build_uri("/post")
response = HTTPX.plugin(:expect).post(uri, form: { "foo" => "bar" })
verify_status(response, 200)
body = json_body(response)
verify_header(body["headers"], "Content-Type", "application/x-www-form-urlencoded")
verify_header(body["headers"], "Expect", "100-continue")
verify_uploaded(body, "form", "foo" => "bar")
end
# def test_plugin_expect_100_send_body_after_delay
# uri = build_uri("/delay/3")
# response = HTTPX.plugin(:expect).post(uri, form: { "foo" => "bar" })
# verify_status(response, 200)
# body = json_body(response)
# verify_header(body["headers"], "Content-Type", "application/x-www-form-urlencoded")
# verify_header(body["headers"], "Expect", "100-continue")
# verify_uploaded(body, "form", "foo" => "bar")
# verify_no_header(response.instance_variable_get(:@request).headers, "expect")
# end
def test_plugin_expect_100_form_params_417
uri = build_uri("/status/417")
response = HTTPX.plugin(:expect).post(uri, form: { "foo" => "bar" })
# we can't really test that the request would be successful without it, however we can
# test whether the header has been removed from the request.
verify_status(response, 417)
verify_no_header(response.instance_variable_get(:@request).headers, "expect")
end
end
end
end

View File

@ -32,17 +32,6 @@ module Requests
verify_uploaded(body, "form", "foo" => "bar")
end
define_method :"test_#{meth}_expect_100_form_params_417" do
uri = build_uri("/status/417")
response = HTTPX.headers("expect" => "100-continue")
.send(meth, uri, form: { "foo" => "bar" })
# we can't really test that the request would be successful without it, however we can
# test whether the header has been removed from the request.
verify_status(response, 417)
verify_no_header(response.instance_variable_get(:@request).headers, "expect")
end
define_method :"test_#{meth}_json_params" do
uri = build_uri("/#{meth}")
response = HTTPX.send(meth, uri, json: { "foo" => "bar" })