httpx 0.24.6 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +0 -48
- data/README.md +4 -13
- data/doc/release_notes/0_24_4.md +3 -3
- data/doc/release_notes/1_0_0.md +60 -0
- data/lib/httpx/adapters/datadog.rb +28 -97
- data/lib/httpx/adapters/faraday.rb +9 -52
- data/lib/httpx/adapters/webmock.rb +2 -7
- data/lib/httpx/altsvc.rb +4 -22
- data/lib/httpx/base64.rb +27 -0
- data/lib/httpx/chainable.rb +0 -23
- data/lib/httpx/connection.rb +11 -32
- data/lib/httpx/domain_name.rb +5 -12
- data/lib/httpx/errors.rb +0 -2
- data/lib/httpx/extensions.rb +0 -124
- data/lib/httpx/io/ssl.rb +26 -59
- data/lib/httpx/io/tcp.rb +27 -68
- data/lib/httpx/io/udp.rb +13 -48
- data/lib/httpx/io/unix.rb +1 -8
- data/lib/httpx/loggable.rb +4 -19
- data/lib/httpx/options.rb +24 -84
- data/lib/httpx/plugins/{authentication → auth}/basic.rb +1 -5
- data/lib/httpx/plugins/{authentication → auth}/digest.rb +2 -5
- data/lib/httpx/plugins/{authentication → auth}/ntlm.rb +1 -3
- data/lib/httpx/plugins/{authentication → auth}/socks5.rb +0 -2
- data/lib/httpx/plugins/auth.rb +25 -0
- data/lib/httpx/plugins/aws_sigv4.rb +0 -1
- data/lib/httpx/plugins/{basic_authentication.rb → basic_auth.rb} +5 -6
- data/lib/httpx/plugins/brotli.rb +50 -0
- data/lib/httpx/plugins/circuit_breaker/circuit.rb +40 -16
- data/lib/httpx/plugins/circuit_breaker/circuit_store.rb +16 -5
- data/lib/httpx/plugins/circuit_breaker.rb +11 -4
- data/lib/httpx/plugins/cookies/set_cookie_parser.rb +0 -2
- data/lib/httpx/plugins/cookies.rb +1 -1
- data/lib/httpx/plugins/{digest_authentication.rb → digest_auth.rb} +5 -5
- data/lib/httpx/plugins/follow_redirects.rb +21 -24
- data/lib/httpx/plugins/grpc/grpc_encoding.rb +82 -0
- data/lib/httpx/plugins/grpc/message.rb +7 -39
- data/lib/httpx/plugins/grpc.rb +15 -21
- data/lib/httpx/plugins/h2c.rb +0 -1
- data/lib/httpx/plugins/{ntlm_authentication.rb → ntlm_auth.rb} +5 -5
- data/lib/httpx/plugins/oauth.rb +2 -2
- data/lib/httpx/plugins/proxy/http.rb +0 -2
- data/lib/httpx/plugins/proxy/socks4.rb +0 -4
- data/lib/httpx/plugins/proxy/socks5.rb +1 -5
- data/lib/httpx/plugins/proxy.rb +3 -32
- data/lib/httpx/plugins/retries.rb +3 -4
- data/lib/httpx/plugins/stream.rb +4 -6
- data/lib/httpx/punycode.rb +9 -291
- data/lib/httpx/request/body.rb +145 -0
- data/lib/httpx/request.rb +2 -119
- data/lib/httpx/resolver/https.rb +1 -1
- data/lib/httpx/resolver/native.rb +6 -14
- data/lib/httpx/resolver/resolver.rb +1 -1
- data/lib/httpx/resolver/system.rb +11 -9
- data/lib/httpx/response/body.rb +206 -0
- data/lib/httpx/response/buffer.rb +90 -0
- data/lib/httpx/response.rb +5 -208
- data/lib/httpx/selector.rb +0 -2
- data/lib/httpx/session.rb +0 -10
- data/lib/httpx/transcoder/body.rb +0 -1
- data/lib/httpx/transcoder/deflate.rb +37 -0
- data/lib/httpx/transcoder/form.rb +52 -32
- data/lib/httpx/transcoder/gzip.rb +74 -0
- data/lib/httpx/transcoder/json.rb +2 -4
- data/lib/httpx/transcoder/multipart/decoder.rb +139 -0
- data/lib/httpx/{plugins → transcoder}/multipart/encoder.rb +3 -3
- data/lib/httpx/{plugins → transcoder}/multipart/mime_type_detector.rb +1 -1
- data/lib/httpx/{plugins → transcoder}/multipart/part.rb +3 -2
- data/lib/httpx/transcoder/multipart.rb +17 -0
- data/lib/httpx/transcoder/utils/body_reader.rb +46 -0
- data/lib/httpx/transcoder/utils/deflater.rb +72 -0
- data/lib/httpx/transcoder/xml.rb +0 -2
- data/lib/httpx/transcoder.rb +2 -2
- data/lib/httpx/utils.rb +10 -20
- data/lib/httpx/version.rb +1 -1
- data/lib/httpx.rb +0 -8
- data/sig/chainable.rbs +5 -6
- data/sig/connection.rbs +0 -1
- data/sig/errors.rbs +0 -3
- data/sig/httpx.rbs +2 -1
- data/sig/io/unix.rbs +1 -1
- data/sig/options.rbs +12 -8
- data/sig/plugins/{authentication → auth}/basic.rbs +0 -2
- data/sig/plugins/auth.rbs +13 -0
- data/sig/plugins/{basic_authentication.rbs → basic_auth.rbs} +2 -2
- data/sig/plugins/brotli.rbs +22 -0
- data/sig/plugins/circuit_breaker.rbs +7 -3
- data/sig/plugins/compression.rbs +0 -2
- data/sig/plugins/{digest_authentication.rbs → digest_auth.rbs} +2 -2
- data/sig/plugins/follow_redirects.rbs +0 -1
- data/sig/plugins/grpc/call.rbs +19 -0
- data/sig/plugins/grpc/grpc_encoding.rbs +33 -0
- data/sig/plugins/grpc/message.rbs +17 -0
- data/sig/plugins/grpc.rbs +2 -32
- data/sig/plugins/{ntlm_authentication.rbs → ntlm_auth.rbs} +2 -2
- data/sig/plugins/oauth.rbs +1 -1
- data/sig/plugins/proxy/socks4.rbs +2 -3
- data/sig/plugins/proxy/socks5.rbs +0 -1
- data/sig/plugins/proxy/ssh.rbs +1 -1
- data/sig/plugins/response_cache.rbs +5 -2
- data/sig/request/body.rbs +42 -0
- data/sig/request.rbs +1 -27
- data/sig/resolver/resolver.rbs +1 -1
- data/sig/response/body.rbs +52 -0
- data/sig/response/buffer.rbs +24 -0
- data/sig/response.rbs +0 -39
- data/sig/transcoder/body.rbs +4 -3
- data/sig/transcoder/deflate.rbs +11 -0
- data/sig/transcoder/form.rbs +5 -3
- data/sig/transcoder/gzip.rbs +24 -0
- data/sig/transcoder/json.rbs +4 -2
- data/sig/{plugins → transcoder}/multipart.rbs +3 -10
- data/sig/transcoder/utils/body_reader.rbs +15 -0
- data/sig/transcoder/utils/deflater.rbs +29 -0
- data/sig/transcoder.rbs +18 -2
- metadata +50 -34
- data/lib/httpx/plugins/authentication.rb +0 -24
- data/lib/httpx/plugins/compression/brotli.rb +0 -54
- data/lib/httpx/plugins/compression/deflate.rb +0 -54
- data/lib/httpx/plugins/compression/gzip.rb +0 -90
- data/lib/httpx/plugins/compression.rb +0 -165
- data/lib/httpx/plugins/multipart/decoder.rb +0 -137
- data/lib/httpx/plugins/multipart.rb +0 -96
- data/sig/plugins/authentication.rbs +0 -13
- data/sig/plugins/compression/brotli.rbs +0 -21
- data/sig/plugins/compression/deflate.rbs +0 -17
- data/sig/plugins/compression/gzip.rbs +0 -29
- /data/sig/plugins/{authentication → auth}/digest.rbs +0 -0
- /data/sig/plugins/{authentication → auth}/ntlm.rbs +0 -0
- /data/sig/plugins/{authentication → auth}/socks5.rbs +0 -0
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "tempfile"
|
|
4
|
-
require "delegate"
|
|
5
|
-
|
|
6
|
-
module HTTPX::Plugins
|
|
7
|
-
module Multipart
|
|
8
|
-
class FilePart < SimpleDelegator
|
|
9
|
-
attr_reader :original_filename, :content_type
|
|
10
|
-
|
|
11
|
-
def initialize(filename, content_type)
|
|
12
|
-
@original_filename = filename
|
|
13
|
-
@content_type = content_type
|
|
14
|
-
@file = Tempfile.new("httpx", encoding: Encoding::BINARY, mode: File::RDWR)
|
|
15
|
-
super(@file)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
class Decoder
|
|
20
|
-
include HTTPX::Utils
|
|
21
|
-
|
|
22
|
-
CRLF = "\r\n"
|
|
23
|
-
BOUNDARY_RE = /;\s*boundary=([^;]+)/i.freeze
|
|
24
|
-
MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{CRLF}/ni.freeze
|
|
25
|
-
MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:.*;\s*name=(#{VALUE})/ni.freeze
|
|
26
|
-
MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{CRLF}]*)/ni.freeze
|
|
27
|
-
WINDOW_SIZE = 2 << 14
|
|
28
|
-
|
|
29
|
-
def initialize(response)
|
|
30
|
-
@boundary = begin
|
|
31
|
-
m = response.headers["content-type"].to_s[BOUNDARY_RE, 1]
|
|
32
|
-
raise Error, "no boundary declared in content-type header" unless m
|
|
33
|
-
|
|
34
|
-
m.strip
|
|
35
|
-
end
|
|
36
|
-
@buffer = "".b
|
|
37
|
-
@parts = {}
|
|
38
|
-
@intermediate_boundary = "--#{@boundary}"
|
|
39
|
-
@state = :idle
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def call(response, *)
|
|
43
|
-
response.body.each do |chunk|
|
|
44
|
-
@buffer << chunk
|
|
45
|
-
|
|
46
|
-
parse
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
raise Error, "invalid or unsupported multipart format" unless @buffer.empty?
|
|
50
|
-
|
|
51
|
-
@parts
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
private
|
|
55
|
-
|
|
56
|
-
def parse
|
|
57
|
-
case @state
|
|
58
|
-
when :idle
|
|
59
|
-
raise Error, "payload does not start with boundary" unless @buffer.start_with?("#{@intermediate_boundary}#{CRLF}")
|
|
60
|
-
|
|
61
|
-
@buffer = @buffer.byteslice(@intermediate_boundary.bytesize + 2..-1)
|
|
62
|
-
|
|
63
|
-
@state = :part_header
|
|
64
|
-
when :part_header
|
|
65
|
-
idx = @buffer.index("#{CRLF}#{CRLF}")
|
|
66
|
-
|
|
67
|
-
# raise Error, "couldn't parse part headers" unless idx
|
|
68
|
-
return unless idx
|
|
69
|
-
|
|
70
|
-
head = @buffer.byteslice(0..idx + 4 - 1)
|
|
71
|
-
|
|
72
|
-
@buffer = @buffer.byteslice(head.bytesize..-1)
|
|
73
|
-
|
|
74
|
-
content_type = head[MULTIPART_CONTENT_TYPE, 1]
|
|
75
|
-
if (name = head[MULTIPART_CONTENT_DISPOSITION, 1])
|
|
76
|
-
name = /\A"(.*)"\Z/ =~ name ? Regexp.last_match(1) : name.dup
|
|
77
|
-
name.gsub!(/\\(.)/, "\\1")
|
|
78
|
-
name
|
|
79
|
-
else
|
|
80
|
-
name = head[MULTIPART_CONTENT_ID, 1]
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
filename = HTTPX::Utils.get_filename(head)
|
|
84
|
-
|
|
85
|
-
name = filename || +"#{content_type || "text/plain"}[]" if name.nil? || name.empty?
|
|
86
|
-
|
|
87
|
-
@current = name
|
|
88
|
-
|
|
89
|
-
@parts[name] = if filename
|
|
90
|
-
FilePart.new(filename, content_type)
|
|
91
|
-
else
|
|
92
|
-
"".b
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
@state = :part_body
|
|
96
|
-
when :part_body
|
|
97
|
-
part = @parts[@current]
|
|
98
|
-
|
|
99
|
-
body_separator = if part.is_a?(FilePart)
|
|
100
|
-
"#{CRLF}#{CRLF}"
|
|
101
|
-
else
|
|
102
|
-
CRLF
|
|
103
|
-
end
|
|
104
|
-
idx = @buffer.index(body_separator)
|
|
105
|
-
|
|
106
|
-
if idx
|
|
107
|
-
payload = @buffer.byteslice(0..idx - 1)
|
|
108
|
-
@buffer = @buffer.byteslice(idx + body_separator.bytesize..-1)
|
|
109
|
-
part << payload
|
|
110
|
-
part.rewind if part.respond_to?(:rewind)
|
|
111
|
-
@state = :parse_boundary
|
|
112
|
-
else
|
|
113
|
-
part << @buffer
|
|
114
|
-
@buffer.clear
|
|
115
|
-
end
|
|
116
|
-
when :parse_boundary
|
|
117
|
-
raise Error, "payload does not start with boundary" unless @buffer.start_with?(@intermediate_boundary)
|
|
118
|
-
|
|
119
|
-
@buffer = @buffer.byteslice(@intermediate_boundary.bytesize..-1)
|
|
120
|
-
|
|
121
|
-
if @buffer == "--"
|
|
122
|
-
@buffer.clear
|
|
123
|
-
@state = :done
|
|
124
|
-
return
|
|
125
|
-
elsif @buffer.start_with?(CRLF)
|
|
126
|
-
@buffer = @buffer.byteslice(2..-1)
|
|
127
|
-
@state = :part_header
|
|
128
|
-
else
|
|
129
|
-
return
|
|
130
|
-
end
|
|
131
|
-
when :done
|
|
132
|
-
raise Error, "parsing should have been over by now"
|
|
133
|
-
end until @buffer.empty?
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
end
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module HTTPX
|
|
4
|
-
module Plugins
|
|
5
|
-
#
|
|
6
|
-
# This plugin adds support for passing `http-form_data` objects (like file objects) as "multipart/form-data";
|
|
7
|
-
#
|
|
8
|
-
# HTTPX.post(URL, form: form: { image: HTTP::FormData::File.new("path/to/file")})
|
|
9
|
-
#
|
|
10
|
-
# https://gitlab.com/os85/httpx/wikis/Multipart-Uploads
|
|
11
|
-
#
|
|
12
|
-
module Multipart
|
|
13
|
-
MULTIPART_VALUE_COND = lambda do |value|
|
|
14
|
-
value.respond_to?(:read) ||
|
|
15
|
-
(value.respond_to?(:to_hash) &&
|
|
16
|
-
value.key?(:body) &&
|
|
17
|
-
(value.key?(:filename) || value.key?(:content_type)))
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
class << self
|
|
21
|
-
def normalize_keys(key, value, &block)
|
|
22
|
-
Transcoder.normalize_keys(key, value, MULTIPART_VALUE_COND, &block)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def load_dependencies(*)
|
|
26
|
-
# :nocov:
|
|
27
|
-
begin
|
|
28
|
-
unless defined?(HTTP::FormData)
|
|
29
|
-
# in order not to break legacy code, we'll keep loading http/form_data for them.
|
|
30
|
-
require "http/form_data"
|
|
31
|
-
warn "httpx: http/form_data is no longer a requirement to use HTTPX :multipart plugin. See migration instructions under" \
|
|
32
|
-
"https://os85.gitlab.io/httpx/wiki/Multipart-Uploads.html#notes. \n\n" \
|
|
33
|
-
"If you'd like to stop seeing this message, require 'http/form_data' yourself."
|
|
34
|
-
end
|
|
35
|
-
rescue LoadError
|
|
36
|
-
end
|
|
37
|
-
# :nocov:
|
|
38
|
-
require "httpx/plugins/multipart/encoder"
|
|
39
|
-
require "httpx/plugins/multipart/decoder"
|
|
40
|
-
require "httpx/plugins/multipart/part"
|
|
41
|
-
require "httpx/plugins/multipart/mime_type_detector"
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
module RequestBodyMethods
|
|
46
|
-
private
|
|
47
|
-
|
|
48
|
-
def initialize_body(options)
|
|
49
|
-
return FormTranscoder.encode(options.form) if options.form
|
|
50
|
-
|
|
51
|
-
super
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
module ResponseMethods
|
|
56
|
-
def form
|
|
57
|
-
decode(FormTranscoder)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
module FormTranscoder
|
|
62
|
-
module_function
|
|
63
|
-
|
|
64
|
-
def encode(form)
|
|
65
|
-
if multipart?(form)
|
|
66
|
-
Encoder.new(form)
|
|
67
|
-
else
|
|
68
|
-
Transcoder::Form::Encoder.new(form)
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def decode(response)
|
|
73
|
-
content_type = response.content_type.mime_type
|
|
74
|
-
|
|
75
|
-
case content_type
|
|
76
|
-
when "application/x-www-form-urlencoded"
|
|
77
|
-
Transcoder::Form.decode(response)
|
|
78
|
-
when "multipart/form-data"
|
|
79
|
-
Decoder.new(response)
|
|
80
|
-
else
|
|
81
|
-
raise Error, "invalid form mime type (#{content_type})"
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def multipart?(data)
|
|
86
|
-
data.any? do |_, v|
|
|
87
|
-
MULTIPART_VALUE_COND.call(v) ||
|
|
88
|
-
(v.respond_to?(:to_ary) && v.to_ary.any?(&MULTIPART_VALUE_COND)) ||
|
|
89
|
-
(v.respond_to?(:to_hash) && v.to_hash.any? { |_, e| MULTIPART_VALUE_COND.call(e) })
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
register_plugin :multipart, Multipart
|
|
95
|
-
end
|
|
96
|
-
end
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
module HTTPX
|
|
2
|
-
module Plugins
|
|
3
|
-
module Authentication
|
|
4
|
-
module InstanceMethods
|
|
5
|
-
def authentication: (string token) -> instance
|
|
6
|
-
|
|
7
|
-
def bearer_auth: (string token) -> instance
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
type sessionAuthentication = Session & Authentication::InstanceMethods
|
|
12
|
-
end
|
|
13
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
module HTTPX
|
|
2
|
-
module Plugins
|
|
3
|
-
module Compression
|
|
4
|
-
module Brotli
|
|
5
|
-
def self.load_dependencies: (singleton(Session)) -> void
|
|
6
|
-
def self.configure: (singleton(Session)) -> void
|
|
7
|
-
|
|
8
|
-
def self?.deflater: () -> _Deflater
|
|
9
|
-
def self?.decoder: (Integer | Float bytesize) -> Inflater
|
|
10
|
-
|
|
11
|
-
module Deflater
|
|
12
|
-
extend _Deflater
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
class Inflater
|
|
16
|
-
include _Inflater
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
module HTTPX
|
|
2
|
-
module Plugins
|
|
3
|
-
module Compression
|
|
4
|
-
module Deflate
|
|
5
|
-
def self.load_dependencies: (singleton(Session)) -> void
|
|
6
|
-
def self.configure: (singleton(Session)) -> void
|
|
7
|
-
|
|
8
|
-
def self?.deflater: () -> _Deflater
|
|
9
|
-
def self?.inflater: (Integer | Float bytesize) -> GZIP::Inflater
|
|
10
|
-
|
|
11
|
-
module Deflater
|
|
12
|
-
extend _Deflater
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
module HTTPX
|
|
2
|
-
module Plugins
|
|
3
|
-
module Compression
|
|
4
|
-
module GZIP
|
|
5
|
-
def self.load_dependencies: (singleton(Session)) -> void
|
|
6
|
-
def self.configure: (singleton(Session)) -> void
|
|
7
|
-
|
|
8
|
-
def self?.deflater: () -> _Deflater
|
|
9
|
-
def self?.inflater: (Integer | Float bytesize) -> Inflater
|
|
10
|
-
|
|
11
|
-
class Deflater
|
|
12
|
-
include _Deflater
|
|
13
|
-
|
|
14
|
-
@compressed_chunk: String
|
|
15
|
-
|
|
16
|
-
private
|
|
17
|
-
|
|
18
|
-
def initialize: () -> untyped
|
|
19
|
-
def write: (string) -> void
|
|
20
|
-
def compressed_chunk: () -> String
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
class Inflater
|
|
24
|
-
include _Inflater
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|