httpx 0.0.1
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 +7 -0
- data/LICENSE.txt +191 -0
- data/README.md +119 -0
- data/lib/httpx.rb +50 -0
- data/lib/httpx/buffer.rb +34 -0
- data/lib/httpx/callbacks.rb +32 -0
- data/lib/httpx/chainable.rb +51 -0
- data/lib/httpx/channel.rb +222 -0
- data/lib/httpx/channel/http1.rb +220 -0
- data/lib/httpx/channel/http2.rb +224 -0
- data/lib/httpx/client.rb +173 -0
- data/lib/httpx/connection.rb +74 -0
- data/lib/httpx/errors.rb +7 -0
- data/lib/httpx/extensions.rb +52 -0
- data/lib/httpx/headers.rb +152 -0
- data/lib/httpx/io.rb +240 -0
- data/lib/httpx/loggable.rb +11 -0
- data/lib/httpx/options.rb +138 -0
- data/lib/httpx/plugins/authentication.rb +14 -0
- data/lib/httpx/plugins/basic_authentication.rb +20 -0
- data/lib/httpx/plugins/compression.rb +123 -0
- data/lib/httpx/plugins/compression/brotli.rb +55 -0
- data/lib/httpx/plugins/compression/deflate.rb +50 -0
- data/lib/httpx/plugins/compression/gzip.rb +59 -0
- data/lib/httpx/plugins/cookies.rb +63 -0
- data/lib/httpx/plugins/digest_authentication.rb +141 -0
- data/lib/httpx/plugins/follow_redirects.rb +72 -0
- data/lib/httpx/plugins/h2c.rb +85 -0
- data/lib/httpx/plugins/proxy.rb +108 -0
- data/lib/httpx/plugins/proxy/http.rb +115 -0
- data/lib/httpx/plugins/proxy/socks4.rb +110 -0
- data/lib/httpx/plugins/proxy/socks5.rb +152 -0
- data/lib/httpx/plugins/push_promise.rb +67 -0
- data/lib/httpx/plugins/stream.rb +33 -0
- data/lib/httpx/registry.rb +88 -0
- data/lib/httpx/request.rb +222 -0
- data/lib/httpx/response.rb +225 -0
- data/lib/httpx/selector.rb +155 -0
- data/lib/httpx/timeout.rb +68 -0
- data/lib/httpx/transcoder.rb +12 -0
- data/lib/httpx/transcoder/body.rb +56 -0
- data/lib/httpx/transcoder/chunker.rb +38 -0
- data/lib/httpx/transcoder/form.rb +41 -0
- data/lib/httpx/transcoder/json.rb +36 -0
- data/lib/httpx/version.rb +5 -0
- metadata +150 -0
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class HTTPX::Selector
|
4
|
+
#
|
5
|
+
# I/O monitor
|
6
|
+
#
|
7
|
+
class Monitor
|
8
|
+
attr_accessor :value, :interests, :readiness
|
9
|
+
|
10
|
+
def initialize(io, interests, reactor)
|
11
|
+
@io = io
|
12
|
+
@interests = interests
|
13
|
+
@reactor = reactor
|
14
|
+
@closed = false
|
15
|
+
end
|
16
|
+
|
17
|
+
def readable?
|
18
|
+
@interests == :rw || @interests == :r
|
19
|
+
end
|
20
|
+
|
21
|
+
def writable?
|
22
|
+
@interests == :rw || @interests == :w
|
23
|
+
end
|
24
|
+
|
25
|
+
# closes +@io+, deregisters from reactor (unless +deregister+ is false)
|
26
|
+
def close(deregister = true)
|
27
|
+
return if @closed
|
28
|
+
@closed = true
|
29
|
+
@reactor.deregister(@io) if deregister
|
30
|
+
end
|
31
|
+
|
32
|
+
def closed?
|
33
|
+
@closed
|
34
|
+
end
|
35
|
+
|
36
|
+
# :nocov:
|
37
|
+
def to_s
|
38
|
+
"#<#{self.class}: #{@io}(closed:#{@closed}) #{@interests} #{object_id.to_s(16)}>"
|
39
|
+
end
|
40
|
+
# :nocov:
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize
|
44
|
+
@readers = {}
|
45
|
+
@writers = {}
|
46
|
+
@lock = Mutex.new
|
47
|
+
@__r__, @__w__ = IO.pipe
|
48
|
+
@closed = false
|
49
|
+
end
|
50
|
+
|
51
|
+
def empty?
|
52
|
+
@readers.empty? && @writers.empty?
|
53
|
+
end
|
54
|
+
|
55
|
+
# deregisters +io+ from selectables.
|
56
|
+
def deregister(io)
|
57
|
+
@lock.synchronize do
|
58
|
+
rmonitor = @readers.delete(io)
|
59
|
+
wmonitor = @writers.delete(io)
|
60
|
+
monitor = rmonitor || wmonitor
|
61
|
+
monitor.close(false) if monitor
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# register +io+ for +interests+ events.
|
66
|
+
def register(io, interests)
|
67
|
+
readable = interests == :r || interests == :rw
|
68
|
+
writable = interests == :w || interests == :rw
|
69
|
+
@lock.synchronize do
|
70
|
+
if readable
|
71
|
+
monitor = @readers[io]
|
72
|
+
if monitor
|
73
|
+
monitor.interests = interests
|
74
|
+
else
|
75
|
+
monitor = Monitor.new(io, interests, self)
|
76
|
+
end
|
77
|
+
@readers[io] = monitor
|
78
|
+
@writers.delete(io) unless writable
|
79
|
+
end
|
80
|
+
if writable
|
81
|
+
monitor = @writers[io]
|
82
|
+
if monitor
|
83
|
+
monitor.interests = interests
|
84
|
+
else
|
85
|
+
# reuse object
|
86
|
+
monitor = readable ? @readers[io] : Monitor.new(io, interests, self)
|
87
|
+
end
|
88
|
+
@writers[io] = monitor
|
89
|
+
@readers.delete(io) unless readable
|
90
|
+
end
|
91
|
+
monitor
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# waits for read/write events for +interval+. Yields for monitors of
|
96
|
+
# selected IO objects.
|
97
|
+
#
|
98
|
+
def select(interval)
|
99
|
+
begin
|
100
|
+
r = nil
|
101
|
+
w = nil
|
102
|
+
@lock.synchronize do
|
103
|
+
r = @readers.keys
|
104
|
+
w = @writers.keys
|
105
|
+
end
|
106
|
+
r.unshift(@__r__)
|
107
|
+
|
108
|
+
readers, writers = IO.select(r, w, nil, interval)
|
109
|
+
|
110
|
+
raise HTTPX::TimeoutError, "timed out while waiting on select" if readers.nil? && writers.nil?
|
111
|
+
rescue IOError, SystemCallError
|
112
|
+
@lock.synchronize do
|
113
|
+
@readers.reject! { |io, _| io.closed? }
|
114
|
+
@writers.reject! { |io, _| io.closed? }
|
115
|
+
end
|
116
|
+
retry
|
117
|
+
end
|
118
|
+
|
119
|
+
readers.each do |io|
|
120
|
+
if io == @__r__
|
121
|
+
# clean up wakeups
|
122
|
+
@__r__.read(@__r__.stat.size)
|
123
|
+
else
|
124
|
+
monitor = io.closed? ? @readers.delete(io) : @readers[io]
|
125
|
+
next unless monitor
|
126
|
+
monitor.readiness = writers.delete(io) ? :rw : :r
|
127
|
+
yield monitor
|
128
|
+
end
|
129
|
+
end if readers
|
130
|
+
|
131
|
+
writers.each do |io|
|
132
|
+
monitor = io.closed? ? @writers.delete(io) : @writers[io]
|
133
|
+
next unless monitor
|
134
|
+
# don't double run this, the last iteration might have run this task already
|
135
|
+
monitor.readiness = :w
|
136
|
+
yield monitor
|
137
|
+
end if writers
|
138
|
+
end
|
139
|
+
|
140
|
+
# Closes the selector.
|
141
|
+
#
|
142
|
+
def close
|
143
|
+
return if @closed
|
144
|
+
@__r__.close
|
145
|
+
@__w__.close
|
146
|
+
rescue IOError
|
147
|
+
ensure
|
148
|
+
@closed = true
|
149
|
+
end
|
150
|
+
|
151
|
+
# interrupts the select call.
|
152
|
+
def wakeup
|
153
|
+
@__w__.write_nonblock("\0", exception: false)
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timeout"
|
4
|
+
|
5
|
+
module HTTPX
|
6
|
+
class Timeout
|
7
|
+
LOOP_TIMEOUT = 5
|
8
|
+
|
9
|
+
def self.new(opts = {})
|
10
|
+
return opts if opts.is_a?(Timeout)
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(loop_timeout: 5, total_timeout: nil)
|
15
|
+
@loop_timeout = loop_timeout
|
16
|
+
@total_timeout = total_timeout
|
17
|
+
reset_counter
|
18
|
+
end
|
19
|
+
|
20
|
+
def timeout
|
21
|
+
@loop_timeout || @total_timeout
|
22
|
+
ensure
|
23
|
+
log_time
|
24
|
+
end
|
25
|
+
|
26
|
+
def ==(other)
|
27
|
+
if other.is_a?(Timeout)
|
28
|
+
@loop_timeout == other.instance_variable_get(:@loop_timeout) &&
|
29
|
+
@total_timeout == other.instance_variable_get(:@total_timeout)
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def merge(other)
|
36
|
+
case other
|
37
|
+
when Hash
|
38
|
+
timeout = Timeout.new(other)
|
39
|
+
merge(timeout)
|
40
|
+
when Timeout
|
41
|
+
loop_timeout = other.instance_variable_get(:@loop_timeout) || @loop_timeout
|
42
|
+
total_timeout = other.instance_variable_get(:@total_timeout) || @total_timeout
|
43
|
+
Timeout.new(loop_timeout: loop_timeout, total_timeout: total_timeout)
|
44
|
+
else
|
45
|
+
raise ArgumentError, "can't merge with #{other.class}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def reset_counter
|
52
|
+
@time_left = @total_timeout
|
53
|
+
end
|
54
|
+
|
55
|
+
def reset_timer
|
56
|
+
@started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
57
|
+
end
|
58
|
+
|
59
|
+
def log_time
|
60
|
+
return unless @time_left
|
61
|
+
return reset_timer unless @started
|
62
|
+
@time_left -= (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @started)
|
63
|
+
raise TimeoutError, "Timed out after #{@total_timeout} seconds" if @time_left <= 0
|
64
|
+
|
65
|
+
reset_timer
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
|
5
|
+
module HTTPX::Transcoder
|
6
|
+
module Body
|
7
|
+
module_function
|
8
|
+
|
9
|
+
class Encoder
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
def_delegator :@raw, :to_s
|
13
|
+
|
14
|
+
def initialize(body)
|
15
|
+
@raw = body
|
16
|
+
end
|
17
|
+
|
18
|
+
def bytesize
|
19
|
+
if @raw.respond_to?(:bytesize)
|
20
|
+
@raw.bytesize
|
21
|
+
elsif @raw.respond_to?(:to_ary)
|
22
|
+
@raw.map(&:bytesize).reduce(0, :+)
|
23
|
+
elsif @raw.respond_to?(:size)
|
24
|
+
@raw.size || Float::INFINITY
|
25
|
+
elsif @raw.respond_to?(:each)
|
26
|
+
Float::INFINITY
|
27
|
+
else
|
28
|
+
raise Error, "cannot determine size of body: #{@raw.inspect}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def content_type
|
33
|
+
"application/octet-stream"
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def respond_to_missing?(meth, *args)
|
39
|
+
@raw.respond_to?(meth, *args) || super
|
40
|
+
end
|
41
|
+
|
42
|
+
def method_missing(meth, *args, &block)
|
43
|
+
if @raw.respond_to?(meth)
|
44
|
+
@raw.__send__(meth, *args, &block)
|
45
|
+
else
|
46
|
+
super
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def encode(body)
|
52
|
+
Encoder.new(body)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
register "body", Body
|
56
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
|
5
|
+
module HTTPX::Transcoder
|
6
|
+
module Chunker
|
7
|
+
module_function
|
8
|
+
|
9
|
+
class Encoder
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
def_delegator :@raw, :readpartial
|
13
|
+
|
14
|
+
CRLF = "\r\n"
|
15
|
+
|
16
|
+
def initialize(body)
|
17
|
+
@raw = body
|
18
|
+
end
|
19
|
+
|
20
|
+
def each
|
21
|
+
return enum_for(__method__) unless block_given?
|
22
|
+
@raw.each do |chunk|
|
23
|
+
yield "#{chunk.bytesize.to_s(16)}#{CRLF}#{chunk}#{CRLF}"
|
24
|
+
end
|
25
|
+
yield "0#{CRLF}#{CRLF}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def respond_to_missing?(meth, *args)
|
29
|
+
@raw.respond_to?(meth, *args) || super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def encode(chunks)
|
34
|
+
Encoder.new(chunks)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
register "chunker", Chunker
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
require "http/form_data"
|
5
|
+
|
6
|
+
module HTTPX::Transcoder
|
7
|
+
module Form
|
8
|
+
module_function
|
9
|
+
|
10
|
+
class Encoder
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
def_delegator :@raw, :content_type
|
14
|
+
|
15
|
+
def_delegator :@raw, :to_s
|
16
|
+
|
17
|
+
def_delegator :@raw, :read
|
18
|
+
|
19
|
+
def initialize(form)
|
20
|
+
@raw = HTTP::FormData.create(form)
|
21
|
+
end
|
22
|
+
|
23
|
+
def bytesize
|
24
|
+
@raw.content_length
|
25
|
+
end
|
26
|
+
|
27
|
+
def force_encoding(*args)
|
28
|
+
@raw.to_s.force_encoding(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_str
|
32
|
+
@raw.to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def encode(form)
|
37
|
+
Encoder.new(form)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
register "form", Form
|
41
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
module HTTPX::Transcoder
|
7
|
+
module JSON
|
8
|
+
module_function
|
9
|
+
|
10
|
+
class Encoder
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
def_delegator :@raw, :to_str
|
14
|
+
|
15
|
+
def_delegator :@raw, :to_s
|
16
|
+
|
17
|
+
def_delegator :@raw, :bytesize
|
18
|
+
|
19
|
+
def_delegator :@raw, :force_encoding
|
20
|
+
|
21
|
+
def initialize(json)
|
22
|
+
@raw = ::JSON.dump(json)
|
23
|
+
@charset = @raw.encoding.name.downcase
|
24
|
+
end
|
25
|
+
|
26
|
+
def content_type
|
27
|
+
"application/json; charset=#{@charset}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def encode(json)
|
32
|
+
Encoder.new(json)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
register "json", JSON
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: httpx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tiago Cardoso
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-02-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: http-2
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.9.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.9.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: http-form_data
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.0
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '3'
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.0.0
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: http_parser.rb
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.6.0
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 0.6.0
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: http-cookie
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '1.0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '1.0'
|
75
|
+
description: A client library for making HTTP requests from Ruby.
|
76
|
+
email:
|
77
|
+
- cardoso_tiago@hotmail.com
|
78
|
+
executables: []
|
79
|
+
extensions: []
|
80
|
+
extra_rdoc_files: []
|
81
|
+
files:
|
82
|
+
- LICENSE.txt
|
83
|
+
- README.md
|
84
|
+
- lib/httpx.rb
|
85
|
+
- lib/httpx/buffer.rb
|
86
|
+
- lib/httpx/callbacks.rb
|
87
|
+
- lib/httpx/chainable.rb
|
88
|
+
- lib/httpx/channel.rb
|
89
|
+
- lib/httpx/channel/http1.rb
|
90
|
+
- lib/httpx/channel/http2.rb
|
91
|
+
- lib/httpx/client.rb
|
92
|
+
- lib/httpx/connection.rb
|
93
|
+
- lib/httpx/errors.rb
|
94
|
+
- lib/httpx/extensions.rb
|
95
|
+
- lib/httpx/headers.rb
|
96
|
+
- lib/httpx/io.rb
|
97
|
+
- lib/httpx/loggable.rb
|
98
|
+
- lib/httpx/options.rb
|
99
|
+
- lib/httpx/plugins/authentication.rb
|
100
|
+
- lib/httpx/plugins/basic_authentication.rb
|
101
|
+
- lib/httpx/plugins/compression.rb
|
102
|
+
- lib/httpx/plugins/compression/brotli.rb
|
103
|
+
- lib/httpx/plugins/compression/deflate.rb
|
104
|
+
- lib/httpx/plugins/compression/gzip.rb
|
105
|
+
- lib/httpx/plugins/cookies.rb
|
106
|
+
- lib/httpx/plugins/digest_authentication.rb
|
107
|
+
- lib/httpx/plugins/follow_redirects.rb
|
108
|
+
- lib/httpx/plugins/h2c.rb
|
109
|
+
- lib/httpx/plugins/proxy.rb
|
110
|
+
- lib/httpx/plugins/proxy/http.rb
|
111
|
+
- lib/httpx/plugins/proxy/socks4.rb
|
112
|
+
- lib/httpx/plugins/proxy/socks5.rb
|
113
|
+
- lib/httpx/plugins/push_promise.rb
|
114
|
+
- lib/httpx/plugins/stream.rb
|
115
|
+
- lib/httpx/registry.rb
|
116
|
+
- lib/httpx/request.rb
|
117
|
+
- lib/httpx/response.rb
|
118
|
+
- lib/httpx/selector.rb
|
119
|
+
- lib/httpx/timeout.rb
|
120
|
+
- lib/httpx/transcoder.rb
|
121
|
+
- lib/httpx/transcoder/body.rb
|
122
|
+
- lib/httpx/transcoder/chunker.rb
|
123
|
+
- lib/httpx/transcoder/form.rb
|
124
|
+
- lib/httpx/transcoder/json.rb
|
125
|
+
- lib/httpx/version.rb
|
126
|
+
homepage: https://gitlab.com/honeyryderchuck/httpx
|
127
|
+
licenses:
|
128
|
+
- Apache 2.0
|
129
|
+
metadata: {}
|
130
|
+
post_install_message:
|
131
|
+
rdoc_options: []
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
requirements: []
|
145
|
+
rubyforge_project:
|
146
|
+
rubygems_version: 2.7.6
|
147
|
+
signing_key:
|
148
|
+
specification_version: 4
|
149
|
+
summary: HTTPX, to the future, and beyond
|
150
|
+
test_files: []
|