http 0.8.14 → 0.9.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +3 -7
- data/Gemfile +3 -6
- data/README.md +12 -22
- data/lib/http/chainable.rb +0 -8
- data/lib/http/client.rb +9 -11
- data/lib/http/errors.rb +0 -3
- data/lib/http/options.rb +12 -27
- data/lib/http/request.rb +2 -21
- data/lib/http/response.rb +0 -6
- data/lib/http/timeout/null.rb +24 -1
- data/lib/http/timeout/per_operation.rb +8 -24
- data/lib/http/uri.rb +2 -7
- data/lib/http/version.rb +1 -1
- data/spec/lib/http/client_spec.rb +1 -31
- data/spec/lib/http/options/merge_spec.rb +0 -1
- data/spec/lib/http/request_spec.rb +2 -7
- data/spec/lib/http/response_spec.rb +0 -5
- data/spec/lib/http_spec.rb +0 -8
- data/spec/spec_helper.rb +5 -0
- data/spec/support/connection_reuse_shared.rb +2 -0
- data/spec/support/http_handling_shared.rb +7 -0
- metadata +36 -19
- data/lib/http/cache.rb +0 -146
- data/lib/http/cache/headers.rb +0 -100
- data/lib/http/cache/null_cache.rb +0 -13
- data/lib/http/request/caching.rb +0 -95
- data/lib/http/response/caching.rb +0 -143
- data/lib/http/response/io_body.rb +0 -63
- data/lib/http/response/string_body.rb +0 -53
- data/spec/lib/http/cache/headers_spec.rb +0 -77
- data/spec/lib/http/cache_spec.rb +0 -182
- data/spec/lib/http/request/caching_spec.rb +0 -133
- data/spec/lib/http/response/caching_spec.rb +0 -201
- data/spec/lib/http/response/io_body_spec.rb +0 -35
- data/spec/lib/http/response/string_body_spec.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4831838669ac11e88040de6ef9efb47f6741bc50
|
4
|
+
data.tar.gz: 816051270873fd03f7550e08623e7705332b12b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05a4d18df5d3fcf9bd97b8b721919d54dcadaccf619be8848f0a31dfb2bb5702b0e6b088cc0f020687eee53b7b3a57840e71054a4d5e3f407b01e7505da0aa03
|
7
|
+
data.tar.gz: 4ea9e0a57fd46b7ef3fae84f860c0fa2445b2f5ccca041c43548339131c8f86b8d28ba154cb92133c304cfafe3f19f3560bbb13541eb9a78c75cb435d944f031
|
data/CHANGES.md
CHANGED
@@ -1,11 +1,7 @@
|
|
1
|
-
## 0.
|
1
|
+
## 0.9.0.pre (2015-07-22)
|
2
2
|
|
3
|
-
*
|
4
|
-
|
5
|
-
|
6
|
-
## 0.8.13 (2015-08-14)
|
7
|
-
|
8
|
-
* Backport params special-chars escaping fix from `v0.9.1`. (@ixti)
|
3
|
+
* Support for caching removed. See #240. (@tarcieri)
|
4
|
+
* JRuby 9000 compatibility
|
9
5
|
|
10
6
|
|
11
7
|
## 0.8.12 (2015-05-26)
|
data/Gemfile
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
2
|
|
3
|
-
gem "jruby-openssl" if defined? JRUBY_VERSION
|
4
3
|
gem "rake"
|
5
4
|
|
6
5
|
gem "rack-cache", "~> 1.2"
|
@@ -23,17 +22,15 @@ group :test do
|
|
23
22
|
gem "coveralls"
|
24
23
|
gem "simplecov", ">= 0.9"
|
25
24
|
gem "json", ">= 1.8.1"
|
26
|
-
gem "
|
27
|
-
gem "rest-client", "~> 1.6.0", :platforms => [:jruby]
|
28
|
-
gem "rspec", "~> 3.2.0"
|
25
|
+
gem "rspec", "~> 3.0"
|
29
26
|
gem "rspec-its"
|
30
|
-
gem "rubocop"
|
27
|
+
gem "rubocop"
|
31
28
|
gem "yardstick"
|
32
29
|
gem "certificate_authority"
|
33
30
|
end
|
34
31
|
|
35
32
|
group :doc do
|
36
|
-
gem "
|
33
|
+
gem "kramdown"
|
37
34
|
gem "yard"
|
38
35
|
end
|
39
36
|
|
data/README.md
CHANGED
@@ -228,6 +228,18 @@ HTTP.accept(:json).get("https://github.com/httprb/http.rb/commit/HEAD")
|
|
228
228
|
This adds the appropriate Accept header for retrieving a JSON response for the
|
229
229
|
given resource.
|
230
230
|
|
231
|
+
### Reuse HTTP connection: HTTP Keep-Alive
|
232
|
+
|
233
|
+
If you have many successive requests against the same host, you better want to
|
234
|
+
reuse the same connection again and again:
|
235
|
+
|
236
|
+
```ruby
|
237
|
+
contents = []
|
238
|
+
targets = %w(Hypertext_Transfer_Protocol Git GitHub Linux Hurd)
|
239
|
+
HTTP.persistent('http://en.wikipedia.org').do |http|
|
240
|
+
targets.each { |target| contents << http.get("/wiki/#{target}") }
|
241
|
+
end
|
242
|
+
```
|
231
243
|
|
232
244
|
### Celluloid::IO Support
|
233
245
|
|
@@ -253,28 +265,6 @@ There's a little more to it, but that's the core idea!
|
|
253
265
|
* [Full parallel HTTP fetcher example](https://github.com/httprb/http.rb/wiki/Parallel-requests-with-Celluloid%3A%3AIO)
|
254
266
|
* See also: [Celluloid::IO](https://github.com/celluloid/celluloid-io)
|
255
267
|
|
256
|
-
### Caching
|
257
|
-
|
258
|
-
http.rb provides caching of HTTP request (per
|
259
|
-
[RFC 7234](https://tools.ietf.org/html/rfc7234)) when configured to do
|
260
|
-
so.
|
261
|
-
|
262
|
-
```ruby
|
263
|
-
require "http"
|
264
|
-
|
265
|
-
http = HTTP.cache(:metastore => "file:/var/cache/my-app-http/meta",
|
266
|
-
:entitystore => "file:/var/cache/my-app-http/entity")
|
267
|
-
|
268
|
-
http.get("http://example.com/") # makes request
|
269
|
-
http.get("http://example.com/") # skips making request and returns
|
270
|
-
# previously cached response
|
271
|
-
```
|
272
|
-
|
273
|
-
http.rb's caching is backed by
|
274
|
-
[rack-cache's excellent storage subsystem](http://rtomayko.github.io/rack-cache/storage.html). Any
|
275
|
-
storage URL supported by rack-cache is supported by http.rb's cache.
|
276
|
-
|
277
|
-
|
278
268
|
### Timeouts
|
279
269
|
|
280
270
|
By default, HTTP does not timeout on a request. You can enable per operation
|
data/lib/http/chainable.rb
CHANGED
@@ -170,14 +170,6 @@ module HTTP
|
|
170
170
|
# @see #follow
|
171
171
|
alias_method :with_follow, :follow
|
172
172
|
|
173
|
-
def cache(cache)
|
174
|
-
branch default_options.with_cache(cache)
|
175
|
-
end
|
176
|
-
|
177
|
-
# @deprecated will be removed in 1.0.0
|
178
|
-
# @see #cache
|
179
|
-
alias_method :with_cache, :cache
|
180
|
-
|
181
173
|
# Make a request with the given headers
|
182
174
|
# @param headers
|
183
175
|
def headers(headers)
|
data/lib/http/client.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require "forwardable"
|
2
2
|
|
3
|
+
require "cgi"
|
4
|
+
require "uri"
|
5
|
+
|
3
6
|
require "http/form_data"
|
4
7
|
require "http/options"
|
5
8
|
require "http/headers"
|
@@ -42,19 +45,13 @@ module HTTP
|
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
45
|
-
# Perform a single (no follow) HTTP request
|
46
|
-
def perform(req, options)
|
47
|
-
options.cache.perform(req, options) do |r, opts|
|
48
|
-
make_request(r, opts)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
48
|
# @!method persistent?
|
53
49
|
# @see Options#persistent?
|
54
50
|
# @return [Boolean] whenever client is persistent
|
55
51
|
def_delegator :default_options, :persistent?
|
56
52
|
|
57
|
-
|
53
|
+
# Perform a single (no follow) HTTP request
|
54
|
+
def perform(req, options)
|
58
55
|
verify_connection!(req.uri)
|
59
56
|
|
60
57
|
@state = :dirty
|
@@ -112,7 +109,7 @@ module HTTP
|
|
112
109
|
#
|
113
110
|
# @param [#to_s] uri
|
114
111
|
# @return [URI]
|
115
|
-
def make_request_uri(uri,
|
112
|
+
def make_request_uri(uri, options)
|
116
113
|
uri = uri.to_s
|
117
114
|
|
118
115
|
if default_options.persistent? && uri !~ HTTP_OR_HTTPS_RE
|
@@ -121,8 +118,9 @@ module HTTP
|
|
121
118
|
|
122
119
|
uri = HTTP::URI.parse uri
|
123
120
|
|
124
|
-
if
|
125
|
-
|
121
|
+
if options.params && !options.params.empty?
|
122
|
+
params = CGI.parse(uri.query.to_s).merge(options.params || {})
|
123
|
+
uri.query = ::URI.encode_www_form params
|
126
124
|
end
|
127
125
|
|
128
126
|
# Some proxies (seen on WEBRick) fail if URL has
|
data/lib/http/errors.rb
CHANGED
data/lib/http/options.rb
CHANGED
@@ -1,21 +1,16 @@
|
|
1
1
|
require "http/headers"
|
2
2
|
require "openssl"
|
3
3
|
require "socket"
|
4
|
-
require "http/cache/null_cache"
|
5
4
|
require "http/uri"
|
6
5
|
|
7
6
|
module HTTP
|
8
7
|
class Options
|
9
8
|
@default_socket_class = TCPSocket
|
10
9
|
@default_ssl_socket_class = OpenSSL::SSL::SSLSocket
|
11
|
-
|
12
|
-
@default_timeout_class = HTTP::Timeout::Null
|
13
|
-
|
14
|
-
@default_cache = Http::Cache::NullCache.new
|
10
|
+
@default_timeout_class = HTTP::Timeout::Null
|
15
11
|
|
16
12
|
class << self
|
17
|
-
attr_accessor :default_socket_class, :default_ssl_socket_class
|
18
|
-
attr_accessor :default_cache, :default_timeout_class
|
13
|
+
attr_accessor :default_socket_class, :default_ssl_socket_class, :default_timeout_class
|
19
14
|
|
20
15
|
def new(options = {})
|
21
16
|
return options if options.is_a?(self)
|
@@ -43,17 +38,16 @@ module HTTP
|
|
43
38
|
|
44
39
|
def initialize(options = {})
|
45
40
|
defaults = {
|
46
|
-
:response
|
47
|
-
:proxy
|
48
|
-
:timeout_class
|
49
|
-
:timeout_options
|
50
|
-
:socket_class
|
51
|
-
:ssl_socket_class
|
52
|
-
:ssl
|
53
|
-
:
|
54
|
-
:
|
55
|
-
:
|
56
|
-
:cookies => {}
|
41
|
+
:response => :auto,
|
42
|
+
:proxy => {},
|
43
|
+
:timeout_class => self.class.default_timeout_class,
|
44
|
+
:timeout_options => {},
|
45
|
+
:socket_class => self.class.default_socket_class,
|
46
|
+
:ssl_socket_class => self.class.default_ssl_socket_class,
|
47
|
+
:ssl => {},
|
48
|
+
:keep_alive_timeout => 5,
|
49
|
+
:headers => {},
|
50
|
+
:cookies => {}
|
57
51
|
}
|
58
52
|
|
59
53
|
opts_w_defaults = defaults.merge(options)
|
@@ -97,15 +91,6 @@ module HTTP
|
|
97
91
|
!persistent.nil?
|
98
92
|
end
|
99
93
|
|
100
|
-
def_option :cache do |cache_or_cache_options|
|
101
|
-
if cache_or_cache_options.respond_to? :perform
|
102
|
-
cache_or_cache_options
|
103
|
-
else
|
104
|
-
require "http/cache"
|
105
|
-
HTTP::Cache.new(cache_or_cache_options)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
94
|
def [](option)
|
110
95
|
send(option) rescue nil
|
111
96
|
end
|
data/lib/http/request.rb
CHANGED
@@ -4,7 +4,6 @@ require "time"
|
|
4
4
|
|
5
5
|
require "http/errors"
|
6
6
|
require "http/headers"
|
7
|
-
require "http/request/caching"
|
8
7
|
require "http/request/writer"
|
9
8
|
require "http/version"
|
10
9
|
require "http/uri"
|
@@ -67,7 +66,7 @@ module HTTP
|
|
67
66
|
# :nodoc:
|
68
67
|
def initialize(verb, uri, headers = {}, proxy = {}, body = nil, version = "1.1") # rubocop:disable ParameterLists
|
69
68
|
@verb = verb.to_s.downcase.to_sym
|
70
|
-
@uri =
|
69
|
+
@uri = HTTP::URI.parse(uri).normalize
|
71
70
|
@scheme = @uri.scheme && @uri.scheme.to_s.downcase.to_sym
|
72
71
|
|
73
72
|
fail(UnsupportedMethodError, "unknown method: #{verb}") unless METHODS.include?(@verb)
|
@@ -124,7 +123,7 @@ module HTTP
|
|
124
123
|
# Compute HTTP request header for direct or proxy request
|
125
124
|
def headline
|
126
125
|
request_uri = using_proxy? ? uri : uri.omit(:scheme, :authority)
|
127
|
-
"#{verb.to_s.upcase} #{request_uri
|
126
|
+
"#{verb.to_s.upcase} #{request_uri} HTTP/#{version}"
|
128
127
|
end
|
129
128
|
|
130
129
|
# @deprecated Will be removed in 1.0.0
|
@@ -157,11 +156,6 @@ module HTTP
|
|
157
156
|
using_proxy? ? proxy[:proxy_port] : port
|
158
157
|
end
|
159
158
|
|
160
|
-
# @return [HTTP::Request::Caching]
|
161
|
-
def caching
|
162
|
-
Caching.new self
|
163
|
-
end
|
164
|
-
|
165
159
|
private
|
166
160
|
|
167
161
|
# @!attribute [r] host
|
@@ -178,18 +172,5 @@ module HTTP
|
|
178
172
|
def default_host_header_value
|
179
173
|
PORTS[@scheme] != port ? "#{host}:#{port}" : host
|
180
174
|
end
|
181
|
-
|
182
|
-
# @return [HTTP::URI] URI with all componentes but query being normalized.
|
183
|
-
def normalize_uri(uri)
|
184
|
-
uri = HTTP::URI.parse uri
|
185
|
-
|
186
|
-
HTTP::URI.new(
|
187
|
-
:scheme => uri.normalized_scheme,
|
188
|
-
:authority => uri.normalized_authority,
|
189
|
-
:path => uri.normalized_path,
|
190
|
-
:query => uri.query,
|
191
|
-
:fragment => uri.normalized_fragment
|
192
|
-
)
|
193
|
-
end
|
194
175
|
end
|
195
176
|
end
|
data/lib/http/response.rb
CHANGED
@@ -3,7 +3,6 @@ require "forwardable"
|
|
3
3
|
require "http/headers"
|
4
4
|
require "http/content_type"
|
5
5
|
require "http/mime_type"
|
6
|
-
require "http/response/caching"
|
7
6
|
require "http/response/status"
|
8
7
|
require "http/uri"
|
9
8
|
require "http/cookie_jar"
|
@@ -115,10 +114,5 @@ module HTTP
|
|
115
114
|
def inspect
|
116
115
|
"#<#{self.class}/#{@version} #{code} #{reason} #{headers.to_h.inspect}>"
|
117
116
|
end
|
118
|
-
|
119
|
-
# @return [HTTP::Response::Caching]
|
120
|
-
def caching
|
121
|
-
Caching.new self
|
122
|
-
end
|
123
117
|
end
|
124
118
|
end
|
data/lib/http/timeout/null.rb
CHANGED
@@ -45,8 +45,31 @@ module HTTP
|
|
45
45
|
def write(data)
|
46
46
|
@socket << data
|
47
47
|
end
|
48
|
-
|
49
48
|
alias_method :<<, :write
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Retry reading
|
53
|
+
def rescue_readable
|
54
|
+
yield
|
55
|
+
rescue IO::WaitReadable
|
56
|
+
if IO.select([socket], nil, nil, read_timeout)
|
57
|
+
retry
|
58
|
+
else
|
59
|
+
raise TimeoutError, "Read timed out after #{read_timeout} seconds"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Retry writing
|
64
|
+
def rescue_writable
|
65
|
+
yield
|
66
|
+
rescue IO::WaitWritable
|
67
|
+
if IO.select(nil, [socket], nil, write_timeout)
|
68
|
+
retry
|
69
|
+
else
|
70
|
+
raise TimeoutError, "Write timed out after #{write_timeout} seconds"
|
71
|
+
end
|
72
|
+
end
|
50
73
|
end
|
51
74
|
end
|
52
75
|
end
|
@@ -22,40 +22,24 @@ module HTTP
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def connect_ssl
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
else
|
30
|
-
raise TimeoutError, "Connection timed out after #{connect_timeout} seconds"
|
31
|
-
end
|
32
|
-
rescue IO::WaitWritable
|
33
|
-
if IO.select(nil, [socket], nil, connect_timeout)
|
34
|
-
retry
|
35
|
-
else
|
36
|
-
raise TimeoutError, "Connection timed out after #{connect_timeout} seconds"
|
25
|
+
rescue_readable do
|
26
|
+
rescue_writable do
|
27
|
+
socket.connect_nonblock
|
28
|
+
end
|
37
29
|
end
|
38
30
|
end
|
39
31
|
|
40
32
|
# Read data from the socket
|
41
33
|
def readpartial(size)
|
42
|
-
|
43
|
-
|
44
|
-
if IO.select([socket], nil, nil, read_timeout)
|
45
|
-
retry
|
46
|
-
else
|
47
|
-
raise TimeoutError, "Read timed out after #{read_timeout} seconds"
|
34
|
+
rescue_readable do
|
35
|
+
socket.read_nonblock(size)
|
48
36
|
end
|
49
37
|
end
|
50
38
|
|
51
39
|
# Write data to the socket
|
52
40
|
def write(data)
|
53
|
-
|
54
|
-
|
55
|
-
if IO.select(nil, [socket], nil, write_timeout)
|
56
|
-
retry
|
57
|
-
else
|
58
|
-
raise TimeoutError, "Read timed out after #{write_timeout} seconds"
|
41
|
+
rescue_writable do
|
42
|
+
socket.write_nonblock(data)
|
59
43
|
end
|
60
44
|
end
|
61
45
|
end
|
data/lib/http/uri.rb
CHANGED
@@ -2,10 +2,10 @@ require "addressable/uri"
|
|
2
2
|
|
3
3
|
module HTTP
|
4
4
|
class URI < Addressable::URI
|
5
|
-
#
|
5
|
+
# HTTP scheme
|
6
6
|
HTTP_SCHEME = "http".freeze
|
7
7
|
|
8
|
-
#
|
8
|
+
# HTTPS scheme
|
9
9
|
HTTPS_SCHEME = "https".freeze
|
10
10
|
|
11
11
|
# @return [True] if URI is HTTP
|
@@ -19,10 +19,5 @@ module HTTP
|
|
19
19
|
def https?
|
20
20
|
HTTPS_SCHEME == scheme
|
21
21
|
end
|
22
|
-
|
23
|
-
# @return [String] human-readable representation of URI
|
24
|
-
def inspect
|
25
|
-
format("#<%s:%#0x URI:%s>", self.class, object_id, to_s)
|
26
|
-
end
|
27
22
|
end
|
28
23
|
end
|
data/lib/http/version.rb
CHANGED
@@ -4,13 +4,11 @@ require "support/http_handling_shared"
|
|
4
4
|
require "support/dummy_server"
|
5
5
|
require "support/ssl_helper"
|
6
6
|
|
7
|
-
require "http/cache"
|
8
|
-
|
9
7
|
RSpec.describe HTTP::Client do
|
10
8
|
run_server(:dummy) { DummyServer.new }
|
11
9
|
|
12
10
|
StubbedClient = Class.new(HTTP::Client) do
|
13
|
-
def
|
11
|
+
def perform(request, options)
|
14
12
|
stubs.fetch(request.uri) { super(request, options) }
|
15
13
|
end
|
16
14
|
|
@@ -97,26 +95,6 @@ RSpec.describe HTTP::Client do
|
|
97
95
|
end
|
98
96
|
end
|
99
97
|
|
100
|
-
describe "caching" do
|
101
|
-
let(:sn) { SecureRandom.urlsafe_base64(3) }
|
102
|
-
|
103
|
-
it "returns cached responses if they exist" do
|
104
|
-
cached_response = simple_response("cached").caching
|
105
|
-
StubbedClient.new(:cache =>
|
106
|
-
HTTP::Cache.new(:metastore => "heap:/", :entitystore => "heap:/")).
|
107
|
-
stub("http://example.com/#{sn}" => cached_response).
|
108
|
-
get("http://example.com/#{sn}")
|
109
|
-
|
110
|
-
# cache is now warm
|
111
|
-
|
112
|
-
client = StubbedClient.new(:cache => HTTP::Cache.new(:metastore => "heap:/", :entitystore => "heap:/")).
|
113
|
-
stub("http://example.com/#{sn}" => simple_response("OK"))
|
114
|
-
|
115
|
-
expect(client.get("http://example.com/#{sn}").body.to_s).
|
116
|
-
to eq cached_response.body.to_s
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
98
|
describe "parsing params" do
|
121
99
|
let(:client) { HTTP::Client.new }
|
122
100
|
before { allow(client).to receive :perform }
|
@@ -160,14 +138,6 @@ RSpec.describe HTTP::Client do
|
|
160
138
|
|
161
139
|
client.get("http://example.com/?a[]=b&a[]=c", :params => {:d => "e"})
|
162
140
|
end
|
163
|
-
|
164
|
-
it "properly encodes colons" do
|
165
|
-
expect(HTTP::Request).to receive(:new) do |_, uri|
|
166
|
-
expect(uri.query).to eq "t=1970-01-01T00%3A00%3A00Z"
|
167
|
-
end
|
168
|
-
|
169
|
-
client.get("http://example.com/", :params => {:t => "1970-01-01T00:00:00Z"})
|
170
|
-
end
|
171
141
|
end
|
172
142
|
|
173
143
|
describe "passing json" do
|