rest-client 1.8.0-x86-mswin32 → 2.0.0.rc1-x86-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +2 -1
- data/.rubocop-disables.yml +375 -0
- data/.rubocop.yml +3 -0
- data/.travis.yml +3 -4
- data/AUTHORS +11 -1
- data/README.rdoc +84 -16
- data/Rakefile +16 -0
- data/bin/restclient +3 -5
- data/history.md +61 -0
- data/lib/restclient.rb +19 -2
- data/lib/restclient/abstract_response.rb +107 -42
- data/lib/restclient/exceptions.rb +44 -44
- data/lib/restclient/payload.rb +2 -2
- data/lib/restclient/platform.rb +19 -0
- data/lib/restclient/raw_response.rb +4 -0
- data/lib/restclient/request.rb +141 -38
- data/lib/restclient/resource.rb +3 -3
- data/lib/restclient/response.rb +61 -5
- data/lib/restclient/utils.rb +93 -0
- data/lib/restclient/version.rb +2 -1
- data/rest-client.gemspec +6 -5
- data/spec/helpers.rb +14 -0
- data/spec/integration/_lib.rb +1 -0
- data/spec/integration/httpbin_spec.rb +72 -0
- data/spec/integration/integration_spec.rb +79 -1
- data/spec/integration/request_spec.rb +24 -1
- data/spec/spec_helper.rb +21 -1
- data/spec/unit/_lib.rb +1 -0
- data/spec/unit/abstract_response_spec.rb +22 -8
- data/spec/unit/exceptions_spec.rb +9 -17
- data/spec/unit/payload_spec.rb +10 -10
- data/spec/unit/raw_response_spec.rb +1 -1
- data/spec/unit/request2_spec.rb +6 -6
- data/spec/unit/request_spec.rb +234 -43
- data/spec/unit/resource_spec.rb +1 -1
- data/spec/unit/response_spec.rb +72 -28
- data/spec/unit/restclient_spec.rb +3 -3
- data/spec/unit/utils_spec.rb +71 -0
- data/spec/unit/windows/root_certs_spec.rb +1 -1
- metadata +41 -14
data/README.rdoc
CHANGED
@@ -10,28 +10,26 @@ of specifying actions: get, put, post, delete.
|
|
10
10
|
|
11
11
|
== Requirements
|
12
12
|
|
13
|
-
MRI Ruby 1.9.
|
14
|
-
1.9
|
13
|
+
MRI Ruby 1.9.3 and newer are supported. Alternative interpreters compatible with
|
14
|
+
1.9+ should work as well.
|
15
15
|
|
16
|
-
Ruby 1.8.7
|
17
|
-
|
18
|
-
|
19
|
-
({More info is on the Ruby developers'
|
20
|
-
blog.}[http://www.ruby-lang.org/en/news/2013/06/30/we-retire-1-8-7/])
|
16
|
+
Earlier Ruby versions such as 1.8.7 and 1.9.2 are no longer supported. These
|
17
|
+
versions no longer have any official support, and do not receive security
|
18
|
+
updates.
|
21
19
|
|
22
|
-
The rest-client gem depends on these other gems for
|
20
|
+
The rest-client gem depends on these other gems for usage at runtime:
|
23
21
|
|
24
22
|
* {mime-types}[http://rubygems.org/gems/mime-types]
|
25
23
|
* {netrc}[http://rubygems.org/gems/netrc]
|
26
|
-
* {
|
24
|
+
* {http-cookie}[https://rubygems.org/gems/http-cookie]
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
There are also several development dependencies. It's recommended to use
|
27
|
+
{bundler}[http://bundler.io/] to manage these dependencies for hacking on
|
28
|
+
rest-client.
|
31
29
|
|
32
30
|
== Usage: Raw URL
|
33
31
|
|
34
|
-
require '
|
32
|
+
require 'rest-client'
|
35
33
|
|
36
34
|
RestClient.get 'http://example.com/resource'
|
37
35
|
|
@@ -67,6 +65,32 @@ dependencies for you.
|
|
67
65
|
}
|
68
66
|
})
|
69
67
|
|
68
|
+
== Passing advanced options
|
69
|
+
|
70
|
+
The top level helper methods like RestClient.get accept a headers hash as
|
71
|
+
their last argument and don't allow passing more complex options. But these
|
72
|
+
helpers are just thin wrappers around RestClient::Request.execute.
|
73
|
+
|
74
|
+
RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
|
75
|
+
timeout: 10)
|
76
|
+
|
77
|
+
You can also use this to pass a payload for HTTP verbs like DELETE, where the
|
78
|
+
RestClient.delete helper doesn't accept a payload.
|
79
|
+
|
80
|
+
RestClient::Request.execute(method: :delete, url: 'http://example.com/resource',
|
81
|
+
payload: 'foo', headers: {myheader: 'bar'})
|
82
|
+
|
83
|
+
Due to unfortunate choices in the original API, the params used to populate the
|
84
|
+
query string are actually taken out of the headers hash. So if you want to pass
|
85
|
+
both the params hash and more complex options, use the special key
|
86
|
+
<tt>:params</tt> in the headers hash. This design may change in a future major
|
87
|
+
release.
|
88
|
+
|
89
|
+
RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
|
90
|
+
timeout: 10, headers: {params: {foo: 'bar'}})
|
91
|
+
|
92
|
+
➔ GET http://example.com/resource?foo=bar
|
93
|
+
|
70
94
|
== Multipart
|
71
95
|
|
72
96
|
Yeah, that's right! This does multipart sends for you!
|
@@ -105,6 +129,7 @@ See RestClient::Resource docs for details.
|
|
105
129
|
* for result codes 301, 302 or 307, the redirection will be followed if the request is a GET or a HEAD
|
106
130
|
* for result code 303, the redirection will be followed and the request transformed into a GET
|
107
131
|
* for other cases, a RestClient::Exception holding the Response will be raised; a specific exception class will be thrown for known error codes
|
132
|
+
* call <tt>.response</tt> on the exception to get the server's response
|
108
133
|
|
109
134
|
RestClient.get 'http://example.com/resource'
|
110
135
|
➔ RestClient::ResourceNotFound: RestClient::ResourceNotFound
|
@@ -118,6 +143,34 @@ See RestClient::Resource docs for details.
|
|
118
143
|
|
119
144
|
== Result handling
|
120
145
|
|
146
|
+
The result of a RestClient::Request is a RestClient::Response object.
|
147
|
+
|
148
|
+
<b>New in 2.0:</b> RestClient::Response objects are now a subclass of String.
|
149
|
+
Previously, they were a real String object with response functionality mixed
|
150
|
+
in, which was very confusing to work with.
|
151
|
+
|
152
|
+
Response objects have several useful methods. (See the class rdoc for more details.)
|
153
|
+
|
154
|
+
* Response#code: The HTTP response code
|
155
|
+
* Response#body: The response body as a string. (AKA .to_s)
|
156
|
+
* Response#headers: A hash of HTTP response headers
|
157
|
+
* Response#cookies: A hash of HTTP cookies set by the server
|
158
|
+
* Response#cookie_jar: <em>New in 1.8</em> An HTTP::CookieJar of cookies
|
159
|
+
* Response#request: The RestClient::Request object used to make the request
|
160
|
+
* Response#history: If redirection was followed, a list of prior Response objects
|
161
|
+
|
162
|
+
>> RestClient.get('http://example.com')
|
163
|
+
=> <RestClient::Response 200 "<!doctype h...">
|
164
|
+
|
165
|
+
>> begin
|
166
|
+
>> RestClient.get('http://example.com/notfound')
|
167
|
+
>> rescue RestClient::ExceptionWithResponse => err
|
168
|
+
>> err.response
|
169
|
+
>> end
|
170
|
+
=> <RestClient::Response 404 "<!doctype h...">
|
171
|
+
|
172
|
+
=== Response callbacks
|
173
|
+
|
121
174
|
A block can be passed to the RestClient method. This block will then be called with the Response.
|
122
175
|
Response.return! can be called to invoke the default response's behavior.
|
123
176
|
|
@@ -249,6 +302,20 @@ the URL for GET, HEAD and DELETE requests, escaping the keys and values as neede
|
|
249
302
|
RestClient.get 'http://example.com/resource', :params => {:foo => 'bar', :baz => 'qux'}
|
250
303
|
# will GET http://example.com/resource?foo=bar&baz=qux
|
251
304
|
|
305
|
+
== Headers
|
306
|
+
|
307
|
+
Request headers can be set by passing a ruby hash containing keys and values
|
308
|
+
representing header names and values:
|
309
|
+
|
310
|
+
# GET request with modified headers
|
311
|
+
RestClient.get 'http://example.com/resource', {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
|
312
|
+
|
313
|
+
# POST request with modified headers
|
314
|
+
RestClient.post 'http://example.com/resource', {:foo => 'bar', :baz => 'qux'}, {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
|
315
|
+
|
316
|
+
# DELETE request with modified headers
|
317
|
+
RestClient.delete 'http://example.com/resource', {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
|
318
|
+
|
252
319
|
== Cookies
|
253
320
|
|
254
321
|
Request and Response objects know about HTTP cookies, and will automatically
|
@@ -302,15 +369,16 @@ Have a look at rest-client-components: http://github.com/crohr/rest-client-compo
|
|
302
369
|
|
303
370
|
== Credits
|
304
371
|
|
305
|
-
REST Client Team::
|
372
|
+
REST Client Team:: Andy Brody
|
306
373
|
|
307
374
|
Creator:: Adam Wiggins
|
308
375
|
|
309
|
-
|
376
|
+
Maintainers Emeriti:: Lawrence Leonard Gilbert, Matthew Manning, Julien Kirch
|
310
377
|
|
311
378
|
Major contributions:: Blake Mizerany, Julien Kirch
|
312
379
|
|
313
|
-
|
380
|
+
A great many generous folks have contributed features and patches.
|
381
|
+
See AUTHORS for the full list.
|
314
382
|
|
315
383
|
== Legal
|
316
384
|
|
data/Rakefile
CHANGED
@@ -34,6 +34,22 @@ RSpec::Core::RakeTask.new('rcov') do |t|
|
|
34
34
|
t.rcov_opts = ['--exclude', 'examples']
|
35
35
|
end
|
36
36
|
|
37
|
+
desc 'Regenerate authors file'
|
38
|
+
task :authors do
|
39
|
+
Dir.chdir(File.dirname(__FILE__)) do
|
40
|
+
File.open('AUTHORS', 'w') do |f|
|
41
|
+
f.write( <<-EOM
|
42
|
+
The Ruby REST Client would not be what it is today without the help of
|
43
|
+
the following kind souls:
|
44
|
+
|
45
|
+
EOM
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
sh 'git shortlog -s | cut -f 2 >> AUTHORS'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
37
53
|
task :default do
|
38
54
|
sh 'rake -T'
|
39
55
|
end
|
data/bin/restclient
CHANGED
@@ -56,11 +56,9 @@ if @verb
|
|
56
56
|
end
|
57
57
|
|
58
58
|
POSSIBLE_VERBS.each do |m|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
63
|
-
end_eval
|
59
|
+
define_method(m.to_sym) do |path, *args, &b|
|
60
|
+
r[path].public_send(m.to_sym, *args, &b)
|
61
|
+
end
|
64
62
|
end
|
65
63
|
|
66
64
|
def method_missing(s, * args, & b)
|
data/history.md
CHANGED
@@ -1,3 +1,64 @@
|
|
1
|
+
# 2.0.0
|
2
|
+
|
3
|
+
This release is largely API compatible, but makes several breaking changes.
|
4
|
+
|
5
|
+
- Drop support for Ruby 1.9.2
|
6
|
+
- Respect Content-Type charset header provided by server. Previously,
|
7
|
+
rest-client would not override the string encoding chosen by Net::HTTP. Now
|
8
|
+
responses that specify a charset will yield a body string in that encoding.
|
9
|
+
For example, `Content-Type: text/plain; charset=EUC-JP` will return a String
|
10
|
+
encoded with `Encoding::EUC_JP`.
|
11
|
+
- Change exceptions raised on request timeout. Instead of
|
12
|
+
RestClient::RequestTimeout (which is still used for HTTP 408), network
|
13
|
+
timeouts will now raise either RestClient::Exceptions::ReadTimeout or
|
14
|
+
RestClient::Exceptions::OpenTimeout, both of which inherit from
|
15
|
+
RestClient::Exceptions::Timeout. This class also makes the original wrapped
|
16
|
+
exception available as `#original_exception`.
|
17
|
+
- Rename `:timeout` to `:read_timeout`. When `:timeout` is passed, now set both
|
18
|
+
`:read_timeout` and `:open_timeout`.
|
19
|
+
- Change default HTTP Accept header to `*/*`
|
20
|
+
- Use a more descriptive User-Agent header by default
|
21
|
+
- Drop RC4-MD5 from default cipher list
|
22
|
+
- Only prepend http:// to URIs without a scheme
|
23
|
+
- Fix some support for using IPv6 addresses in URLs (still affected by Ruby
|
24
|
+
2.0+ bug https://bugs.ruby-lang.org/issues/9129, with the fix expected to be
|
25
|
+
backported to 2.0 and 2.1)
|
26
|
+
- `Response` objects are now a subclass of `String` rather than a `String` that
|
27
|
+
mixes in the response functionality. Most of the methods remain unchanged,
|
28
|
+
but this makes it much easier to understand what is happening when you look
|
29
|
+
at a RestClient response object. There are a few additional changes:
|
30
|
+
- Response objects now implement `.inspect` to make this distinction clearer.
|
31
|
+
- `Response#to_i` will now behave like `String#to_i` instead of returning the
|
32
|
+
HTTP response code, which was very surprising behavior.
|
33
|
+
- `Response#body` and `#to_s` will now return a true `String` object rather
|
34
|
+
than self. Previously there was no easy way to get the true `String` response
|
35
|
+
instead of the Frankenstein response string object with AbstractResponse
|
36
|
+
mixed in.
|
37
|
+
- Handle multiple HTTP response headers with the same name (except for
|
38
|
+
Set-Cookie, which is special) by joining the values with a comma space,
|
39
|
+
compliant with RFC 7230
|
40
|
+
- Don't set basic auth header if explicit `Authorization` header is specified
|
41
|
+
- Add `:proxy` option to requests, which can be used for thread-safe
|
42
|
+
per-request proxy configuration, overriding `RestClient.proxy`
|
43
|
+
- Allow overriding `ENV['http_proxy']` to disable proxies by setting
|
44
|
+
`RestClient.proxy` to a falsey value. Previously there was no way in Ruby 2.x
|
45
|
+
to turn off a proxy specified in the environment without changing `ENV`.
|
46
|
+
- Add actual support for streaming request payloads. Previously rest-client
|
47
|
+
would call `.to_s` even on RestClient::Payload::Streamed objects. Instead,
|
48
|
+
treat any object that responds to `.read` as a streaming payload and pass it
|
49
|
+
through to `.body_stream=` on the Net:HTTP object. This massively reduces the
|
50
|
+
memory required for large file uploads.
|
51
|
+
- Remove `RestClient::MaxRedirectsReached` in favor of the normal
|
52
|
+
`ExceptionWithResponse` subclasses. This makes the response accessible on the
|
53
|
+
exception object as `.response`, making it possible for callers to tell what
|
54
|
+
has actually happened when the redirect limit is reached.
|
55
|
+
- When following HTTP redirection, store a list of each previous response on
|
56
|
+
the response object as `.history`. This makes it possible to access the
|
57
|
+
original response headers and body before the redirection was followed.
|
58
|
+
- Add `:before_execution_proc` option to `RestClient::Request`. This makes it
|
59
|
+
possible to add procs like `RestClient.add_before_execution_proc` to a single
|
60
|
+
request without global state.
|
61
|
+
|
1
62
|
# 1.8.0
|
2
63
|
|
3
64
|
- Security: implement standards compliant cookie handling by adding a
|
data/lib/restclient.rb
CHANGED
@@ -7,6 +7,7 @@ require 'zlib'
|
|
7
7
|
require File.dirname(__FILE__) + '/restclient/version'
|
8
8
|
require File.dirname(__FILE__) + '/restclient/platform'
|
9
9
|
require File.dirname(__FILE__) + '/restclient/exceptions'
|
10
|
+
require File.dirname(__FILE__) + '/restclient/utils'
|
10
11
|
require File.dirname(__FILE__) + '/restclient/request'
|
11
12
|
require File.dirname(__FILE__) + '/restclient/abstract_response'
|
12
13
|
require File.dirname(__FILE__) + '/restclient/response'
|
@@ -89,8 +90,23 @@ module RestClient
|
|
89
90
|
Request.execute(:method => :options, :url => url, :headers => headers, &block)
|
90
91
|
end
|
91
92
|
|
92
|
-
|
93
|
-
|
93
|
+
# A global proxy URL to use for all requests. This can be overridden on a
|
94
|
+
# per-request basis by passing `:proxy` to RestClient::Request.
|
95
|
+
def self.proxy
|
96
|
+
@proxy
|
97
|
+
end
|
98
|
+
def self.proxy=(value)
|
99
|
+
@proxy = value
|
100
|
+
@proxy_set = true
|
101
|
+
end
|
102
|
+
|
103
|
+
# Return whether RestClient.proxy was set explicitly. We use this to
|
104
|
+
# differentiate between no value being set and a value explicitly set to nil.
|
105
|
+
#
|
106
|
+
# @return [Boolean]
|
107
|
+
#
|
108
|
+
def self.proxy_set?
|
109
|
+
!!@proxy_set
|
94
110
|
end
|
95
111
|
|
96
112
|
# Setup the log for RestClient calls.
|
@@ -150,6 +166,7 @@ module RestClient
|
|
150
166
|
# Add a Proc to be called before each request in executed.
|
151
167
|
# The proc parameters will be the http request and the request params.
|
152
168
|
def self.add_before_execution_proc &proc
|
169
|
+
raise ArgumentError.new('block is required') unless proc
|
153
170
|
@@before_execution_procs << proc
|
154
171
|
end
|
155
172
|
|
@@ -7,11 +7,19 @@ module RestClient
|
|
7
7
|
|
8
8
|
attr_reader :net_http_res, :args, :request
|
9
9
|
|
10
|
+
def inspect
|
11
|
+
raise NotImplementedError.new('must override in subclass')
|
12
|
+
end
|
13
|
+
|
10
14
|
# HTTP status code
|
11
15
|
def code
|
12
16
|
@code ||= @net_http_res.code.to_i
|
13
17
|
end
|
14
18
|
|
19
|
+
def history
|
20
|
+
@history ||= request.redirection_history || []
|
21
|
+
end
|
22
|
+
|
15
23
|
# A hash of the headers, beautified with symbols and underscores.
|
16
24
|
# e.g. "Content-type" will become :content_type.
|
17
25
|
def headers
|
@@ -27,6 +35,9 @@ module RestClient
|
|
27
35
|
@net_http_res = net_http_res
|
28
36
|
@args = args
|
29
37
|
@request = request
|
38
|
+
|
39
|
+
# prime redirection history
|
40
|
+
history
|
30
41
|
end
|
31
42
|
|
32
43
|
# Hash of cookies extracted from response headers
|
@@ -57,79 +68,133 @@ module RestClient
|
|
57
68
|
|
58
69
|
# Return the default behavior corresponding to the response code:
|
59
70
|
# the response itself for code in 200..206, redirection for 301, 302 and 307 in get and head cases, redirection for 303 and an exception in other cases
|
60
|
-
def return!
|
71
|
+
def return!(&block)
|
61
72
|
if (200..207).include? code
|
62
73
|
self
|
63
74
|
elsif [301, 302, 307].include? code
|
64
75
|
unless [:get, :head].include? args[:method]
|
65
|
-
raise
|
76
|
+
raise exception_with_response
|
66
77
|
else
|
67
|
-
follow_redirection(
|
78
|
+
follow_redirection(&block)
|
68
79
|
end
|
69
80
|
elsif code == 303
|
70
|
-
|
71
|
-
args.delete :payload
|
72
|
-
follow_redirection(request, result, & block)
|
73
|
-
elsif Exceptions::EXCEPTIONS_MAP[code]
|
74
|
-
raise Exceptions::EXCEPTIONS_MAP[code].new(self, code)
|
81
|
+
follow_get_redirection(&block)
|
75
82
|
else
|
76
|
-
raise
|
83
|
+
raise exception_with_response
|
77
84
|
end
|
78
85
|
end
|
79
86
|
|
80
87
|
def to_i
|
81
|
-
|
88
|
+
warn('warning: calling Response#to_i is not recommended')
|
89
|
+
super
|
82
90
|
end
|
83
91
|
|
84
92
|
def description
|
85
93
|
"#{code} #{STATUSES[code]} | #{(headers[:content_type] || '').gsub(/;.*$/, '')} #{size} bytes\n"
|
86
94
|
end
|
87
95
|
|
88
|
-
# Follow a redirection
|
89
|
-
|
90
|
-
|
96
|
+
# Follow a redirection response by making a new HTTP request to the
|
97
|
+
# redirection target.
|
98
|
+
def follow_redirection(&block)
|
99
|
+
_follow_redirection(@args.dup, &block)
|
100
|
+
end
|
91
101
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
new_args[:
|
97
|
-
|
98
|
-
if request.max_redirects == 0
|
99
|
-
raise MaxRedirectsReached
|
100
|
-
end
|
101
|
-
new_args[:password] = request.password
|
102
|
-
new_args[:user] = request.user
|
103
|
-
new_args[:headers] = request.headers
|
104
|
-
new_args[:max_redirects] = request.max_redirects - 1
|
105
|
-
|
106
|
-
# TODO: figure out what to do with original :cookie, :cookies values
|
107
|
-
new_args[:headers]['Cookie'] = HTTP::Cookie.cookie_value(
|
108
|
-
cookie_jar.cookies(new_args.fetch(:url)))
|
109
|
-
end
|
102
|
+
# Follow a redirection response, but change the HTTP method to GET and drop
|
103
|
+
# the payload from the original request.
|
104
|
+
def follow_get_redirection(&block)
|
105
|
+
new_args = @args.dup
|
106
|
+
new_args[:method] = :get
|
107
|
+
new_args.delete(:payload)
|
110
108
|
|
111
|
-
|
109
|
+
_follow_redirection(new_args, &block)
|
112
110
|
end
|
113
111
|
|
112
|
+
# Convert headers hash into canonical form.
|
113
|
+
#
|
114
|
+
# Header names will be converted to lowercase symbols with underscores
|
115
|
+
# instead of hyphens.
|
116
|
+
#
|
117
|
+
# Headers specified multiple times will be joined by comma and space,
|
118
|
+
# except for Set-Cookie, which will always be an array.
|
119
|
+
#
|
120
|
+
# Per RFC 2616, if a server sends multiple headers with the same key, they
|
121
|
+
# MUST be able to be joined into a single header by a comma. However,
|
122
|
+
# Set-Cookie (RFC 6265) cannot because commas are valid within cookie
|
123
|
+
# definitions. The newer RFC 7230 notes (3.2.2) that Set-Cookie should be
|
124
|
+
# handled as a special case.
|
125
|
+
#
|
126
|
+
# http://tools.ietf.org/html/rfc2616#section-4.2
|
127
|
+
# http://tools.ietf.org/html/rfc7230#section-3.2.2
|
128
|
+
# http://tools.ietf.org/html/rfc6265
|
129
|
+
#
|
130
|
+
# @param headers [Hash]
|
131
|
+
# @return [Hash]
|
132
|
+
#
|
114
133
|
def self.beautify_headers(headers)
|
115
134
|
headers.inject({}) do |out, (key, value)|
|
116
|
-
|
135
|
+
key_sym = key.gsub(/-/, '_').downcase.to_sym
|
136
|
+
|
137
|
+
# Handle Set-Cookie specially since it cannot be joined by comma.
|
138
|
+
if key.downcase == 'set-cookie'
|
139
|
+
out[key_sym] = value
|
140
|
+
else
|
141
|
+
out[key_sym] = value.join(', ')
|
142
|
+
end
|
143
|
+
|
117
144
|
out
|
118
145
|
end
|
119
146
|
end
|
120
147
|
|
121
148
|
private
|
122
149
|
|
123
|
-
#
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
150
|
+
# Follow a redirection
|
151
|
+
#
|
152
|
+
# @param new_args [Hash] Start with this hash of arguments for the
|
153
|
+
# redirection request. The hash will be mutated, so be sure to dup any
|
154
|
+
# existing hash that should not be modified.
|
155
|
+
#
|
156
|
+
def _follow_redirection(new_args, &block)
|
157
|
+
|
158
|
+
# parse location header and merge into existing URL
|
159
|
+
url = headers[:location]
|
160
|
+
|
161
|
+
# handle relative redirects
|
162
|
+
unless url.start_with?('http')
|
163
|
+
url = URI.parse(request.url).merge(url).to_s
|
164
|
+
end
|
165
|
+
new_args[:url] = url
|
166
|
+
|
167
|
+
if request.max_redirects <= 0
|
168
|
+
raise exception_with_response
|
169
|
+
end
|
170
|
+
new_args[:password] = request.password
|
171
|
+
new_args[:user] = request.user
|
172
|
+
new_args[:headers] = request.headers
|
173
|
+
new_args[:max_redirects] = request.max_redirects - 1
|
174
|
+
|
175
|
+
# TODO: figure out what to do with original :cookie, :cookies values
|
176
|
+
new_args[:headers]['Cookie'] = HTTP::Cookie.cookie_value(
|
177
|
+
cookie_jar.cookies(new_args.fetch(:url)))
|
178
|
+
|
179
|
+
|
180
|
+
# prepare new request
|
181
|
+
new_req = Request.new(new_args)
|
182
|
+
|
183
|
+
# append self to redirection history
|
184
|
+
new_req.redirection_history = history + [self]
|
185
|
+
|
186
|
+
# execute redirected request
|
187
|
+
new_req.execute(&block)
|
188
|
+
end
|
189
|
+
|
190
|
+
def exception_with_response
|
191
|
+
begin
|
192
|
+
klass = Exceptions::EXCEPTIONS_MAP.fetch(code)
|
193
|
+
rescue KeyError
|
194
|
+
raise RequestFailed.new(self, code)
|
130
195
|
end
|
131
|
-
|
196
|
+
|
197
|
+
raise klass.new(self, code)
|
132
198
|
end
|
133
199
|
end
|
134
|
-
|
135
200
|
end
|