httparty 0.13.0 → 0.14.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.

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