httpx 0.24.6 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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/doc/release_notes/1_0_1.md +5 -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 +52 -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
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
require "uri"
|
5
|
+
require "stringio"
|
6
|
+
require "zlib"
|
7
|
+
|
8
|
+
module HTTPX
|
9
|
+
module Transcoder
|
10
|
+
module GZIP
|
11
|
+
class Deflater < Transcoder::Deflater
|
12
|
+
def initialize(body)
|
13
|
+
@compressed_chunk = "".b
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def deflate(chunk)
|
18
|
+
@deflater ||= Zlib::GzipWriter.new(self)
|
19
|
+
|
20
|
+
if chunk.nil?
|
21
|
+
unless @deflater.closed?
|
22
|
+
@deflater.flush
|
23
|
+
@deflater.close
|
24
|
+
compressed_chunk
|
25
|
+
end
|
26
|
+
else
|
27
|
+
@deflater.write(chunk)
|
28
|
+
compressed_chunk
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def write(chunk)
|
35
|
+
@compressed_chunk << chunk
|
36
|
+
end
|
37
|
+
|
38
|
+
def compressed_chunk
|
39
|
+
@compressed_chunk.dup
|
40
|
+
ensure
|
41
|
+
@compressed_chunk.clear
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Inflater
|
46
|
+
def initialize(bytesize)
|
47
|
+
@inflater = Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
|
48
|
+
@bytesize = bytesize
|
49
|
+
end
|
50
|
+
|
51
|
+
def call(chunk)
|
52
|
+
buffer = @inflater.inflate(chunk)
|
53
|
+
@bytesize -= chunk.bytesize
|
54
|
+
if @bytesize <= 0
|
55
|
+
buffer << @inflater.finish
|
56
|
+
@inflater.close
|
57
|
+
end
|
58
|
+
buffer
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module_function
|
63
|
+
|
64
|
+
def encode(body)
|
65
|
+
Deflater.new(body)
|
66
|
+
end
|
67
|
+
|
68
|
+
def decode(response, bytesize: nil)
|
69
|
+
bytesize ||= response.headers.key?("content-length") ? response.headers["content-length"].to_i : Float::INFINITY
|
70
|
+
Inflater.new(bytesize)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -4,12 +4,10 @@ require "forwardable"
|
|
4
4
|
|
5
5
|
module HTTPX::Transcoder
|
6
6
|
module JSON
|
7
|
-
JSON_REGEX = %r{\bapplication/(?:vnd\.api\+)?json\b}i.freeze
|
8
|
-
|
9
|
-
using HTTPX::RegexpExtensions unless Regexp.method_defined?(:match?)
|
10
|
-
|
11
7
|
module_function
|
12
8
|
|
9
|
+
JSON_REGEX = %r{\bapplication/(?:vnd\.api\+)?json\b}i.freeze
|
10
|
+
|
13
11
|
class Encoder
|
14
12
|
extend Forwardable
|
15
13
|
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tempfile"
|
4
|
+
require "delegate"
|
5
|
+
|
6
|
+
module HTTPX
|
7
|
+
module Transcoder
|
8
|
+
module Multipart
|
9
|
+
class FilePart < SimpleDelegator
|
10
|
+
attr_reader :original_filename, :content_type
|
11
|
+
|
12
|
+
def initialize(filename, content_type)
|
13
|
+
@original_filename = filename
|
14
|
+
@content_type = content_type
|
15
|
+
@file = Tempfile.new("httpx", encoding: Encoding::BINARY, mode: File::RDWR)
|
16
|
+
super(@file)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Decoder
|
21
|
+
include HTTPX::Utils
|
22
|
+
|
23
|
+
CRLF = "\r\n"
|
24
|
+
BOUNDARY_RE = /;\s*boundary=([^;]+)/i.freeze
|
25
|
+
MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{CRLF}/ni.freeze
|
26
|
+
MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:.*;\s*name=(#{VALUE})/ni.freeze
|
27
|
+
MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{CRLF}]*)/ni.freeze
|
28
|
+
WINDOW_SIZE = 2 << 14
|
29
|
+
|
30
|
+
def initialize(response)
|
31
|
+
@boundary = begin
|
32
|
+
m = response.headers["content-type"].to_s[BOUNDARY_RE, 1]
|
33
|
+
raise Error, "no boundary declared in content-type header" unless m
|
34
|
+
|
35
|
+
m.strip
|
36
|
+
end
|
37
|
+
@buffer = "".b
|
38
|
+
@parts = {}
|
39
|
+
@intermediate_boundary = "--#{@boundary}"
|
40
|
+
@state = :idle
|
41
|
+
end
|
42
|
+
|
43
|
+
def call(response, *)
|
44
|
+
response.body.each do |chunk|
|
45
|
+
@buffer << chunk
|
46
|
+
|
47
|
+
parse
|
48
|
+
end
|
49
|
+
|
50
|
+
raise Error, "invalid or unsupported multipart format" unless @buffer.empty?
|
51
|
+
|
52
|
+
@parts
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def parse
|
58
|
+
case @state
|
59
|
+
when :idle
|
60
|
+
raise Error, "payload does not start with boundary" unless @buffer.start_with?("#{@intermediate_boundary}#{CRLF}")
|
61
|
+
|
62
|
+
@buffer = @buffer.byteslice(@intermediate_boundary.bytesize + 2..-1)
|
63
|
+
|
64
|
+
@state = :part_header
|
65
|
+
when :part_header
|
66
|
+
idx = @buffer.index("#{CRLF}#{CRLF}")
|
67
|
+
|
68
|
+
# raise Error, "couldn't parse part headers" unless idx
|
69
|
+
return unless idx
|
70
|
+
|
71
|
+
head = @buffer.byteslice(0..idx + 4 - 1)
|
72
|
+
|
73
|
+
@buffer = @buffer.byteslice(head.bytesize..-1)
|
74
|
+
|
75
|
+
content_type = head[MULTIPART_CONTENT_TYPE, 1]
|
76
|
+
if (name = head[MULTIPART_CONTENT_DISPOSITION, 1])
|
77
|
+
name = /\A"(.*)"\Z/ =~ name ? Regexp.last_match(1) : name.dup
|
78
|
+
name.gsub!(/\\(.)/, "\\1")
|
79
|
+
name
|
80
|
+
else
|
81
|
+
name = head[MULTIPART_CONTENT_ID, 1]
|
82
|
+
end
|
83
|
+
|
84
|
+
filename = HTTPX::Utils.get_filename(head)
|
85
|
+
|
86
|
+
name = filename || +"#{content_type || "text/plain"}[]" if name.nil? || name.empty?
|
87
|
+
|
88
|
+
@current = name
|
89
|
+
|
90
|
+
@parts[name] = if filename
|
91
|
+
FilePart.new(filename, content_type)
|
92
|
+
else
|
93
|
+
"".b
|
94
|
+
end
|
95
|
+
|
96
|
+
@state = :part_body
|
97
|
+
when :part_body
|
98
|
+
part = @parts[@current]
|
99
|
+
|
100
|
+
body_separator = if part.is_a?(FilePart)
|
101
|
+
"#{CRLF}#{CRLF}"
|
102
|
+
else
|
103
|
+
CRLF
|
104
|
+
end
|
105
|
+
idx = @buffer.index(body_separator)
|
106
|
+
|
107
|
+
if idx
|
108
|
+
payload = @buffer.byteslice(0..idx - 1)
|
109
|
+
@buffer = @buffer.byteslice(idx + body_separator.bytesize..-1)
|
110
|
+
part << payload
|
111
|
+
part.rewind if part.respond_to?(:rewind)
|
112
|
+
@state = :parse_boundary
|
113
|
+
else
|
114
|
+
part << @buffer
|
115
|
+
@buffer.clear
|
116
|
+
end
|
117
|
+
when :parse_boundary
|
118
|
+
raise Error, "payload does not start with boundary" unless @buffer.start_with?(@intermediate_boundary)
|
119
|
+
|
120
|
+
@buffer = @buffer.byteslice(@intermediate_boundary.bytesize..-1)
|
121
|
+
|
122
|
+
if @buffer == "--"
|
123
|
+
@buffer.clear
|
124
|
+
@state = :done
|
125
|
+
return
|
126
|
+
elsif @buffer.start_with?(CRLF)
|
127
|
+
@buffer = @buffer.byteslice(2..-1)
|
128
|
+
@state = :part_header
|
129
|
+
else
|
130
|
+
return
|
131
|
+
end
|
132
|
+
when :done
|
133
|
+
raise Error, "parsing should have been over by now"
|
134
|
+
end until @buffer.empty?
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module HTTPX
|
4
|
-
module Multipart
|
3
|
+
module HTTPX
|
4
|
+
module Transcoder::Multipart
|
5
5
|
class Encoder
|
6
6
|
attr_reader :bytesize
|
7
7
|
|
@@ -43,7 +43,7 @@ module HTTPX::Plugins
|
|
43
43
|
def to_parts(form)
|
44
44
|
@bytesize = 0
|
45
45
|
params = form.each_with_object([]) do |(key, val), aux|
|
46
|
-
|
46
|
+
Transcoder.normalize_keys(key, val, MULTIPART_VALUE_COND) do |k, v|
|
47
47
|
next if v.nil?
|
48
48
|
|
49
49
|
value, content_type, filename = Part.call(v)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module HTTPX
|
4
|
-
module
|
4
|
+
module Transcoder::Multipart
|
5
5
|
module Part
|
6
6
|
module_function
|
7
7
|
|
@@ -21,7 +21,8 @@ module HTTPX
|
|
21
21
|
|
22
22
|
value = value.open(File::RDONLY) if Object.const_defined?(:Pathname) && value.is_a?(Pathname)
|
23
23
|
|
24
|
-
if value.
|
24
|
+
if value.respond_to?(:path) && value.respond_to?(:read)
|
25
|
+
# either a File, a Tempfile, or something else which has to quack like a file
|
25
26
|
filename ||= File.basename(value.path)
|
26
27
|
content_type ||= MimeTypeDetector.call(value, filename) || "application/octet-stream"
|
27
28
|
[value, content_type, filename]
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "multipart/encoder"
|
4
|
+
require_relative "multipart/decoder"
|
5
|
+
require_relative "multipart/part"
|
6
|
+
require_relative "multipart/mime_type_detector"
|
7
|
+
|
8
|
+
module HTTPX::Transcoder
|
9
|
+
module Multipart
|
10
|
+
MULTIPART_VALUE_COND = lambda do |value|
|
11
|
+
value.respond_to?(:read) ||
|
12
|
+
(value.respond_to?(:to_hash) &&
|
13
|
+
value.key?(:body) &&
|
14
|
+
(value.key?(:filename) || value.key?(:content_type)))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "stringio"
|
4
|
+
|
5
|
+
module HTTPX
|
6
|
+
module Transcoder
|
7
|
+
class BodyReader
|
8
|
+
def initialize(body)
|
9
|
+
@body = if body.respond_to?(:read)
|
10
|
+
body.rewind if body.respond_to?(:rewind)
|
11
|
+
body
|
12
|
+
elsif body.respond_to?(:each)
|
13
|
+
body.enum_for(:each)
|
14
|
+
else
|
15
|
+
StringIO.new(body.to_s)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def bytesize
|
20
|
+
return @body.bytesize if @body.respond_to?(:bytesize)
|
21
|
+
|
22
|
+
Float::INFINITY
|
23
|
+
end
|
24
|
+
|
25
|
+
def read(length = nil, outbuf = nil)
|
26
|
+
return @body.read(length, outbuf) if @body.respond_to?(:read)
|
27
|
+
|
28
|
+
begin
|
29
|
+
chunk = @body.next
|
30
|
+
if outbuf
|
31
|
+
outbuf.clear.force_encoding(Encoding::BINARY)
|
32
|
+
outbuf << chunk
|
33
|
+
else
|
34
|
+
outbuf = chunk
|
35
|
+
end
|
36
|
+
outbuf unless length && outbuf.empty?
|
37
|
+
rescue StopIteration
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def close
|
42
|
+
@body.close if @body.respond_to?(:close)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
require_relative "body_reader"
|
5
|
+
|
6
|
+
module HTTPX
|
7
|
+
module Transcoder
|
8
|
+
class Deflater
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
attr_reader :content_type
|
12
|
+
|
13
|
+
def initialize(body)
|
14
|
+
@content_type = body.content_type
|
15
|
+
@body = BodyReader.new(body)
|
16
|
+
@closed = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def bytesize
|
20
|
+
buffer_deflate!
|
21
|
+
|
22
|
+
@buffer.size
|
23
|
+
end
|
24
|
+
|
25
|
+
def read(length = nil, outbuf = nil)
|
26
|
+
return @buffer.read(length, outbuf) if @buffer
|
27
|
+
|
28
|
+
return if @closed
|
29
|
+
|
30
|
+
chunk = @body.read(length)
|
31
|
+
|
32
|
+
compressed_chunk = deflate(chunk)
|
33
|
+
|
34
|
+
return unless compressed_chunk
|
35
|
+
|
36
|
+
if outbuf
|
37
|
+
outbuf.clear.force_encoding(Encoding::BINARY)
|
38
|
+
outbuf << compressed_chunk
|
39
|
+
else
|
40
|
+
compressed_chunk
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def close
|
45
|
+
return if @closed
|
46
|
+
|
47
|
+
@buffer.close if @buffer
|
48
|
+
|
49
|
+
@body.close
|
50
|
+
|
51
|
+
@closed = true
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# rubocop:disable Naming/MemoizedInstanceVariableName
|
57
|
+
def buffer_deflate!
|
58
|
+
return @buffer if defined?(@buffer)
|
59
|
+
|
60
|
+
buffer = Response::Buffer.new(
|
61
|
+
threshold_size: Options::MAX_BODY_THRESHOLD_SIZE
|
62
|
+
)
|
63
|
+
::IO.copy_stream(self, buffer)
|
64
|
+
|
65
|
+
buffer.rewind
|
66
|
+
|
67
|
+
@buffer = buffer
|
68
|
+
end
|
69
|
+
# rubocop:enable Naming/MemoizedInstanceVariableName
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/httpx/transcoder/xml.rb
CHANGED
data/lib/httpx/transcoder.rb
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
module HTTPX
|
4
4
|
module Transcoder
|
5
|
-
using RegexpExtensions unless Regexp.method_defined?(:match?)
|
6
|
-
|
7
5
|
module_function
|
8
6
|
|
9
7
|
def normalize_keys(key, value, cond = nil, &block)
|
@@ -90,3 +88,5 @@ require "httpx/transcoder/form"
|
|
90
88
|
require "httpx/transcoder/json"
|
91
89
|
require "httpx/transcoder/xml"
|
92
90
|
require "httpx/transcoder/chunker"
|
91
|
+
require "httpx/transcoder/deflate"
|
92
|
+
require "httpx/transcoder/gzip"
|
data/lib/httpx/utils.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
module HTTPX
|
4
4
|
module Utils
|
5
5
|
using URIExtensions
|
6
|
-
using HTTPX::RegexpExtensions unless Regexp.method_defined?(:match?)
|
7
6
|
|
8
7
|
TOKEN = %r{[^\s()<>,;:\\"/\[\]?=]+}.freeze
|
9
8
|
VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/.freeze
|
@@ -55,31 +54,22 @@ module HTTPX
|
|
55
54
|
filename
|
56
55
|
end
|
57
56
|
|
58
|
-
|
57
|
+
URIParser = URI::RFC2396_Parser.new
|
59
58
|
|
60
|
-
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
else
|
65
|
-
|
66
|
-
URIParser = URI::RFC2396_Parser.new
|
59
|
+
def to_uri(uri)
|
60
|
+
return URI(uri) unless uri.is_a?(String) && !uri.ascii_only?
|
67
61
|
|
68
|
-
|
69
|
-
return URI(uri) unless uri.is_a?(String) && !uri.ascii_only?
|
62
|
+
uri = URI(URIParser.escape(uri))
|
70
63
|
|
71
|
-
|
64
|
+
non_ascii_hostname = URIParser.unescape(uri.host)
|
72
65
|
|
73
|
-
|
66
|
+
non_ascii_hostname.force_encoding(Encoding::UTF_8)
|
74
67
|
|
75
|
-
|
68
|
+
idna_hostname = Punycode.encode_hostname(non_ascii_hostname)
|
76
69
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
uri.non_ascii_hostname = non_ascii_hostname
|
81
|
-
uri
|
82
|
-
end
|
70
|
+
uri.host = idna_hostname
|
71
|
+
uri.non_ascii_hostname = non_ascii_hostname
|
72
|
+
uri
|
83
73
|
end
|
84
74
|
end
|
85
75
|
end
|
data/lib/httpx/version.rb
CHANGED
data/lib/httpx.rb
CHANGED
@@ -53,14 +53,6 @@ module HTTPX
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
# :nocov:
|
57
|
-
def self.const_missing(const_name)
|
58
|
-
super unless const_name == :Client
|
59
|
-
warn "DEPRECATION WARNING: the class #{self}::Client is deprecated. Use #{self}::Session instead."
|
60
|
-
Session
|
61
|
-
end
|
62
|
-
# :nocov:
|
63
|
-
|
64
56
|
extend Chainable
|
65
57
|
end
|
66
58
|
|
data/sig/chainable.rbs
CHANGED
@@ -12,18 +12,17 @@ module HTTPX
|
|
12
12
|
def with: (options) -> Session
|
13
13
|
| (options) { (Session) -> void } -> void
|
14
14
|
|
15
|
-
def plugin: (:
|
16
|
-
| (:
|
17
|
-
| (:
|
18
|
-
| (:
|
15
|
+
def plugin: (:auth, ?options) -> Plugins::sessionAuthorization
|
16
|
+
| (:basic_auth, ?options) -> Plugins::sessionBasicAuth
|
17
|
+
| (:digest_auth, ?options) -> Plugins::sessionDigestAuth
|
18
|
+
| (:ntlm_auth, ?options) -> Plugins::sessionNTLMAuth
|
19
19
|
| (:aws_sdk_authentication, ?options) -> Plugins::sessionAwsSdkAuthentication
|
20
|
-
| (:
|
20
|
+
| (:brotli, ?options) -> Session
|
21
21
|
| (:cookies, ?options) -> Plugins::sessionCookies
|
22
22
|
| (:expect, ?options) -> Session
|
23
23
|
| (:follow_redirects, ?options) -> Plugins::sessionFollowRedirects
|
24
24
|
| (:upgrade, ?options) -> Session
|
25
25
|
| (:h2c, ?options) -> Session
|
26
|
-
| (:multipart, ?options) -> Session
|
27
26
|
| (:persistent, ?options) -> Plugins::sessionPersistent
|
28
27
|
| (:proxy, ?options) -> (Plugins::sessionProxy & Plugins::httpProxy)
|
29
28
|
| (:push_promise, ?options) -> Plugins::sessionPushPromise
|
data/sig/connection.rbs
CHANGED
data/sig/errors.rbs
CHANGED
data/sig/httpx.rbs
CHANGED
@@ -5,7 +5,8 @@ module HTTPX
|
|
5
5
|
|
6
6
|
VERSION: String
|
7
7
|
|
8
|
-
type
|
8
|
+
type http_uri = URI::HTTP | URI::HTTPS
|
9
|
+
type uri = http_uri | string
|
9
10
|
type generic_uri = String | URI::Generic
|
10
11
|
|
11
12
|
type verb = "OPTIONS" | "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "TRACE" | "CONNECT" |
|
data/sig/io/unix.rbs
CHANGED
data/sig/options.rbs
CHANGED
@@ -11,13 +11,11 @@ module HTTPX
|
|
11
11
|
SETTINGS_TIMEOUT: Integer
|
12
12
|
DEFAULT_OPTIONS: Hash[Symbol, untyped]
|
13
13
|
|
14
|
-
type timeout_type = :connect_timeout | :settings_timeout | :operation_timeout | :keep_alive_timeout | :
|
14
|
+
type timeout_type = :connect_timeout | :settings_timeout | :operation_timeout | :keep_alive_timeout | :read_timeout | :write_timeout | :request_timeout
|
15
15
|
type timeout = Hash[timeout_type, Numeric]
|
16
16
|
|
17
17
|
def self.new: (?options) -> instance
|
18
18
|
|
19
|
-
def self.def_option: (Symbol, ?String) -> void
|
20
|
-
| (Symbol) { (*nil) -> untyped } -> void
|
21
19
|
# headers
|
22
20
|
attr_reader uri: URI?
|
23
21
|
|
@@ -48,12 +46,18 @@ module HTTPX
|
|
48
46
|
# transport
|
49
47
|
attr_reader transport: "unix" | nil
|
50
48
|
|
51
|
-
# transport_options
|
52
|
-
attr_reader transport_options: Hash[untyped, untyped]?
|
53
|
-
|
54
49
|
# addresses
|
55
50
|
attr_reader addresses: Array[ipaddr]?
|
56
51
|
|
52
|
+
# supported_compression_formats
|
53
|
+
attr_reader supported_compression_formats: Array[String]
|
54
|
+
|
55
|
+
# compress_request_body
|
56
|
+
attr_reader compress_request_body: bool
|
57
|
+
|
58
|
+
# decompress_response_body
|
59
|
+
attr_reader decompress_response_body: bool
|
60
|
+
|
57
61
|
# params
|
58
62
|
attr_reader params: Transcoder::urlencoded_input?
|
59
63
|
|
@@ -124,9 +128,9 @@ module HTTPX
|
|
124
128
|
|
125
129
|
REQUEST_IVARS: Array[Symbol]
|
126
130
|
|
127
|
-
def initialize: (?options options) ->
|
131
|
+
def initialize: (?options options) -> void
|
128
132
|
|
129
|
-
def
|
133
|
+
def do_initialize: (?options options) -> void
|
130
134
|
end
|
131
135
|
|
132
136
|
type options = Options | Hash[Symbol, untyped]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module HTTPX
|
2
|
+
module Plugins
|
3
|
+
module Authorization
|
4
|
+
module InstanceMethods
|
5
|
+
def authorization: (string token) -> instance
|
6
|
+
|
7
|
+
def bearer_auth: (string token) -> instance
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
type sessionAuthorization = Session & Authorization::InstanceMethods
|
12
|
+
end
|
13
|
+
end
|
@@ -6,10 +6,10 @@ module HTTPX
|
|
6
6
|
def self.configure: (singleton(Session)) -> void
|
7
7
|
|
8
8
|
module InstanceMethods
|
9
|
-
def
|
9
|
+
def basic_auth: (string user, string password) -> instance
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
type sessionBasicAuth =
|
13
|
+
type sessionBasicAuth = sessionAuthorization & BasicAuth::InstanceMethods
|
14
14
|
end
|
15
15
|
end
|