httparty 0.13.7 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of httparty might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.editorconfig +18 -0
- data/.github/workflows/ci.yml +23 -0
- data/.gitignore +2 -0
- data/.rubocop_todo.yml +1 -1
- data/{History → Changelog.md} +220 -59
- data/Gemfile +8 -3
- data/README.md +8 -7
- data/bin/httparty +3 -1
- data/docs/README.md +171 -0
- data/examples/README.md +34 -12
- data/examples/aaws.rb +7 -3
- data/examples/body_stream.rb +14 -0
- data/examples/crack.rb +1 -1
- data/examples/custom_parsers.rb +5 -1
- data/examples/delicious.rb +4 -4
- data/examples/headers_and_user_agents.rb +7 -3
- data/examples/idn.rb +10 -0
- data/examples/logging.rb +4 -4
- data/examples/microsoft_graph.rb +52 -0
- data/examples/multipart.rb +22 -0
- data/examples/peer_cert.rb +9 -0
- data/examples/stackexchange.rb +1 -1
- data/examples/stream_download.rb +26 -0
- data/examples/tripit_sign_in.rb +17 -6
- data/examples/twitter.rb +2 -2
- data/examples/whoismyrep.rb +1 -1
- data/httparty.gemspec +7 -5
- data/lib/httparty/connection_adapter.rb +86 -20
- data/lib/httparty/cookie_hash.rb +10 -8
- data/lib/httparty/decompressor.rb +92 -0
- data/lib/httparty/exceptions.rb +8 -2
- data/lib/httparty/hash_conversions.rb +30 -8
- data/lib/httparty/headers_processor.rb +32 -0
- data/lib/httparty/logger/apache_formatter.rb +31 -6
- data/lib/httparty/logger/curl_formatter.rb +68 -23
- data/lib/httparty/logger/logger.rb +5 -1
- data/lib/httparty/logger/logstash_formatter.rb +61 -0
- data/lib/httparty/module_inheritable_attributes.rb +6 -4
- data/lib/httparty/net_digest_auth.rb +23 -21
- data/lib/httparty/parser.rb +25 -14
- data/lib/httparty/request/body.rb +98 -0
- data/lib/httparty/request/multipart_boundary.rb +13 -0
- data/lib/httparty/request.rb +156 -106
- data/lib/httparty/response/headers.rb +23 -19
- data/lib/httparty/response.rb +92 -13
- data/lib/httparty/response_fragment.rb +21 -0
- data/lib/httparty/text_encoder.rb +72 -0
- data/lib/httparty/utils.rb +13 -0
- data/lib/httparty/version.rb +3 -1
- data/lib/httparty.rb +98 -34
- data/website/css/common.css +1 -1
- metadata +34 -113
- data/.travis.yml +0 -7
- data/features/basic_authentication.feature +0 -20
- data/features/command_line.feature +0 -95
- data/features/deals_with_http_error_codes.feature +0 -26
- data/features/digest_authentication.feature +0 -30
- data/features/handles_compressed_responses.feature +0 -27
- data/features/handles_multiple_formats.feature +0 -57
- data/features/steps/env.rb +0 -27
- data/features/steps/httparty_response_steps.rb +0 -52
- data/features/steps/httparty_steps.rb +0 -43
- data/features/steps/mongrel_helper.rb +0 -127
- data/features/steps/remote_service_steps.rb +0 -90
- data/features/supports_read_timeout_option.feature +0 -13
- data/features/supports_redirection.feature +0 -22
- data/features/supports_timeout_option.feature +0 -13
- data/spec/fixtures/delicious.xml +0 -23
- data/spec/fixtures/empty.xml +0 -0
- data/spec/fixtures/google.html +0 -3
- data/spec/fixtures/ssl/generate.sh +0 -29
- data/spec/fixtures/ssl/generated/1fe462c2.0 +0 -16
- data/spec/fixtures/ssl/generated/bogushost.crt +0 -13
- data/spec/fixtures/ssl/generated/ca.crt +0 -16
- data/spec/fixtures/ssl/generated/ca.key +0 -15
- data/spec/fixtures/ssl/generated/selfsigned.crt +0 -14
- data/spec/fixtures/ssl/generated/server.crt +0 -13
- data/spec/fixtures/ssl/generated/server.key +0 -15
- data/spec/fixtures/ssl/openssl-exts.cnf +0 -9
- data/spec/fixtures/twitter.csv +0 -2
- data/spec/fixtures/twitter.json +0 -1
- data/spec/fixtures/twitter.xml +0 -403
- data/spec/fixtures/undefined_method_add_node_for_nil.xml +0 -2
- data/spec/httparty/connection_adapter_spec.rb +0 -468
- data/spec/httparty/cookie_hash_spec.rb +0 -83
- data/spec/httparty/exception_spec.rb +0 -38
- data/spec/httparty/hash_conversions_spec.rb +0 -41
- data/spec/httparty/logger/apache_formatter_spec.rb +0 -41
- data/spec/httparty/logger/curl_formatter_spec.rb +0 -18
- data/spec/httparty/logger/logger_spec.rb +0 -38
- data/spec/httparty/net_digest_auth_spec.rb +0 -230
- data/spec/httparty/parser_spec.rb +0 -173
- data/spec/httparty/request_spec.rb +0 -1073
- data/spec/httparty/response_spec.rb +0 -241
- data/spec/httparty/ssl_spec.rb +0 -74
- data/spec/httparty_spec.rb +0 -850
- data/spec/spec_helper.rb +0 -59
- data/spec/support/ssl_test_helper.rb +0 -47
- data/spec/support/ssl_test_server.rb +0 -80
- data/spec/support/stub_response.rb +0 -49
@@ -1,1073 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
-
|
3
|
-
RSpec.describe HTTParty::Request do
|
4
|
-
before do
|
5
|
-
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', format: :xml)
|
6
|
-
end
|
7
|
-
|
8
|
-
describe "::NON_RAILS_QUERY_STRING_NORMALIZER" do
|
9
|
-
let(:normalizer) { HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER }
|
10
|
-
|
11
|
-
it "doesn't modify strings" do
|
12
|
-
query_string = normalizer["foo=bar&foo=baz"]
|
13
|
-
expect(CGI.unescape(query_string)).to eq("foo=bar&foo=baz")
|
14
|
-
end
|
15
|
-
|
16
|
-
context "when the query is an array" do
|
17
|
-
it "doesn't include brackets" do
|
18
|
-
query_string = normalizer[{page: 1, foo: %w(bar baz)}]
|
19
|
-
expect(CGI.unescape(query_string)).to eq("foo=bar&foo=baz&page=1")
|
20
|
-
end
|
21
|
-
|
22
|
-
it "URI encodes array values" do
|
23
|
-
query_string = normalizer[{people: ["Otis Redding", "Bob Marley", "Tim & Jon"], page: 1, xyzzy: 3}]
|
24
|
-
expect(query_string).to eq("page=1&people=Otis%20Redding&people=Bob%20Marley&people=Tim%20%26%20Jon&xyzzy=3")
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context "when the query is a hash" do
|
29
|
-
it "correctly handles nil values" do
|
30
|
-
query_string = normalizer[{page: 1, per_page: nil}]
|
31
|
-
expect(query_string).to eq("page=1&per_page")
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "initialization" do
|
37
|
-
it "sets parser to HTTParty::Parser" do
|
38
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com')
|
39
|
-
expect(request.parser).to eq(HTTParty::Parser)
|
40
|
-
end
|
41
|
-
|
42
|
-
it "sets parser to the optional parser" do
|
43
|
-
my_parser = lambda {}
|
44
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', parser: my_parser)
|
45
|
-
expect(request.parser).to eq(my_parser)
|
46
|
-
end
|
47
|
-
|
48
|
-
it "sets connection_adapter to HTTPParty::ConnectionAdapter" do
|
49
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com')
|
50
|
-
expect(request.connection_adapter).to eq(HTTParty::ConnectionAdapter)
|
51
|
-
end
|
52
|
-
|
53
|
-
it "sets connection_adapter to the optional connection_adapter" do
|
54
|
-
my_adapter = lambda {}
|
55
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', connection_adapter: my_adapter)
|
56
|
-
expect(request.connection_adapter).to eq(my_adapter)
|
57
|
-
end
|
58
|
-
|
59
|
-
context "when basic authentication credentials provided in uri" do
|
60
|
-
context "when basic auth options wasn't set explicitly" do
|
61
|
-
it "sets basic auth from uri" do
|
62
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://user1:pass1@example.com')
|
63
|
-
expect(request.options[:basic_auth]).to eq({username: 'user1', password: 'pass1'})
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
context "when basic auth options was set explicitly" do
|
68
|
-
it "uses basic auth from url anyway" do
|
69
|
-
basic_auth = {username: 'user2', password: 'pass2'}
|
70
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://user1:pass1@example.com', basic_auth: basic_auth)
|
71
|
-
expect(request.options[:basic_auth]).to eq({username: 'user1', password: 'pass1'})
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
describe "#format" do
|
78
|
-
context "request yet to be made" do
|
79
|
-
it "returns format option" do
|
80
|
-
request = HTTParty::Request.new 'get', '/', format: :xml
|
81
|
-
expect(request.format).to eq(:xml)
|
82
|
-
end
|
83
|
-
|
84
|
-
it "returns nil format" do
|
85
|
-
request = HTTParty::Request.new 'get', '/'
|
86
|
-
expect(request.format).to be_nil
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
context "request has been made" do
|
91
|
-
it "returns format option" do
|
92
|
-
request = HTTParty::Request.new 'get', '/', format: :xml
|
93
|
-
request.last_response = double
|
94
|
-
expect(request.format).to eq(:xml)
|
95
|
-
end
|
96
|
-
|
97
|
-
it "returns the content-type from the last response when the option is not set" do
|
98
|
-
request = HTTParty::Request.new 'get', '/'
|
99
|
-
response = double
|
100
|
-
expect(response).to receive(:[]).with('content-type').and_return('text/json')
|
101
|
-
request.last_response = response
|
102
|
-
expect(request.format).to eq(:json)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
context "options" do
|
108
|
-
it "should use basic auth when configured" do
|
109
|
-
@request.options[:basic_auth] = {username: 'foobar', password: 'secret'}
|
110
|
-
@request.send(:setup_raw_request)
|
111
|
-
expect(@request.instance_variable_get(:@raw_request)['authorization']).not_to be_nil
|
112
|
-
end
|
113
|
-
|
114
|
-
it "should use digest auth when configured" do
|
115
|
-
FakeWeb.register_uri(:get, "http://api.foo.com/v1",
|
116
|
-
www_authenticate: 'Digest realm="Log Viewer", qop="auth", nonce="2CA0EC6B0E126C4800E56BA0C0003D3C", opaque="5ccc069c403ebaf9f0171e9517f40e41", stale=false')
|
117
|
-
|
118
|
-
@request.options[:digest_auth] = {username: 'foobar', password: 'secret'}
|
119
|
-
@request.send(:setup_raw_request)
|
120
|
-
|
121
|
-
raw_request = @request.instance_variable_get(:@raw_request)
|
122
|
-
expect(raw_request.instance_variable_get(:@header)['Authorization']).not_to be_nil
|
123
|
-
end
|
124
|
-
|
125
|
-
it "should use the right http method for digest authentication" do
|
126
|
-
@post_request = HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', format: :xml)
|
127
|
-
FakeWeb.register_uri(:post, "http://api.foo.com/v1", {})
|
128
|
-
|
129
|
-
http = @post_request.send(:http)
|
130
|
-
expect(@post_request).to receive(:http).and_return(http)
|
131
|
-
expect(http).not_to receive(:head).with({'www-authenticate' => nil})
|
132
|
-
@post_request.options[:digest_auth] = {username: 'foobar', password: 'secret'}
|
133
|
-
@post_request.send(:setup_raw_request)
|
134
|
-
end
|
135
|
-
|
136
|
-
it 'should maintain cookies returned from setup_digest_auth' do
|
137
|
-
FakeWeb.register_uri(
|
138
|
-
:get, "http://api.foo.com/v1",
|
139
|
-
set_cookie: 'custom-cookie=1234567',
|
140
|
-
www_authenticate: 'Digest realm="Log Viewer", qop="auth", nonce="2CA0EC6B0E126C4800E56BA0C0003D3C", opaque="5ccc069c403ebaf9f0171e9517f40e41", stale=false'
|
141
|
-
)
|
142
|
-
|
143
|
-
@request.options[:digest_auth] = {username: 'foobar', password: 'secret'}
|
144
|
-
@request.send(:setup_raw_request)
|
145
|
-
|
146
|
-
raw_request = @request.instance_variable_get(:@raw_request)
|
147
|
-
expect(raw_request.instance_variable_get(:@header)['cookie']).to eql ["custom-cookie=1234567"]
|
148
|
-
end
|
149
|
-
|
150
|
-
it 'should merge cookies from setup_digest_auth and request' do
|
151
|
-
FakeWeb.register_uri(
|
152
|
-
:get, "http://api.foo.com/v1",
|
153
|
-
set_cookie: 'custom-cookie=1234567',
|
154
|
-
www_authenticate: 'Digest realm="Log Viewer", qop="auth", nonce="2CA0EC6B0E126C4800E56BA0C0003D3C", opaque="5ccc069c403ebaf9f0171e9517f40e41", stale=false'
|
155
|
-
)
|
156
|
-
|
157
|
-
@request.options[:digest_auth] = {username: 'foobar', password: 'secret'}
|
158
|
-
@request.options[:headers] = {'cookie' => 'request-cookie=test'}
|
159
|
-
@request.send(:setup_raw_request)
|
160
|
-
|
161
|
-
raw_request = @request.instance_variable_get(:@raw_request)
|
162
|
-
expect(raw_request.instance_variable_get(:@header)['cookie']).to eql ['request-cookie=test', 'custom-cookie=1234567']
|
163
|
-
end
|
164
|
-
|
165
|
-
it 'should use body_stream when configured' do
|
166
|
-
stream = StringIO.new('foo')
|
167
|
-
request = HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', body_stream: stream)
|
168
|
-
request.send(:setup_raw_request)
|
169
|
-
expect(request.instance_variable_get(:@raw_request).body_stream).to eq(stream)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
describe "#uri" do
|
174
|
-
context "redirects" do
|
175
|
-
it "returns correct path when the server sets the location header to a filename" do
|
176
|
-
@request.last_uri = URI.parse("http://example.com/foo/bar")
|
177
|
-
@request.path = URI.parse("bar?foo=bar")
|
178
|
-
@request.redirect = true
|
179
|
-
|
180
|
-
expect(@request.uri).to eq(URI.parse("http://example.com/foo/bar?foo=bar"))
|
181
|
-
end
|
182
|
-
|
183
|
-
context "location header is an absolute path" do
|
184
|
-
it "returns correct path when location has leading slash" do
|
185
|
-
@request.last_uri = URI.parse("http://example.com/foo/bar")
|
186
|
-
@request.path = URI.parse("/bar?foo=bar")
|
187
|
-
@request.redirect = true
|
188
|
-
|
189
|
-
expect(@request.uri).to eq(URI.parse("http://example.com/bar?foo=bar"))
|
190
|
-
end
|
191
|
-
|
192
|
-
it "returns the correct path when location has no leading slash" do
|
193
|
-
@request.last_uri = URI.parse("http://example.com")
|
194
|
-
@request.path = URI.parse("bar/")
|
195
|
-
@request.redirect = true
|
196
|
-
|
197
|
-
expect(@request.uri).to eq(URI.parse("http://example.com/bar/"))
|
198
|
-
end
|
199
|
-
end
|
200
|
-
it "returns correct path when the server sets the location header to a full uri" do
|
201
|
-
@request.last_uri = URI.parse("http://example.com/foo/bar")
|
202
|
-
@request.path = URI.parse("http://example.com/bar?foo=bar")
|
203
|
-
@request.redirect = true
|
204
|
-
|
205
|
-
expect(@request.uri).to eq(URI.parse("http://example.com/bar?foo=bar"))
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
context "query strings" do
|
210
|
-
it "does not add an empty query string when default_params are blank" do
|
211
|
-
@request.options[:default_params] = {}
|
212
|
-
expect(@request.uri.query).to be_nil
|
213
|
-
end
|
214
|
-
|
215
|
-
it "respects the query string normalization proc" do
|
216
|
-
empty_proc = lambda {|qs| ""}
|
217
|
-
@request.options[:query_string_normalizer] = empty_proc
|
218
|
-
@request.options[:query] = {foo: :bar}
|
219
|
-
expect(CGI.unescape(@request.uri.query)).to eq("")
|
220
|
-
end
|
221
|
-
|
222
|
-
it "does not append an ampersand when queries are embedded in paths" do
|
223
|
-
@request.path = "/path?a=1"
|
224
|
-
@request.options[:query] = {}
|
225
|
-
expect(@request.uri.query).to eq("a=1")
|
226
|
-
end
|
227
|
-
|
228
|
-
it "does not duplicate query string parameters when uri is called twice" do
|
229
|
-
@request.options[:query] = {foo: :bar}
|
230
|
-
@request.uri
|
231
|
-
expect(@request.uri.query).to eq("foo=bar")
|
232
|
-
end
|
233
|
-
|
234
|
-
context "when representing an array" do
|
235
|
-
it "returns a Rails style query string" do
|
236
|
-
@request.options[:query] = {foo: %w(bar baz)}
|
237
|
-
expect(CGI.unescape(@request.uri.query)).to eq("foo[]=bar&foo[]=baz")
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
describe "#setup_raw_request" do
|
244
|
-
context "when query_string_normalizer is set" do
|
245
|
-
it "sets the body to the return value of the proc" do
|
246
|
-
@request.options[:query_string_normalizer] = HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER
|
247
|
-
@request.options[:body] = {page: 1, foo: %w(bar baz)}
|
248
|
-
@request.send(:setup_raw_request)
|
249
|
-
body = @request.instance_variable_get(:@raw_request).body
|
250
|
-
expect(CGI.unescape(body)).to eq("foo=bar&foo=baz&page=1")
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
describe 'http' do
|
256
|
-
it "should get a connection from the connection_adapter" do
|
257
|
-
http = Net::HTTP.new('google.com')
|
258
|
-
adapter = double('adapter')
|
259
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'https://api.foo.com/v1:443', connection_adapter: adapter)
|
260
|
-
expect(adapter).to receive(:call).with(request.uri, request.options).and_return(http)
|
261
|
-
expect(request.send(:http)).to be http
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
describe '#format_from_mimetype' do
|
266
|
-
it 'should handle text/xml' do
|
267
|
-
["text/xml", "text/xml; charset=iso8859-1"].each do |ct|
|
268
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:xml)
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
it 'should handle application/xml' do
|
273
|
-
["application/xml", "application/xml; charset=iso8859-1"].each do |ct|
|
274
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:xml)
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
it 'should handle text/json' do
|
279
|
-
["text/json", "text/json; charset=iso8859-1"].each do |ct|
|
280
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:json)
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
it 'should handle application/json' do
|
285
|
-
["application/json", "application/json; charset=iso8859-1"].each do |ct|
|
286
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:json)
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
it 'should handle text/csv' do
|
291
|
-
["text/csv", "text/csv; charset=iso8859-1"].each do |ct|
|
292
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:csv)
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
it 'should handle application/csv' do
|
297
|
-
["application/csv", "application/csv; charset=iso8859-1"].each do |ct|
|
298
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:csv)
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
it 'should handle text/comma-separated-values' do
|
303
|
-
["text/comma-separated-values", "text/comma-separated-values; charset=iso8859-1"].each do |ct|
|
304
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:csv)
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
it 'should handle text/javascript' do
|
309
|
-
["text/javascript", "text/javascript; charset=iso8859-1"].each do |ct|
|
310
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:plain)
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
it 'should handle application/javascript' do
|
315
|
-
["application/javascript", "application/javascript; charset=iso8859-1"].each do |ct|
|
316
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:plain)
|
317
|
-
end
|
318
|
-
end
|
319
|
-
|
320
|
-
it "returns nil for an unrecognized mimetype" do
|
321
|
-
expect(@request.send(:format_from_mimetype, "application/atom+xml")).to be_nil
|
322
|
-
end
|
323
|
-
|
324
|
-
it "returns nil when using a default parser" do
|
325
|
-
@request.options[:parser] = lambda {}
|
326
|
-
expect(@request.send(:format_from_mimetype, "text/json")).to be_nil
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
describe 'parsing responses' do
|
331
|
-
it 'should handle xml automatically' do
|
332
|
-
xml = '<books><book><id>1234</id><name>Foo Bar!</name></book></books>'
|
333
|
-
@request.options[:format] = :xml
|
334
|
-
expect(@request.send(:parse_response, xml)).to eq({'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}})
|
335
|
-
end
|
336
|
-
|
337
|
-
it 'should handle csv automatically' do
|
338
|
-
csv = ['"id","Name"', '"1234","Foo Bar!"'].join("\n")
|
339
|
-
@request.options[:format] = :csv
|
340
|
-
expect(@request.send(:parse_response, csv)).to eq([%w(id Name), ["1234", "Foo Bar!"]])
|
341
|
-
end
|
342
|
-
|
343
|
-
it 'should handle json automatically' do
|
344
|
-
json = '{"books": {"book": {"name": "Foo Bar!", "id": "1234"}}}'
|
345
|
-
@request.options[:format] = :json
|
346
|
-
expect(@request.send(:parse_response, json)).to eq({'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}})
|
347
|
-
end
|
348
|
-
|
349
|
-
it "should include any HTTP headers in the returned response" do
|
350
|
-
@request.options[:format] = :html
|
351
|
-
response = stub_response "Content"
|
352
|
-
response.initialize_http_header("key" => "value")
|
353
|
-
|
354
|
-
expect(@request.perform.headers).to eq({ "key" => ["value"] })
|
355
|
-
end
|
356
|
-
|
357
|
-
if "".respond_to?(:encoding)
|
358
|
-
|
359
|
-
it "should process charset in content type properly" do
|
360
|
-
response = stub_response "Content"
|
361
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-8")
|
362
|
-
resp = @request.perform
|
363
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-8"))
|
364
|
-
end
|
365
|
-
|
366
|
-
it "should process charset in content type properly if it has a different case" do
|
367
|
-
response = stub_response "Content"
|
368
|
-
response.initialize_http_header("Content-Type" => "text/plain;CHARSET = utf-8")
|
369
|
-
resp = @request.perform
|
370
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-8"))
|
371
|
-
end
|
372
|
-
|
373
|
-
it "should process quoted charset in content type properly" do
|
374
|
-
response = stub_response "Content"
|
375
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = \"utf-8\"")
|
376
|
-
resp = @request.perform
|
377
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-8"))
|
378
|
-
end
|
379
|
-
|
380
|
-
it "should process utf-16 charset with little endian bom correctly" do
|
381
|
-
@request.options[:assume_utf16_is_big_endian] = true
|
382
|
-
|
383
|
-
response = stub_response "\xFF\xFEC\x00o\x00n\x00t\x00e\x00n\x00t\x00"
|
384
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-16")
|
385
|
-
resp = @request.perform
|
386
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-16LE"))
|
387
|
-
end
|
388
|
-
|
389
|
-
it "should process utf-16 charset with big endian bom correctly" do
|
390
|
-
@request.options[:assume_utf16_is_big_endian] = false
|
391
|
-
|
392
|
-
response = stub_response "\xFE\xFF\x00C\x00o\x00n\x00t\x00e\x00n\x00t"
|
393
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-16")
|
394
|
-
resp = @request.perform
|
395
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-16BE"))
|
396
|
-
end
|
397
|
-
|
398
|
-
it "should assume utf-16 little endian if options has been chosen" do
|
399
|
-
@request.options[:assume_utf16_is_big_endian] = false
|
400
|
-
|
401
|
-
response = stub_response "C\x00o\x00n\x00t\x00e\x00n\x00t\x00"
|
402
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-16")
|
403
|
-
resp = @request.perform
|
404
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-16LE"))
|
405
|
-
end
|
406
|
-
|
407
|
-
it "should perform no encoding if the charset is not available" do
|
408
|
-
response = stub_response "Content"
|
409
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-lols")
|
410
|
-
resp = @request.perform
|
411
|
-
expect(resp.body).to eq("Content")
|
412
|
-
expect(resp.body.encoding).to eq("Content".encoding)
|
413
|
-
end
|
414
|
-
|
415
|
-
it "should perform no encoding if the content type is specified but no charset is specified" do
|
416
|
-
response = stub_response "Content"
|
417
|
-
response.initialize_http_header("Content-Type" => "text/plain")
|
418
|
-
resp = @request.perform
|
419
|
-
expect(resp.body).to eq("Content")
|
420
|
-
expect(resp.body.encoding).to eq("Content".encoding)
|
421
|
-
end
|
422
|
-
end
|
423
|
-
|
424
|
-
describe 'with non-200 responses' do
|
425
|
-
context "3xx responses" do
|
426
|
-
it 'returns a valid object for 304 not modified' do
|
427
|
-
stub_response '', 304
|
428
|
-
resp = @request.perform
|
429
|
-
expect(resp.code).to eq(304)
|
430
|
-
expect(resp.body).to eq('')
|
431
|
-
expect(resp).to be_nil
|
432
|
-
end
|
433
|
-
|
434
|
-
it "redirects if a 300 contains a location header" do
|
435
|
-
redirect = stub_response '', 300
|
436
|
-
redirect['location'] = 'http://foo.com/foo'
|
437
|
-
ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
438
|
-
allow(@http).to receive(:request).and_return(redirect, ok)
|
439
|
-
response = @request.perform
|
440
|
-
expect(response.request.base_uri.to_s).to eq("http://foo.com")
|
441
|
-
expect(response.request.path.to_s).to eq("http://foo.com/foo")
|
442
|
-
expect(response.request.uri.request_uri).to eq("/foo")
|
443
|
-
expect(response.request.uri.to_s).to eq("http://foo.com/foo")
|
444
|
-
expect(response.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
445
|
-
end
|
446
|
-
|
447
|
-
it "calls block given to perform with each redirect" do
|
448
|
-
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://test.com/redirect', format: :xml)
|
449
|
-
FakeWeb.register_uri(:get, "http://test.com/redirect", status: [300, "REDIRECT"], location: "http://api.foo.com/v2")
|
450
|
-
FakeWeb.register_uri(:get, "http://api.foo.com/v2", body: "<hash><foo>bar</foo></hash>")
|
451
|
-
body = ""
|
452
|
-
response = @request.perform { |chunk| body += chunk }
|
453
|
-
expect(body.length).to eq(27)
|
454
|
-
end
|
455
|
-
|
456
|
-
it "redirects if a 300 contains a relative location header" do
|
457
|
-
redirect = stub_response '', 300
|
458
|
-
redirect['location'] = '/foo/bar'
|
459
|
-
ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
460
|
-
allow(@http).to receive(:request).and_return(redirect, ok)
|
461
|
-
response = @request.perform
|
462
|
-
expect(response.request.base_uri.to_s).to eq("http://api.foo.com")
|
463
|
-
expect(response.request.path.to_s).to eq("/foo/bar")
|
464
|
-
expect(response.request.uri.request_uri).to eq("/foo/bar")
|
465
|
-
expect(response.request.uri.to_s).to eq("http://api.foo.com/foo/bar")
|
466
|
-
expect(response.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
467
|
-
end
|
468
|
-
|
469
|
-
it "handles multiple redirects and relative location headers on different hosts" do
|
470
|
-
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://test.com/redirect', format: :xml)
|
471
|
-
FakeWeb.register_uri(:get, "http://test.com/redirect", status: [300, "REDIRECT"], location: "http://api.foo.com/v2")
|
472
|
-
FakeWeb.register_uri(:get, "http://api.foo.com/v2", status: [300, "REDIRECT"], location: "/v3")
|
473
|
-
FakeWeb.register_uri(:get, "http://api.foo.com/v3", body: "<hash><foo>bar</foo></hash>")
|
474
|
-
response = @request.perform
|
475
|
-
expect(response.request.base_uri.to_s).to eq("http://api.foo.com")
|
476
|
-
expect(response.request.path.to_s).to eq("/v3")
|
477
|
-
expect(response.request.uri.request_uri).to eq("/v3")
|
478
|
-
expect(response.request.uri.to_s).to eq("http://api.foo.com/v3")
|
479
|
-
expect(response.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
480
|
-
end
|
481
|
-
|
482
|
-
it "returns the HTTParty::Response when the 300 does not contain a location header" do
|
483
|
-
stub_response '', 300
|
484
|
-
expect(HTTParty::Response).to be === @request.perform
|
485
|
-
end
|
486
|
-
|
487
|
-
it "redirects including port" do
|
488
|
-
FakeWeb.register_uri(:get, "http://withport.com:3000/v1", status: [301, "Moved Permanently"], location: "http://withport.com:3000/v2")
|
489
|
-
FakeWeb.register_uri(:get, "http://withport.com:3000/v2", status: 200)
|
490
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://withport.com:3000/v1')
|
491
|
-
response = request.perform
|
492
|
-
expect(response.request.base_uri.to_s).to eq("http://withport.com:3000")
|
493
|
-
end
|
494
|
-
end
|
495
|
-
|
496
|
-
it 'should return a valid object for 4xx response' do
|
497
|
-
stub_response '<foo><bar>yes</bar></foo>', 401
|
498
|
-
resp = @request.perform
|
499
|
-
expect(resp.code).to eq(401)
|
500
|
-
expect(resp.body).to eq("<foo><bar>yes</bar></foo>")
|
501
|
-
expect(resp['foo']['bar']).to eq("yes")
|
502
|
-
end
|
503
|
-
|
504
|
-
it 'should return a valid object for 5xx response' do
|
505
|
-
stub_response '<foo><bar>error</bar></foo>', 500
|
506
|
-
resp = @request.perform
|
507
|
-
expect(resp.code).to eq(500)
|
508
|
-
expect(resp.body).to eq("<foo><bar>error</bar></foo>")
|
509
|
-
expect(resp['foo']['bar']).to eq("error")
|
510
|
-
end
|
511
|
-
|
512
|
-
it "parses response lazily so codes can be checked prior" do
|
513
|
-
stub_response 'not xml', 500
|
514
|
-
@request.options[:format] = :xml
|
515
|
-
expect {
|
516
|
-
response = @request.perform
|
517
|
-
expect(response.code).to eq(500)
|
518
|
-
expect(response.body).to eq('not xml')
|
519
|
-
}.not_to raise_error
|
520
|
-
end
|
521
|
-
end
|
522
|
-
end
|
523
|
-
|
524
|
-
it "should not attempt to parse empty responses" do
|
525
|
-
[204, 304].each do |code|
|
526
|
-
stub_response "", code
|
527
|
-
|
528
|
-
@request.options[:format] = :xml
|
529
|
-
expect(@request.perform).to be_nil
|
530
|
-
end
|
531
|
-
end
|
532
|
-
|
533
|
-
it "should not fail for missing mime type" do
|
534
|
-
stub_response "Content for you"
|
535
|
-
@request.options[:format] = :html
|
536
|
-
expect(@request.perform.parsed_response).to eq('Content for you')
|
537
|
-
end
|
538
|
-
|
539
|
-
[300, 301, 302, 305].each do |code|
|
540
|
-
describe "a request that #{code} redirects" do
|
541
|
-
before(:each) do
|
542
|
-
@redirect = stub_response("", code)
|
543
|
-
@redirect['location'] = '/foo'
|
544
|
-
|
545
|
-
@ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
546
|
-
end
|
547
|
-
|
548
|
-
describe "once" do
|
549
|
-
before(:each) do
|
550
|
-
allow(@http).to receive(:request).and_return(@redirect, @ok)
|
551
|
-
end
|
552
|
-
|
553
|
-
it "should be handled by GET transparently" do
|
554
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
555
|
-
end
|
556
|
-
|
557
|
-
it "should be handled by POST transparently" do
|
558
|
-
@request.http_method = Net::HTTP::Post
|
559
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
560
|
-
end
|
561
|
-
|
562
|
-
it "should be handled by DELETE transparently" do
|
563
|
-
@request.http_method = Net::HTTP::Delete
|
564
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
565
|
-
end
|
566
|
-
|
567
|
-
it "should be handled by MOVE transparently" do
|
568
|
-
@request.http_method = Net::HTTP::Move
|
569
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
570
|
-
end
|
571
|
-
|
572
|
-
it "should be handled by COPY transparently" do
|
573
|
-
@request.http_method = Net::HTTP::Copy
|
574
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
575
|
-
end
|
576
|
-
|
577
|
-
it "should be handled by PATCH transparently" do
|
578
|
-
@request.http_method = Net::HTTP::Patch
|
579
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
580
|
-
end
|
581
|
-
|
582
|
-
it "should be handled by PUT transparently" do
|
583
|
-
@request.http_method = Net::HTTP::Put
|
584
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
585
|
-
end
|
586
|
-
|
587
|
-
it "should be handled by HEAD transparently" do
|
588
|
-
@request.http_method = Net::HTTP::Head
|
589
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
590
|
-
end
|
591
|
-
|
592
|
-
it "should be handled by OPTIONS transparently" do
|
593
|
-
@request.http_method = Net::HTTP::Options
|
594
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
595
|
-
end
|
596
|
-
|
597
|
-
it "should keep track of cookies between redirects" do
|
598
|
-
@redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
|
599
|
-
@request.perform
|
600
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
601
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
602
|
-
end
|
603
|
-
|
604
|
-
it 'should update cookies with rediects' do
|
605
|
-
@request.options[:headers] = {'Cookie' => 'foo=bar;'}
|
606
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
607
|
-
@request.perform
|
608
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=tar/)
|
609
|
-
end
|
610
|
-
|
611
|
-
it 'should keep cookies between rediects' do
|
612
|
-
@request.options[:headers] = {'Cookie' => 'keep=me'}
|
613
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
614
|
-
@request.perform
|
615
|
-
expect(@request.options[:headers]['Cookie']).to match(/keep=me/)
|
616
|
-
end
|
617
|
-
|
618
|
-
it "should handle multiple Set-Cookie headers between redirects" do
|
619
|
-
@redirect.add_field 'set-cookie', 'foo=bar; name=value; HTTPOnly'
|
620
|
-
@redirect.add_field 'set-cookie', 'one=1; two=2; HTTPOnly'
|
621
|
-
@request.perform
|
622
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
623
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
624
|
-
expect(@request.options[:headers]['Cookie']).to match(/one=1/)
|
625
|
-
expect(@request.options[:headers]['Cookie']).to match(/two=2/)
|
626
|
-
end
|
627
|
-
|
628
|
-
it 'should make resulting request a get request if it not already' do
|
629
|
-
@request.http_method = Net::HTTP::Delete
|
630
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
631
|
-
expect(@request.http_method).to eq(Net::HTTP::Get)
|
632
|
-
end
|
633
|
-
|
634
|
-
it 'should not make resulting request a get request if options[:maintain_method_across_redirects] is true' do
|
635
|
-
@request.options[:maintain_method_across_redirects] = true
|
636
|
-
@request.http_method = Net::HTTP::Delete
|
637
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
638
|
-
expect(@request.http_method).to eq(Net::HTTP::Delete)
|
639
|
-
end
|
640
|
-
|
641
|
-
it 'should log the redirection' do
|
642
|
-
logger_double = double
|
643
|
-
expect(logger_double).to receive(:info).twice
|
644
|
-
@request.options[:logger] = logger_double
|
645
|
-
@request.perform
|
646
|
-
end
|
647
|
-
end
|
648
|
-
|
649
|
-
describe "infinitely" do
|
650
|
-
before(:each) do
|
651
|
-
allow(@http).to receive(:request).and_return(@redirect)
|
652
|
-
end
|
653
|
-
|
654
|
-
it "should raise an exception" do
|
655
|
-
expect { @request.perform }.to raise_error(HTTParty::RedirectionTooDeep)
|
656
|
-
end
|
657
|
-
end
|
658
|
-
end
|
659
|
-
end
|
660
|
-
|
661
|
-
describe "a request that 303 redirects" do
|
662
|
-
before(:each) do
|
663
|
-
@redirect = stub_response("", 303)
|
664
|
-
@redirect['location'] = '/foo'
|
665
|
-
|
666
|
-
@ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
667
|
-
end
|
668
|
-
|
669
|
-
describe "once" do
|
670
|
-
before(:each) do
|
671
|
-
allow(@http).to receive(:request).and_return(@redirect, @ok)
|
672
|
-
end
|
673
|
-
|
674
|
-
it "should be handled by GET transparently" do
|
675
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
676
|
-
end
|
677
|
-
|
678
|
-
it "should be handled by POST transparently" do
|
679
|
-
@request.http_method = Net::HTTP::Post
|
680
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
681
|
-
end
|
682
|
-
|
683
|
-
it "should be handled by DELETE transparently" do
|
684
|
-
@request.http_method = Net::HTTP::Delete
|
685
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
686
|
-
end
|
687
|
-
|
688
|
-
it "should be handled by MOVE transparently" do
|
689
|
-
@request.http_method = Net::HTTP::Move
|
690
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
691
|
-
end
|
692
|
-
|
693
|
-
it "should be handled by COPY transparently" do
|
694
|
-
@request.http_method = Net::HTTP::Copy
|
695
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
696
|
-
end
|
697
|
-
|
698
|
-
it "should be handled by PATCH transparently" do
|
699
|
-
@request.http_method = Net::HTTP::Patch
|
700
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
701
|
-
end
|
702
|
-
|
703
|
-
it "should be handled by PUT transparently" do
|
704
|
-
@request.http_method = Net::HTTP::Put
|
705
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
706
|
-
end
|
707
|
-
|
708
|
-
it "should be handled by HEAD transparently" do
|
709
|
-
@request.http_method = Net::HTTP::Head
|
710
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
711
|
-
end
|
712
|
-
|
713
|
-
it "should be handled by OPTIONS transparently" do
|
714
|
-
@request.http_method = Net::HTTP::Options
|
715
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
716
|
-
end
|
717
|
-
|
718
|
-
it "should keep track of cookies between redirects" do
|
719
|
-
@redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
|
720
|
-
@request.perform
|
721
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
722
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
723
|
-
end
|
724
|
-
|
725
|
-
it 'should update cookies with rediects' do
|
726
|
-
@request.options[:headers] = {'Cookie' => 'foo=bar;'}
|
727
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
728
|
-
@request.perform
|
729
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=tar/)
|
730
|
-
end
|
731
|
-
|
732
|
-
it 'should keep cookies between rediects' do
|
733
|
-
@request.options[:headers] = {'Cookie' => 'keep=me'}
|
734
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
735
|
-
@request.perform
|
736
|
-
expect(@request.options[:headers]['Cookie']).to match(/keep=me/)
|
737
|
-
end
|
738
|
-
|
739
|
-
it "should handle multiple Set-Cookie headers between redirects" do
|
740
|
-
@redirect.add_field 'set-cookie', 'foo=bar; name=value; HTTPOnly'
|
741
|
-
@redirect.add_field 'set-cookie', 'one=1; two=2; HTTPOnly'
|
742
|
-
@request.perform
|
743
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
744
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
745
|
-
expect(@request.options[:headers]['Cookie']).to match(/one=1/)
|
746
|
-
expect(@request.options[:headers]['Cookie']).to match(/two=2/)
|
747
|
-
end
|
748
|
-
|
749
|
-
it 'should make resulting request a get request if it not already' do
|
750
|
-
@request.http_method = Net::HTTP::Delete
|
751
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
752
|
-
expect(@request.http_method).to eq(Net::HTTP::Get)
|
753
|
-
end
|
754
|
-
|
755
|
-
it 'should make resulting request a get request if options[:maintain_method_across_redirects] is false' do
|
756
|
-
@request.options[:maintain_method_across_redirects] = false
|
757
|
-
@request.http_method = Net::HTTP::Delete
|
758
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
759
|
-
expect(@request.http_method).to eq(Net::HTTP::Get)
|
760
|
-
end
|
761
|
-
|
762
|
-
it 'should make resulting request a get request if options[:maintain_method_across_redirects] is true but options[:resend_on_redirect] is false' do
|
763
|
-
@request.options[:maintain_method_across_redirects] = true
|
764
|
-
@request.options[:resend_on_redirect] = false
|
765
|
-
@request.http_method = Net::HTTP::Delete
|
766
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
767
|
-
expect(@request.http_method).to eq(Net::HTTP::Get)
|
768
|
-
end
|
769
|
-
|
770
|
-
it 'should not make resulting request a get request if options[:maintain_method_across_redirects] and options[:resend_on_redirect] is true' do
|
771
|
-
@request.options[:maintain_method_across_redirects] = true
|
772
|
-
@request.options[:resend_on_redirect] = true
|
773
|
-
@request.http_method = Net::HTTP::Delete
|
774
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
775
|
-
expect(@request.http_method).to eq(Net::HTTP::Delete)
|
776
|
-
end
|
777
|
-
|
778
|
-
it 'should log the redirection' do
|
779
|
-
logger_double = double
|
780
|
-
expect(logger_double).to receive(:info).twice
|
781
|
-
@request.options[:logger] = logger_double
|
782
|
-
@request.perform
|
783
|
-
end
|
784
|
-
end
|
785
|
-
|
786
|
-
describe "infinitely" do
|
787
|
-
before(:each) do
|
788
|
-
allow(@http).to receive(:request).and_return(@redirect)
|
789
|
-
end
|
790
|
-
|
791
|
-
it "should raise an exception" do
|
792
|
-
expect { @request.perform }.to raise_error(HTTParty::RedirectionTooDeep)
|
793
|
-
end
|
794
|
-
end
|
795
|
-
end
|
796
|
-
|
797
|
-
describe "a request that returns 304" do
|
798
|
-
before(:each) do
|
799
|
-
@redirect = stub_response("", 304)
|
800
|
-
@redirect['location'] = '/foo'
|
801
|
-
end
|
802
|
-
|
803
|
-
before(:each) do
|
804
|
-
allow(@http).to receive(:request).and_return(@redirect)
|
805
|
-
end
|
806
|
-
|
807
|
-
it "should report 304 with a GET request" do
|
808
|
-
expect(@request.perform.code).to eq(304)
|
809
|
-
end
|
810
|
-
|
811
|
-
it "should report 304 with a POST request" do
|
812
|
-
@request.http_method = Net::HTTP::Post
|
813
|
-
expect(@request.perform.code).to eq(304)
|
814
|
-
end
|
815
|
-
|
816
|
-
it "should report 304 with a DELETE request" do
|
817
|
-
@request.http_method = Net::HTTP::Delete
|
818
|
-
expect(@request.perform.code).to eq(304)
|
819
|
-
end
|
820
|
-
|
821
|
-
it "should report 304 with a MOVE request" do
|
822
|
-
@request.http_method = Net::HTTP::Move
|
823
|
-
expect(@request.perform.code).to eq(304)
|
824
|
-
end
|
825
|
-
|
826
|
-
it "should report 304 with a COPY request" do
|
827
|
-
@request.http_method = Net::HTTP::Copy
|
828
|
-
expect(@request.perform.code).to eq(304)
|
829
|
-
end
|
830
|
-
|
831
|
-
it "should report 304 with a PATCH request" do
|
832
|
-
@request.http_method = Net::HTTP::Patch
|
833
|
-
expect(@request.perform.code).to eq(304)
|
834
|
-
end
|
835
|
-
|
836
|
-
it "should report 304 with a PUT request" do
|
837
|
-
@request.http_method = Net::HTTP::Put
|
838
|
-
expect(@request.perform.code).to eq(304)
|
839
|
-
end
|
840
|
-
|
841
|
-
it "should report 304 with a HEAD request" do
|
842
|
-
@request.http_method = Net::HTTP::Head
|
843
|
-
expect(@request.perform.code).to eq(304)
|
844
|
-
end
|
845
|
-
|
846
|
-
it "should report 304 with a OPTIONS request" do
|
847
|
-
@request.http_method = Net::HTTP::Options
|
848
|
-
expect(@request.perform.code).to eq(304)
|
849
|
-
end
|
850
|
-
|
851
|
-
it 'should not log the redirection' do
|
852
|
-
logger_double = double
|
853
|
-
expect(logger_double).to receive(:info).once
|
854
|
-
@request.options[:logger] = logger_double
|
855
|
-
@request.perform
|
856
|
-
end
|
857
|
-
end
|
858
|
-
|
859
|
-
[307, 308].each do |code|
|
860
|
-
describe "a request that #{code} redirects" do
|
861
|
-
before(:each) do
|
862
|
-
@redirect = stub_response("", code)
|
863
|
-
@redirect['location'] = '/foo'
|
864
|
-
|
865
|
-
@ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
866
|
-
end
|
867
|
-
|
868
|
-
describe "once" do
|
869
|
-
before(:each) do
|
870
|
-
allow(@http).to receive(:request).and_return(@redirect, @ok)
|
871
|
-
end
|
872
|
-
|
873
|
-
it "should be handled by GET transparently" do
|
874
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
875
|
-
end
|
876
|
-
|
877
|
-
it "should be handled by POST transparently" do
|
878
|
-
@request.http_method = Net::HTTP::Post
|
879
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
880
|
-
end
|
881
|
-
|
882
|
-
it "should be handled by DELETE transparently" do
|
883
|
-
@request.http_method = Net::HTTP::Delete
|
884
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
885
|
-
end
|
886
|
-
|
887
|
-
it "should be handled by MOVE transparently" do
|
888
|
-
@request.http_method = Net::HTTP::Move
|
889
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
890
|
-
end
|
891
|
-
|
892
|
-
it "should be handled by COPY transparently" do
|
893
|
-
@request.http_method = Net::HTTP::Copy
|
894
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
895
|
-
end
|
896
|
-
|
897
|
-
it "should be handled by PATCH transparently" do
|
898
|
-
@request.http_method = Net::HTTP::Patch
|
899
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
900
|
-
end
|
901
|
-
|
902
|
-
it "should be handled by PUT transparently" do
|
903
|
-
@request.http_method = Net::HTTP::Put
|
904
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
905
|
-
end
|
906
|
-
|
907
|
-
it "should be handled by HEAD transparently" do
|
908
|
-
@request.http_method = Net::HTTP::Head
|
909
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
910
|
-
end
|
911
|
-
|
912
|
-
it "should be handled by OPTIONS transparently" do
|
913
|
-
@request.http_method = Net::HTTP::Options
|
914
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
915
|
-
end
|
916
|
-
|
917
|
-
it "should keep track of cookies between redirects" do
|
918
|
-
@redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
|
919
|
-
@request.perform
|
920
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
921
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
922
|
-
end
|
923
|
-
|
924
|
-
it 'should update cookies with rediects' do
|
925
|
-
@request.options[:headers] = {'Cookie' => 'foo=bar;'}
|
926
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
927
|
-
@request.perform
|
928
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=tar/)
|
929
|
-
end
|
930
|
-
|
931
|
-
it 'should keep cookies between rediects' do
|
932
|
-
@request.options[:headers] = {'Cookie' => 'keep=me'}
|
933
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
934
|
-
@request.perform
|
935
|
-
expect(@request.options[:headers]['Cookie']).to match(/keep=me/)
|
936
|
-
end
|
937
|
-
|
938
|
-
it "should handle multiple Set-Cookie headers between redirects" do
|
939
|
-
@redirect.add_field 'set-cookie', 'foo=bar; name=value; HTTPOnly'
|
940
|
-
@redirect.add_field 'set-cookie', 'one=1; two=2; HTTPOnly'
|
941
|
-
@request.perform
|
942
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
943
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
944
|
-
expect(@request.options[:headers]['Cookie']).to match(/one=1/)
|
945
|
-
expect(@request.options[:headers]['Cookie']).to match(/two=2/)
|
946
|
-
end
|
947
|
-
|
948
|
-
it 'should maintain method in resulting request' do
|
949
|
-
@request.http_method = Net::HTTP::Delete
|
950
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
951
|
-
expect(@request.http_method).to eq(Net::HTTP::Delete)
|
952
|
-
end
|
953
|
-
|
954
|
-
it 'should maintain method in resulting request if options[:maintain_method_across_redirects] is false' do
|
955
|
-
@request.options[:maintain_method_across_redirects] = false
|
956
|
-
@request.http_method = Net::HTTP::Delete
|
957
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
958
|
-
expect(@request.http_method).to eq(Net::HTTP::Delete)
|
959
|
-
end
|
960
|
-
|
961
|
-
it 'should maintain method in resulting request if options[:maintain_method_across_redirects] is true' do
|
962
|
-
@request.options[:maintain_method_across_redirects] = true
|
963
|
-
@request.http_method = Net::HTTP::Delete
|
964
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
965
|
-
expect(@request.http_method).to eq(Net::HTTP::Delete)
|
966
|
-
end
|
967
|
-
|
968
|
-
it 'should log the redirection' do
|
969
|
-
logger_double = double
|
970
|
-
expect(logger_double).to receive(:info).twice
|
971
|
-
@request.options[:logger] = logger_double
|
972
|
-
@request.perform
|
973
|
-
end
|
974
|
-
end
|
975
|
-
|
976
|
-
describe "infinitely" do
|
977
|
-
before(:each) do
|
978
|
-
allow(@http).to receive(:request).and_return(@redirect)
|
979
|
-
end
|
980
|
-
|
981
|
-
it "should raise an exception" do
|
982
|
-
expect { @request.perform }.to raise_error(HTTParty::RedirectionTooDeep)
|
983
|
-
end
|
984
|
-
end
|
985
|
-
end
|
986
|
-
end
|
987
|
-
|
988
|
-
describe "#handle_deflation" do
|
989
|
-
context "context-encoding" do
|
990
|
-
before do
|
991
|
-
@request.options[:format] = :html
|
992
|
-
@last_response = double
|
993
|
-
allow(@last_response).to receive(:body).and_return('')
|
994
|
-
end
|
995
|
-
|
996
|
-
it "should inflate the gzipped body with content-encoding: gzip" do
|
997
|
-
allow(@last_response).to receive(:[]).with("content-encoding").and_return("gzip")
|
998
|
-
allow(@request).to receive(:last_response).and_return(@last_response)
|
999
|
-
expect(Zlib::GzipReader).to receive(:new).and_return(StringIO.new(''))
|
1000
|
-
expect(@request.last_response).to receive(:delete).with('content-encoding')
|
1001
|
-
@request.send(:handle_deflation)
|
1002
|
-
end
|
1003
|
-
|
1004
|
-
it "should inflate the gzipped body with content-encoding: x-gzip" do
|
1005
|
-
allow(@last_response).to receive(:[]).with("content-encoding").and_return("x-gzip")
|
1006
|
-
allow(@request).to receive(:last_response).and_return(@last_response)
|
1007
|
-
expect(Zlib::GzipReader).to receive(:new).and_return(StringIO.new(''))
|
1008
|
-
expect(@request.last_response).to receive(:delete).with('content-encoding')
|
1009
|
-
@request.send(:handle_deflation)
|
1010
|
-
end
|
1011
|
-
|
1012
|
-
it "should inflate the deflated body" do
|
1013
|
-
allow(@last_response).to receive(:[]).with("content-encoding").and_return("deflate")
|
1014
|
-
allow(@request).to receive(:last_response).and_return(@last_response)
|
1015
|
-
expect(Zlib::Inflate).to receive(:inflate).and_return('')
|
1016
|
-
expect(@request.last_response).to receive(:delete).with('content-encoding')
|
1017
|
-
@request.send(:handle_deflation)
|
1018
|
-
end
|
1019
|
-
end
|
1020
|
-
end
|
1021
|
-
|
1022
|
-
context "with POST http method" do
|
1023
|
-
it "should raise argument error if query is not a hash" do
|
1024
|
-
expect {
|
1025
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', format: :xml, query: 'astring').perform
|
1026
|
-
}.to raise_error(ArgumentError)
|
1027
|
-
end
|
1028
|
-
end
|
1029
|
-
|
1030
|
-
describe "argument validation" do
|
1031
|
-
it "should raise argument error if basic_auth and digest_auth are both present" do
|
1032
|
-
expect {
|
1033
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', basic_auth: {}, digest_auth: {}).perform
|
1034
|
-
}.to raise_error(ArgumentError, "only one authentication method, :basic_auth or :digest_auth may be used at a time")
|
1035
|
-
end
|
1036
|
-
|
1037
|
-
it "should raise argument error if basic_auth is not a hash" do
|
1038
|
-
expect {
|
1039
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', basic_auth: %w(foo bar)).perform
|
1040
|
-
}.to raise_error(ArgumentError, ":basic_auth must be a hash")
|
1041
|
-
end
|
1042
|
-
|
1043
|
-
it "should raise argument error if digest_auth is not a hash" do
|
1044
|
-
expect {
|
1045
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', digest_auth: %w(foo bar)).perform
|
1046
|
-
}.to raise_error(ArgumentError, ":digest_auth must be a hash")
|
1047
|
-
end
|
1048
|
-
|
1049
|
-
it "should raise argument error if headers is not a hash" do
|
1050
|
-
expect {
|
1051
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', headers: %w(foo bar)).perform
|
1052
|
-
}.to raise_error(ArgumentError, ":headers must be a hash")
|
1053
|
-
end
|
1054
|
-
|
1055
|
-
it "should raise argument error if options method is not http accepted method" do
|
1056
|
-
expect {
|
1057
|
-
HTTParty::Request.new('SuperPost', 'http://api.foo.com/v1').perform
|
1058
|
-
}.to raise_error(ArgumentError, "only get, post, patch, put, delete, head, and options methods are supported")
|
1059
|
-
end
|
1060
|
-
|
1061
|
-
it "should raise argument error if http method is post and query is not hash" do
|
1062
|
-
expect {
|
1063
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', query: "message: hello").perform
|
1064
|
-
}.to raise_error(ArgumentError, ":query must be hash if using HTTP Post")
|
1065
|
-
end
|
1066
|
-
|
1067
|
-
it "should raise RedirectionTooDeep error if limit is negative" do
|
1068
|
-
expect {
|
1069
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', limit: -1).perform
|
1070
|
-
}.to raise_error(HTTParty::RedirectionTooDeep, 'HTTP redirects too deep')
|
1071
|
-
end
|
1072
|
-
end
|
1073
|
-
end
|