rest-client 1.8.0-x64-mingw32 → 2.0.0.rc1-x64-mingw32
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/.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
|