http 1.0.4 → 2.0.0.pre
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/.travis.yml +1 -2
- data/CHANGES.md +7 -0
- data/Gemfile +0 -2
- data/README.md +1 -3
- data/lib/http/chainable.rb +1 -1
- data/lib/http/client.rb +3 -2
- data/lib/http/connection.rb +5 -5
- data/lib/http/timeout/global.rb +6 -9
- data/lib/http/timeout/null.rb +3 -2
- data/lib/http/timeout/per_operation.rb +8 -9
- data/lib/http/uri.rb +100 -2
- data/lib/http/version.rb +1 -1
- data/spec/lib/http/uri_spec.rb +20 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 528cd808cd0cf04d196ac3459063496777a46736
|
4
|
+
data.tar.gz: a3a4cf179068d8f5c48bc803118075e5e71331d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1774996540d80f6f08866f5bee7d632baa72a33bd31122485f15fdb97d695de7645c0f9131a5e52188ef4706005c96c74bcc175ee3b5182a9a7b7b4597f07274
|
7
|
+
data.tar.gz: 9cc27b2c73fee256c61409ce41069588e780c41df32d27662eea5c1d7de116e820c8843b3e08b670a84cfbb695b64d126c1f1b6e7b43de599cb84cad91f09d73
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -151,13 +151,11 @@ In practice you'll want to bind the HTTP::Response::Body to a local variable (e.
|
|
151
151
|
This library aims to support and is [tested against][travis] the following Ruby
|
152
152
|
versions:
|
153
153
|
|
154
|
-
* Ruby 1.9.3
|
155
154
|
* Ruby 2.0.0
|
156
155
|
* Ruby 2.1.x
|
157
156
|
* Ruby 2.2.x
|
158
157
|
* Ruby 2.3.x
|
159
|
-
* JRuby
|
160
|
-
* JRuby 9000+
|
158
|
+
* JRuby 9.0.5.0
|
161
159
|
|
162
160
|
If something doesn't work on one of these versions, it's a bug.
|
163
161
|
|
data/lib/http/chainable.rb
CHANGED
data/lib/http/client.rb
CHANGED
@@ -161,8 +161,9 @@ module HTTP
|
|
161
161
|
headers[Headers::CONTENT_LENGTH] ||= form.content_length
|
162
162
|
form.to_s
|
163
163
|
when opts.json
|
164
|
-
|
165
|
-
|
164
|
+
body = MimeType[:json].encode opts.json
|
165
|
+
headers[Headers::CONTENT_TYPE] ||= "application/json; charset=#{body.encoding.name}"
|
166
|
+
body
|
166
167
|
end
|
167
168
|
end
|
168
169
|
end
|
data/lib/http/connection.rb
CHANGED
@@ -37,8 +37,8 @@ module HTTP
|
|
37
37
|
send_proxy_connect_request(req)
|
38
38
|
start_tls(req, options)
|
39
39
|
reset_timer
|
40
|
-
rescue SocketError, SystemCallError =>
|
41
|
-
raise ConnectionError, "failed to connect: #{
|
40
|
+
rescue IOError, SocketError, SystemCallError => ex
|
41
|
+
raise ConnectionError, "failed to connect: #{ex}", ex.backtrace
|
42
42
|
end
|
43
43
|
|
44
44
|
# @see (HTTP::Response::Parser#status_code)
|
@@ -94,7 +94,7 @@ module HTTP
|
|
94
94
|
def read_headers!
|
95
95
|
loop do
|
96
96
|
if read_more(BUFFER_SIZE) == :eof
|
97
|
-
fail
|
97
|
+
fail ConnectionError, "couldn't read response headers" unless @parser.headers?
|
98
98
|
break
|
99
99
|
elsif @parser.headers?
|
100
100
|
break
|
@@ -102,8 +102,6 @@ module HTTP
|
|
102
102
|
end
|
103
103
|
|
104
104
|
set_keep_alive
|
105
|
-
rescue IOError, Errno::ECONNRESET, Errno::EPIPE => e
|
106
|
-
raise ConnectionError, "failed to read headers: #{e}"
|
107
105
|
end
|
108
106
|
|
109
107
|
# Callback for when we've reached the end of a response
|
@@ -213,6 +211,8 @@ module HTTP
|
|
213
211
|
elsif value
|
214
212
|
@parser << value
|
215
213
|
end
|
214
|
+
rescue IOError, SocketError, SystemCallError => ex
|
215
|
+
raise ConnectionError, "error reading from socket: #{ex}", ex.backtrace
|
216
216
|
end
|
217
217
|
end
|
218
218
|
end
|
data/lib/http/timeout/global.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "timeout"
|
2
|
+
require "io/wait"
|
2
3
|
|
3
4
|
require "http/timeout/per_operation"
|
4
5
|
|
@@ -32,13 +33,13 @@ module HTTP
|
|
32
33
|
reset_timer
|
33
34
|
|
34
35
|
begin
|
35
|
-
socket.connect_nonblock
|
36
|
+
@socket.connect_nonblock
|
36
37
|
rescue IO::WaitReadable
|
37
|
-
IO.select([socket], nil, nil, time_left)
|
38
|
+
IO.select([@socket], nil, nil, time_left)
|
38
39
|
log_time
|
39
40
|
retry
|
40
41
|
rescue IO::WaitWritable
|
41
|
-
IO.select(nil, [socket], nil, time_left)
|
42
|
+
IO.select(nil, [@socket], nil, time_left)
|
42
43
|
log_time
|
43
44
|
retry
|
44
45
|
end
|
@@ -59,7 +60,6 @@ module HTTP
|
|
59
60
|
private
|
60
61
|
|
61
62
|
if RUBY_VERSION < "2.1.0"
|
62
|
-
|
63
63
|
def read_nonblock(size)
|
64
64
|
@socket.read_nonblock(size)
|
65
65
|
end
|
@@ -67,9 +67,7 @@ module HTTP
|
|
67
67
|
def write_nonblock(data)
|
68
68
|
@socket.write_nonblock(data)
|
69
69
|
end
|
70
|
-
|
71
70
|
else
|
72
|
-
|
73
71
|
def read_nonblock(size)
|
74
72
|
@socket.read_nonblock(size, :exception => false)
|
75
73
|
end
|
@@ -77,7 +75,6 @@ module HTTP
|
|
77
75
|
def write_nonblock(data)
|
78
76
|
@socket.write_nonblock(data, :exception => false)
|
79
77
|
end
|
80
|
-
|
81
78
|
end
|
82
79
|
|
83
80
|
# Perform the given I/O operation with the given argument
|
@@ -106,13 +103,13 @@ module HTTP
|
|
106
103
|
|
107
104
|
# Wait for a socket to become readable
|
108
105
|
def wait_readable_or_timeout
|
109
|
-
|
106
|
+
@socket.to_io.wait_readable(time_left)
|
110
107
|
log_time
|
111
108
|
end
|
112
109
|
|
113
110
|
# Wait for a socket to become writable
|
114
111
|
def wait_writable_or_timeout
|
115
|
-
|
112
|
+
@socket.to_io.wait_writable(time_left)
|
116
113
|
log_time
|
117
114
|
end
|
118
115
|
|
data/lib/http/timeout/null.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "forwardable"
|
2
|
+
require "io/wait"
|
2
3
|
|
3
4
|
module HTTP
|
4
5
|
module Timeout
|
@@ -56,7 +57,7 @@ module HTTP
|
|
56
57
|
def rescue_readable
|
57
58
|
yield
|
58
59
|
rescue IO::WaitReadable
|
59
|
-
retry if
|
60
|
+
retry if @socket.to_io.wait_readable(read_timeout)
|
60
61
|
raise TimeoutError, "Read timed out after #{read_timeout} seconds"
|
61
62
|
end
|
62
63
|
|
@@ -64,7 +65,7 @@ module HTTP
|
|
64
65
|
def rescue_writable
|
65
66
|
yield
|
66
67
|
rescue IO::WaitWritable
|
67
|
-
retry if
|
68
|
+
retry if @socket.to_io.wait_writable(write_timeout)
|
68
69
|
raise TimeoutError, "Write timed out after #{write_timeout} seconds"
|
69
70
|
end
|
70
71
|
end
|
@@ -29,7 +29,7 @@ module HTTP
|
|
29
29
|
def connect_ssl
|
30
30
|
rescue_readable do
|
31
31
|
rescue_writable do
|
32
|
-
socket.connect_nonblock
|
32
|
+
@socket.connect_nonblock
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -39,7 +39,7 @@ module HTTP
|
|
39
39
|
# Read data from the socket
|
40
40
|
def readpartial(size)
|
41
41
|
rescue_readable do
|
42
|
-
socket.read_nonblock(size)
|
42
|
+
@socket.read_nonblock(size)
|
43
43
|
end
|
44
44
|
rescue EOFError
|
45
45
|
:eof
|
@@ -48,7 +48,7 @@ module HTTP
|
|
48
48
|
# Write data to the socket
|
49
49
|
def write(data)
|
50
50
|
rescue_writable do
|
51
|
-
socket.write_nonblock(data)
|
51
|
+
@socket.write_nonblock(data)
|
52
52
|
end
|
53
53
|
rescue EOFError
|
54
54
|
:eof
|
@@ -59,14 +59,14 @@ module HTTP
|
|
59
59
|
# Read data from the socket
|
60
60
|
def readpartial(size)
|
61
61
|
loop do
|
62
|
-
result = socket.read_nonblock(size, :exception => false)
|
62
|
+
result = @socket.read_nonblock(size, :exception => false)
|
63
63
|
if result.nil?
|
64
64
|
return :eof
|
65
65
|
elsif result != :wait_readable
|
66
66
|
return result
|
67
67
|
end
|
68
68
|
|
69
|
-
unless IO.select([socket], nil, nil, read_timeout)
|
69
|
+
unless IO.select([@socket], nil, nil, read_timeout)
|
70
70
|
fail TimeoutError, "Read timed out after #{read_timeout} seconds"
|
71
71
|
end
|
72
72
|
end
|
@@ -75,16 +75,15 @@ module HTTP
|
|
75
75
|
# Write data to the socket
|
76
76
|
def write(data)
|
77
77
|
loop do
|
78
|
-
result = socket.write_nonblock(data, :exception => false)
|
78
|
+
result = @socket.write_nonblock(data, :exception => false)
|
79
79
|
return result unless result == :wait_writable
|
80
80
|
|
81
|
-
unless IO.select(nil, [socket], nil, write_timeout)
|
82
|
-
fail TimeoutError, "
|
81
|
+
unless IO.select(nil, [@socket], nil, write_timeout)
|
82
|
+
fail TimeoutError, "Write timed out after #{write_timeout} seconds"
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
86
86
|
end
|
87
|
-
# rubocop:enable Metrics/BlockNesting
|
88
87
|
end
|
89
88
|
end
|
90
89
|
end
|
data/lib/http/uri.rb
CHANGED
@@ -2,13 +2,103 @@
|
|
2
2
|
require "addressable/uri"
|
3
3
|
|
4
4
|
module HTTP
|
5
|
-
class URI
|
5
|
+
class URI
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegators :@uri, :scheme, :normalized_scheme, :scheme=
|
9
|
+
def_delegators :@uri, :user, :normalized_user, :user=
|
10
|
+
def_delegators :@uri, :password, :normalized_password, :password=
|
11
|
+
def_delegators :@uri, :host, :normalized_host, :host=
|
12
|
+
def_delegators :@uri, :authority, :normalized_authority, :authority=
|
13
|
+
def_delegators :@uri, :origin, :origin=
|
14
|
+
def_delegators :@uri, :normalized_port, :port=
|
15
|
+
def_delegators :@uri, :path, :normalized_path, :path=
|
16
|
+
def_delegators :@uri, :query, :normalized_query, :query=
|
17
|
+
def_delegators :@uri, :request_uri, :request_uri=
|
18
|
+
def_delegators :@uri, :fragment, :normalized_fragment, :fragment=
|
19
|
+
def_delegators :@uri, :omit, :join, :normalize
|
20
|
+
|
6
21
|
# @private
|
7
22
|
HTTP_SCHEME = "http".freeze
|
8
23
|
|
9
24
|
# @private
|
10
25
|
HTTPS_SCHEME = "https".freeze
|
11
26
|
|
27
|
+
# Parse the given URI string, returning an HTTP::URI object
|
28
|
+
#
|
29
|
+
# @param [HTTP::URI, String, #to_str] :uri to parse
|
30
|
+
#
|
31
|
+
# @return [HTTP::URI] new URI instance
|
32
|
+
def self.parse(uri)
|
33
|
+
return uri if uri.is_a?(self)
|
34
|
+
|
35
|
+
new(Addressable::URI.parse(uri))
|
36
|
+
end
|
37
|
+
|
38
|
+
# Encodes key/value pairs as application/x-www-form-urlencoded
|
39
|
+
#
|
40
|
+
# @param [#to_hash, #to_ary] :form_values to encode
|
41
|
+
# @param [TrueClass, FalseClass] :sort should key/value pairs be sorted first?
|
42
|
+
#
|
43
|
+
# @return [String] encoded value
|
44
|
+
def self.form_encode(form_values, sort = false)
|
45
|
+
Addressable::URI.form_encode(form_values, sort)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Creates an HTTP::URI instance from the given options
|
49
|
+
#
|
50
|
+
# @option [String, #to_str] :scheme URI scheme
|
51
|
+
# @option [String, #to_str] :user for basic authentication
|
52
|
+
# @option [String, #to_str] :password for basic authentication
|
53
|
+
# @option [String, #to_str] :host name component
|
54
|
+
# @option [String, #to_str] :port network port to connect to
|
55
|
+
# @option [String, #to_str] :path component to request
|
56
|
+
# @option [String, #to_str] :query component distinct from path
|
57
|
+
# @option [String, #to_str] :fragment component at the end of the URI
|
58
|
+
#
|
59
|
+
# @return [HTTP::URI] new URI instance
|
60
|
+
def initialize(options_or_uri = {})
|
61
|
+
case options_or_uri
|
62
|
+
when Hash
|
63
|
+
@uri = Addressable::URI.new(options_or_uri)
|
64
|
+
when Addressable::URI
|
65
|
+
@uri = options_or_uri
|
66
|
+
else fail TypeError, "expected Hash for options, got #{options_or_uri.class}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Are these URI objects equal? Normalizes both URIs prior to comparison
|
71
|
+
#
|
72
|
+
# @param [Object] :other URI to compare this one with
|
73
|
+
#
|
74
|
+
# @return [TrueClass, FalseClass] are the URIs equivalent (after normalization)?
|
75
|
+
def ==(other)
|
76
|
+
other.is_a?(URI) && normalize.to_s == other.normalize.to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
# Are these URI objects equal? Does NOT normalizes both URIs prior to comparison
|
80
|
+
#
|
81
|
+
# @param [Object] :other URI to compare this one with
|
82
|
+
#
|
83
|
+
# @return [TrueClass, FalseClass] are the URIs equivalent?
|
84
|
+
def eql?(other)
|
85
|
+
other.is_a?(URI) && to_s == other.to_s
|
86
|
+
end
|
87
|
+
|
88
|
+
# Hash value based off the normalized form of a URI
|
89
|
+
#
|
90
|
+
# @return [Integer] A hash of the URI
|
91
|
+
def hash
|
92
|
+
@hash ||= to_s.hash * -1
|
93
|
+
end
|
94
|
+
|
95
|
+
# Port number, either as specified or the default if unspecified
|
96
|
+
#
|
97
|
+
# @return [Integer] port number
|
98
|
+
def port
|
99
|
+
@uri.port || @uri.default_port
|
100
|
+
end
|
101
|
+
|
12
102
|
# @return [True] if URI is HTTP
|
13
103
|
# @return [False] otherwise
|
14
104
|
def http?
|
@@ -21,9 +111,17 @@ module HTTP
|
|
21
111
|
HTTPS_SCHEME == scheme
|
22
112
|
end
|
23
113
|
|
114
|
+
# Convert an HTTP::URI to a String
|
115
|
+
#
|
116
|
+
# @return [String] URI serialized as a String
|
117
|
+
def to_s
|
118
|
+
@uri.to_s
|
119
|
+
end
|
120
|
+
alias to_str to_s
|
121
|
+
|
24
122
|
# @return [String] human-readable representation of URI
|
25
123
|
def inspect
|
26
|
-
format("#<%s
|
124
|
+
format("#<%s:0x%014x URI:%s>", self.class.name, object_id << 1, to_s)
|
27
125
|
end
|
28
126
|
end
|
29
127
|
end
|
data/lib/http/version.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
RSpec.describe HTTP::URI do
|
2
|
+
let(:example_http_uri_string) { "http://example.com" }
|
3
|
+
let(:example_https_uri_string) { "https://example.com" }
|
4
|
+
|
5
|
+
subject(:http_uri) { described_class.parse(example_http_uri_string) }
|
6
|
+
subject(:https_uri) { described_class.parse(example_https_uri_string) }
|
7
|
+
|
8
|
+
it "knows URI schemes" do
|
9
|
+
expect(http_uri.scheme).to eq "http"
|
10
|
+
expect(https_uri.scheme).to eq "https"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "sets default ports for HTTP URIs" do
|
14
|
+
expect(http_uri.port).to eq 80
|
15
|
+
end
|
16
|
+
|
17
|
+
it "sets default ports for HTTPS URIs" do
|
18
|
+
expect(https_uri.port).to eq 443
|
19
|
+
end
|
20
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Arcieri
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2016-03
|
14
|
+
date: 2016-04-03 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: http_parser.rb
|
@@ -150,6 +150,7 @@ files:
|
|
150
150
|
- spec/lib/http/response/body_spec.rb
|
151
151
|
- spec/lib/http/response/status_spec.rb
|
152
152
|
- spec/lib/http/response_spec.rb
|
153
|
+
- spec/lib/http/uri_spec.rb
|
153
154
|
- spec/lib/http_spec.rb
|
154
155
|
- spec/regression_specs.rb
|
155
156
|
- spec/spec_helper.rb
|
@@ -177,9 +178,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
177
178
|
version: '0'
|
178
179
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
180
|
requirements:
|
180
|
-
- - "
|
181
|
+
- - ">"
|
181
182
|
- !ruby/object:Gem::Version
|
182
|
-
version:
|
183
|
+
version: 1.3.1
|
183
184
|
requirements: []
|
184
185
|
rubyforge_project:
|
185
186
|
rubygems_version: 2.5.1
|
@@ -205,6 +206,7 @@ test_files:
|
|
205
206
|
- spec/lib/http/response/body_spec.rb
|
206
207
|
- spec/lib/http/response/status_spec.rb
|
207
208
|
- spec/lib/http/response_spec.rb
|
209
|
+
- spec/lib/http/uri_spec.rb
|
208
210
|
- spec/lib/http_spec.rb
|
209
211
|
- spec/regression_specs.rb
|
210
212
|
- spec/spec_helper.rb
|