mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-08-10 00:01:27 -04:00
Added multipart plugin, to handle multipart requests
This logic was extracted from the vanilla httpx build to a plugin to make the gem "leaner", by removing "http_form_data" as a hard dependency. The multipart plugin still requires one to install it though, but if you don't need to upload files, you don't have to install the gem anymore
This commit is contained in:
parent
82ef579047
commit
ce674ff4e2
@ -20,8 +20,7 @@ Gem::Specification.new do |gem|
|
||||
gem.require_paths = ["lib"]
|
||||
gem.version = HTTPX::VERSION
|
||||
|
||||
gem.add_runtime_dependency "http-2", ">= 0.9.0"
|
||||
gem.add_runtime_dependency "http-form_data", ">= 2.0.0", "< 3"
|
||||
|
||||
gem.add_development_dependency "http-cookie", "~> 1.0"
|
||||
gem.add_runtime_dependency "http-2", ">= 0.9.0"
|
||||
gem.add_development_dependency "http-form_data", ">= 2.0.0", "< 3"
|
||||
gem.add_development_dependency "http-cookie", "~> 1.0"
|
||||
end
|
||||
|
50
lib/httpx/plugins/multipart.rb
Normal file
50
lib/httpx/plugins/multipart.rb
Normal file
@ -0,0 +1,50 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module HTTPX
|
||||
module Plugins
|
||||
module Multipart
|
||||
module FormTranscoder
|
||||
module_function
|
||||
|
||||
class Encoder
|
||||
extend Forwardable
|
||||
|
||||
def_delegator :@raw, :content_type
|
||||
|
||||
def_delegator :@raw, :to_s
|
||||
|
||||
def_delegator :@raw, :read
|
||||
|
||||
def initialize(form)
|
||||
@raw = HTTP::FormData.create(form)
|
||||
end
|
||||
|
||||
def bytesize
|
||||
@raw.content_length
|
||||
end
|
||||
|
||||
def force_encoding(*args)
|
||||
@raw.to_s.force_encoding(*args)
|
||||
end
|
||||
|
||||
def to_str
|
||||
@raw.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def encode(form)
|
||||
Encoder.new(form)
|
||||
end
|
||||
end
|
||||
|
||||
def self.load_dependencies(*)
|
||||
require "http/form_data"
|
||||
end
|
||||
|
||||
def self.configure(*)
|
||||
Transcoder.register("form", FormTranscoder)
|
||||
end
|
||||
end
|
||||
register_plugin :multipart, Multipart
|
||||
end
|
||||
end
|
@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "forwardable"
|
||||
require "http/form_data"
|
||||
require "uri"
|
||||
|
||||
module HTTPX::Transcoder
|
||||
module Form
|
||||
@ -10,22 +10,18 @@ module HTTPX::Transcoder
|
||||
class Encoder
|
||||
extend Forwardable
|
||||
|
||||
def_delegator :@raw, :content_type
|
||||
|
||||
def_delegator :@raw, :to_s
|
||||
|
||||
def_delegator :@raw, :read
|
||||
def_delegator :@raw, :bytesize
|
||||
|
||||
def_delegator :@raw, :force_encoding
|
||||
|
||||
def initialize(form)
|
||||
@raw = HTTP::FormData.create(form)
|
||||
@raw = URI.encode_www_form(form)
|
||||
end
|
||||
|
||||
def bytesize
|
||||
@raw.content_length
|
||||
end
|
||||
|
||||
def force_encoding(*args)
|
||||
@raw.to_s.force_encoding(*args)
|
||||
def content_type
|
||||
"application/x-www-form-urlencoded"
|
||||
end
|
||||
|
||||
def to_str
|
||||
|
@ -23,6 +23,7 @@ class HTTPTest < Minitest::Test
|
||||
include Plugins::Compression
|
||||
include Plugins::H2C
|
||||
include Plugins::Retries
|
||||
include Plugins::Multipart
|
||||
|
||||
private
|
||||
|
||||
|
@ -21,6 +21,7 @@ class HTTPSTest < Minitest::Test
|
||||
include Plugins::Compression
|
||||
include Plugins::PushPromise if OpenSSL::SSL::SSLContext.instance_methods.include?(:alpn_protocols)
|
||||
include Plugins::Retries
|
||||
include Plugins::Multipart
|
||||
|
||||
private
|
||||
|
||||
|
48
test/support/requests/plugins/multipart.rb
Normal file
48
test/support/requests/plugins/multipart.rb
Normal file
@ -0,0 +1,48 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "http/form_data"
|
||||
|
||||
module Requests
|
||||
module Plugins
|
||||
module Multipart
|
||||
%w[post put patch delete].each do |meth|
|
||||
define_method :"test_plugin_multipart_urlencoded_#{meth}" do
|
||||
uri = build_uri("/#{meth}")
|
||||
response = HTTPX.plugin(:multipart)
|
||||
.send(meth, uri, form: { "foo" => "bar" })
|
||||
verify_status(response, 200)
|
||||
body = json_body(response)
|
||||
verify_header(body["headers"], "Content-Type", "application/x-www-form-urlencoded")
|
||||
verify_uploaded(body, "form", "foo" => "bar")
|
||||
end
|
||||
|
||||
define_method :"test_plugin_multipart_formdata_#{meth}" do
|
||||
uri = build_uri("/#{meth}")
|
||||
response = HTTPX.plugin(:multipart)
|
||||
.send(meth, uri, form: { image: HTTP::FormData::File.new(fixture_file_path) })
|
||||
verify_status(response, 200)
|
||||
body = json_body(response)
|
||||
verify_header(body["headers"], "Content-Type", "multipart/form-data")
|
||||
verify_uploaded_image(body)
|
||||
end
|
||||
end
|
||||
|
||||
def fixture
|
||||
File.read(fixture_file_path, encoding: Encoding::BINARY)
|
||||
end
|
||||
|
||||
def fixture_name
|
||||
File.basename(fixture_file_path)
|
||||
end
|
||||
|
||||
def fixture_file_path
|
||||
File.join("test", "support", "fixtures", "image.jpg")
|
||||
end
|
||||
|
||||
def verify_uploaded_image(body)
|
||||
assert body.key?("files"), "there were no files uploaded"
|
||||
assert body["files"].key?("image"), "there is no image in the file"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -21,6 +21,17 @@ module Requests
|
||||
verify_uploaded(body, "form", "foo" => "bar")
|
||||
end
|
||||
|
||||
define_method :"test_#{meth}_expect_100_form_params" do
|
||||
uri = build_uri("/#{meth}")
|
||||
response = HTTPX.headers("expect" => "100-continue")
|
||||
.send(meth, 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
|
||||
|
||||
define_method :"test_#{meth}_json_params" do
|
||||
uri = build_uri("/#{meth}")
|
||||
response = HTTPX.send(meth, uri, json: { "foo" => "bar" })
|
||||
@ -73,50 +84,13 @@ module Requests
|
||||
verify_header(body["headers"], "Content-Type", "application/octet-stream")
|
||||
verify_uploaded(body, "data", "data")
|
||||
end
|
||||
|
||||
define_method :"test_#{meth}_form_file_params" do
|
||||
uri = build_uri("/#{meth}")
|
||||
response = HTTPX.send(meth, uri, form: { image: HTTP::FormData::File.new(fixture_file_path) })
|
||||
verify_status(response, 200)
|
||||
body = json_body(response)
|
||||
verify_header(body["headers"], "Content-Type", "multipart/form-data")
|
||||
verify_uploaded_image(body)
|
||||
end
|
||||
|
||||
define_method :"test_#{meth}_expect_100_form_file_params" do
|
||||
uri = build_uri("/#{meth}")
|
||||
response = HTTPX.headers("expect" => "100-continue")
|
||||
.send(meth, uri, form: { image: HTTP::FormData::File.new(fixture_file_path) })
|
||||
verify_status(response, 200)
|
||||
body = json_body(response)
|
||||
verify_header(body["headers"], "Content-Type", "multipart/form-data")
|
||||
verify_header(body["headers"], "Expect", "100-continue")
|
||||
verify_uploaded_image(body)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fixture
|
||||
File.read(fixture_file_path, encoding: Encoding::BINARY)
|
||||
end
|
||||
|
||||
def fixture_name
|
||||
File.basename(fixture_file_path)
|
||||
end
|
||||
|
||||
def fixture_file_path
|
||||
File.join("test", "support", "fixtures", "image.jpg")
|
||||
end
|
||||
|
||||
def verify_uploaded(body, type, expect)
|
||||
assert body.key?(type), "there is no #{type} available"
|
||||
assert body[type] == expect, "#{type} is unexpected: #{body[type]} (expected: #{expect})"
|
||||
end
|
||||
|
||||
def verify_uploaded_image(body)
|
||||
assert body.key?("files"), "there were no files uploaded"
|
||||
assert body["files"].key?("image"), "there is no image in the file"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user