httpserious 0.13.5.lstoll1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rubocop.yml +92 -0
  4. data/.rubocop_todo.yml +124 -0
  5. data/.simplecov +1 -0
  6. data/.travis.yml +7 -0
  7. data/CONTRIBUTING.md +23 -0
  8. data/Gemfile +19 -0
  9. data/Guardfile +16 -0
  10. data/History +370 -0
  11. data/MIT-LICENSE +20 -0
  12. data/README.md +78 -0
  13. data/Rakefile +10 -0
  14. data/bin/httparty +116 -0
  15. data/cucumber.yml +1 -0
  16. data/examples/README.md +67 -0
  17. data/examples/aaws.rb +32 -0
  18. data/examples/basic.rb +28 -0
  19. data/examples/crack.rb +19 -0
  20. data/examples/custom_parsers.rb +64 -0
  21. data/examples/delicious.rb +37 -0
  22. data/examples/google.rb +16 -0
  23. data/examples/headers_and_user_agents.rb +6 -0
  24. data/examples/logging.rb +36 -0
  25. data/examples/nokogiri_html_parser.rb +19 -0
  26. data/examples/rescue_json.rb +17 -0
  27. data/examples/rubyurl.rb +14 -0
  28. data/examples/stackexchange.rb +24 -0
  29. data/examples/tripit_sign_in.rb +33 -0
  30. data/examples/twitter.rb +31 -0
  31. data/examples/whoismyrep.rb +10 -0
  32. data/features/basic_authentication.feature +20 -0
  33. data/features/command_line.feature +90 -0
  34. data/features/deals_with_http_error_codes.feature +26 -0
  35. data/features/digest_authentication.feature +20 -0
  36. data/features/handles_compressed_responses.feature +27 -0
  37. data/features/handles_multiple_formats.feature +57 -0
  38. data/features/steps/env.rb +27 -0
  39. data/features/steps/httparty_response_steps.rb +52 -0
  40. data/features/steps/httparty_steps.rb +43 -0
  41. data/features/steps/mongrel_helper.rb +94 -0
  42. data/features/steps/remote_service_steps.rb +86 -0
  43. data/features/supports_read_timeout_option.feature +13 -0
  44. data/features/supports_redirection.feature +22 -0
  45. data/features/supports_timeout_option.feature +13 -0
  46. data/httparty.gemspec +28 -0
  47. data/httpserious.gemspec +25 -0
  48. data/lib/httparty.rb +612 -0
  49. data/lib/httparty/connection_adapter.rb +190 -0
  50. data/lib/httparty/cookie_hash.rb +21 -0
  51. data/lib/httparty/exceptions.rb +29 -0
  52. data/lib/httparty/hash_conversions.rb +49 -0
  53. data/lib/httparty/logger/apache_formatter.rb +22 -0
  54. data/lib/httparty/logger/curl_formatter.rb +48 -0
  55. data/lib/httparty/logger/logger.rb +26 -0
  56. data/lib/httparty/module_inheritable_attributes.rb +56 -0
  57. data/lib/httparty/net_digest_auth.rb +117 -0
  58. data/lib/httparty/parser.rb +141 -0
  59. data/lib/httparty/request.rb +361 -0
  60. data/lib/httparty/response.rb +77 -0
  61. data/lib/httparty/response/headers.rb +31 -0
  62. data/lib/httparty/version.rb +3 -0
  63. data/lib/httpserious.rb +1 -0
  64. data/script/release +42 -0
  65. data/spec/fixtures/delicious.xml +23 -0
  66. data/spec/fixtures/empty.xml +0 -0
  67. data/spec/fixtures/google.html +3 -0
  68. data/spec/fixtures/ssl/generate.sh +29 -0
  69. data/spec/fixtures/ssl/generated/1fe462c2.0 +16 -0
  70. data/spec/fixtures/ssl/generated/bogushost.crt +13 -0
  71. data/spec/fixtures/ssl/generated/ca.crt +16 -0
  72. data/spec/fixtures/ssl/generated/ca.key +15 -0
  73. data/spec/fixtures/ssl/generated/selfsigned.crt +14 -0
  74. data/spec/fixtures/ssl/generated/server.crt +13 -0
  75. data/spec/fixtures/ssl/generated/server.key +15 -0
  76. data/spec/fixtures/ssl/openssl-exts.cnf +9 -0
  77. data/spec/fixtures/twitter.csv +2 -0
  78. data/spec/fixtures/twitter.json +1 -0
  79. data/spec/fixtures/twitter.xml +403 -0
  80. data/spec/fixtures/undefined_method_add_node_for_nil.xml +2 -0
  81. data/spec/httparty/connection_adapter_spec.rb +468 -0
  82. data/spec/httparty/cookie_hash_spec.rb +83 -0
  83. data/spec/httparty/exception_spec.rb +38 -0
  84. data/spec/httparty/hash_conversions_spec.rb +41 -0
  85. data/spec/httparty/logger/apache_formatter_spec.rb +41 -0
  86. data/spec/httparty/logger/curl_formatter_spec.rb +18 -0
  87. data/spec/httparty/logger/logger_spec.rb +38 -0
  88. data/spec/httparty/net_digest_auth_spec.rb +191 -0
  89. data/spec/httparty/parser_spec.rb +167 -0
  90. data/spec/httparty/request_spec.rb +872 -0
  91. data/spec/httparty/response_spec.rb +241 -0
  92. data/spec/httparty/ssl_spec.rb +74 -0
  93. data/spec/httparty_spec.rb +823 -0
  94. data/spec/spec_helper.rb +59 -0
  95. data/spec/support/ssl_test_helper.rb +47 -0
  96. data/spec/support/ssl_test_server.rb +80 -0
  97. data/spec/support/stub_response.rb +43 -0
  98. data/website/css/common.css +47 -0
  99. data/website/index.html +73 -0
  100. metadata +219 -0
@@ -0,0 +1,167 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ RSpec.describe HTTParty::Parser do
4
+ describe ".SupportedFormats" do
5
+ it "returns a hash" do
6
+ expect(HTTParty::Parser::SupportedFormats).to be_instance_of(Hash)
7
+ end
8
+ end
9
+
10
+ describe ".call" do
11
+ it "generates an HTTParty::Parser instance with the given body and format" do
12
+ expect(HTTParty::Parser).to receive(:new).with('body', :plain).and_return(double(parse: nil))
13
+ HTTParty::Parser.call('body', :plain)
14
+ end
15
+
16
+ it "calls #parse on the parser" do
17
+ parser = double('Parser')
18
+ expect(parser).to receive(:parse)
19
+ allow(HTTParty::Parser).to receive_messages(new: parser)
20
+ parser = HTTParty::Parser.call('body', :plain)
21
+ end
22
+ end
23
+
24
+ describe ".formats" do
25
+ it "returns the SupportedFormats constant" do
26
+ expect(HTTParty::Parser.formats).to eq(HTTParty::Parser::SupportedFormats)
27
+ end
28
+
29
+ it "returns the SupportedFormats constant for subclasses" do
30
+ class MyParser < HTTParty::Parser
31
+ SupportedFormats = {"application/atom+xml" => :atom}
32
+ end
33
+ expect(MyParser.formats).to eq({"application/atom+xml" => :atom})
34
+ end
35
+ end
36
+
37
+ describe ".format_from_mimetype" do
38
+ it "returns a symbol representing the format mimetype" do
39
+ expect(HTTParty::Parser.format_from_mimetype("text/plain")).to eq(:plain)
40
+ end
41
+
42
+ it "returns nil when the mimetype is not supported" do
43
+ expect(HTTParty::Parser.format_from_mimetype("application/atom+xml")).to be_nil
44
+ end
45
+ end
46
+
47
+ describe ".supported_formats" do
48
+ it "returns a unique set of supported formats represented by symbols" do
49
+ expect(HTTParty::Parser.supported_formats).to eq(HTTParty::Parser::SupportedFormats.values.uniq)
50
+ end
51
+ end
52
+
53
+ describe ".supports_format?" do
54
+ it "returns true for a supported format" do
55
+ allow(HTTParty::Parser).to receive_messages(supported_formats: [:json])
56
+ expect(HTTParty::Parser.supports_format?(:json)).to be_truthy
57
+ end
58
+
59
+ it "returns false for an unsupported format" do
60
+ allow(HTTParty::Parser).to receive_messages(supported_formats: [])
61
+ expect(HTTParty::Parser.supports_format?(:json)).to be_falsey
62
+ end
63
+ end
64
+
65
+ describe "#parse" do
66
+ before do
67
+ @parser = HTTParty::Parser.new('body', :json)
68
+ end
69
+
70
+ it "attempts to parse supported formats" do
71
+ allow(@parser).to receive_messages(supports_format?: true)
72
+ expect(@parser).to receive(:parse_supported_format)
73
+ @parser.parse
74
+ end
75
+
76
+ it "returns the unparsed body when the format is unsupported" do
77
+ allow(@parser).to receive_messages(supports_format?: false)
78
+ expect(@parser.parse).to eq(@parser.body)
79
+ end
80
+
81
+ it "returns nil for an empty body" do
82
+ allow(@parser).to receive_messages(body: '')
83
+ expect(@parser.parse).to be_nil
84
+ end
85
+
86
+ it "returns nil for a nil body" do
87
+ allow(@parser).to receive_messages(body: nil)
88
+ expect(@parser.parse).to be_nil
89
+ end
90
+
91
+ it "returns nil for a 'null' body" do
92
+ allow(@parser).to receive_messages(body: "null")
93
+ expect(@parser.parse).to be_nil
94
+ end
95
+
96
+ it "returns nil for a body with spaces only" do
97
+ allow(@parser).to receive_messages(body: " ")
98
+ expect(@parser.parse).to be_nil
99
+ end
100
+ end
101
+
102
+ describe "#supports_format?" do
103
+ it "utilizes the class method to determine if the format is supported" do
104
+ expect(HTTParty::Parser).to receive(:supports_format?).with(:json)
105
+ parser = HTTParty::Parser.new('body', :json)
106
+ parser.send(:supports_format?)
107
+ end
108
+ end
109
+
110
+ describe "#parse_supported_format" do
111
+ it "calls the parser for the given format" do
112
+ parser = HTTParty::Parser.new('body', :json)
113
+ expect(parser).to receive(:json)
114
+ parser.send(:parse_supported_format)
115
+ end
116
+
117
+ context "when a parsing method does not exist for the given format" do
118
+ it "raises an exception" do
119
+ parser = HTTParty::Parser.new('body', :atom)
120
+ expect do
121
+ parser.send(:parse_supported_format)
122
+ end.to raise_error(NotImplementedError, "HTTParty::Parser has not implemented a parsing method for the :atom format.")
123
+ end
124
+
125
+ it "raises a useful exception message for subclasses" do
126
+ atom_parser = Class.new(HTTParty::Parser) do
127
+ def self.name
128
+ 'AtomParser'
129
+ end
130
+ end
131
+ parser = atom_parser.new 'body', :atom
132
+ expect do
133
+ parser.send(:parse_supported_format)
134
+ end.to raise_error(NotImplementedError, "AtomParser has not implemented a parsing method for the :atom format.")
135
+ end
136
+ end
137
+ end
138
+
139
+ context "parsers" do
140
+ subject do
141
+ HTTParty::Parser.new('body', nil)
142
+ end
143
+
144
+ it "parses xml with MultiXml" do
145
+ expect(MultiXml).to receive(:parse).with('body')
146
+ subject.send(:xml)
147
+ end
148
+
149
+ it "parses json with JSON" do
150
+ expect(JSON).to receive(:parse).with('body', :quirks_mode => true, :allow_nan => true)
151
+ subject.send(:json)
152
+ end
153
+
154
+ it "parses html by simply returning the body" do
155
+ expect(subject.send(:html)).to eq('body')
156
+ end
157
+
158
+ it "parses plain text by simply returning the body" do
159
+ expect(subject.send(:plain)).to eq('body')
160
+ end
161
+
162
+ it "parses csv with CSV" do
163
+ expect(CSV).to receive(:parse).with('body')
164
+ subject.send(:csv)
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,872 @@
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
+ end
487
+
488
+ it 'should return a valid object for 4xx response' do
489
+ stub_response '<foo><bar>yes</bar></foo>', 401
490
+ resp = @request.perform
491
+ expect(resp.code).to eq(401)
492
+ expect(resp.body).to eq("<foo><bar>yes</bar></foo>")
493
+ expect(resp['foo']['bar']).to eq("yes")
494
+ end
495
+
496
+ it 'should return a valid object for 5xx response' do
497
+ stub_response '<foo><bar>error</bar></foo>', 500
498
+ resp = @request.perform
499
+ expect(resp.code).to eq(500)
500
+ expect(resp.body).to eq("<foo><bar>error</bar></foo>")
501
+ expect(resp['foo']['bar']).to eq("error")
502
+ end
503
+
504
+ it "parses response lazily so codes can be checked prior" do
505
+ stub_response 'not xml', 500
506
+ @request.options[:format] = :xml
507
+ expect {
508
+ response = @request.perform
509
+ expect(response.code).to eq(500)
510
+ expect(response.body).to eq('not xml')
511
+ }.not_to raise_error
512
+ end
513
+ end
514
+ end
515
+
516
+ it "should not attempt to parse empty responses" do
517
+ [204, 304].each do |code|
518
+ stub_response "", code
519
+
520
+ @request.options[:format] = :xml
521
+ expect(@request.perform).to be_nil
522
+ end
523
+ end
524
+
525
+ it "should not fail for missing mime type" do
526
+ stub_response "Content for you"
527
+ @request.options[:format] = :html
528
+ expect(@request.perform.parsed_response).to eq('Content for you')
529
+ end
530
+
531
+ describe "a request that 302 redirects" do
532
+ before(:each) do
533
+ @redirect = stub_response("", 302)
534
+ @redirect['location'] = '/foo'
535
+
536
+ @ok = stub_response('<hash><foo>bar</foo></hash>', 200)
537
+ end
538
+
539
+ describe "once" do
540
+ before(:each) do
541
+ allow(@http).to receive(:request).and_return(@redirect, @ok)
542
+ end
543
+
544
+ it "should be handled by GET transparently" do
545
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
546
+ end
547
+
548
+ it "should be handled by POST transparently" do
549
+ @request.http_method = Net::HTTP::Post
550
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
551
+ end
552
+
553
+ it "should be handled by DELETE transparently" do
554
+ @request.http_method = Net::HTTP::Delete
555
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
556
+ end
557
+
558
+ it "should be handled by MOVE transparently" do
559
+ @request.http_method = Net::HTTP::Move
560
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
561
+ end
562
+
563
+ it "should be handled by COPY transparently" do
564
+ @request.http_method = Net::HTTP::Copy
565
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
566
+ end
567
+
568
+ it "should be handled by PATCH transparently" do
569
+ @request.http_method = Net::HTTP::Patch
570
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
571
+ end
572
+
573
+ it "should be handled by PUT transparently" do
574
+ @request.http_method = Net::HTTP::Put
575
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
576
+ end
577
+
578
+ it "should be handled by HEAD transparently" do
579
+ @request.http_method = Net::HTTP::Head
580
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
581
+ end
582
+
583
+ it "should be handled by OPTIONS transparently" do
584
+ @request.http_method = Net::HTTP::Options
585
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
586
+ end
587
+
588
+ it "should keep track of cookies between redirects" do
589
+ @redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
590
+ @request.perform
591
+ expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
592
+ expect(@request.options[:headers]['Cookie']).to match(/name=value/)
593
+ end
594
+
595
+ it 'should update cookies with rediects' do
596
+ @request.options[:headers] = {'Cookie' => 'foo=bar;'}
597
+ @redirect['Set-Cookie'] = 'foo=tar;'
598
+ @request.perform
599
+ expect(@request.options[:headers]['Cookie']).to match(/foo=tar/)
600
+ end
601
+
602
+ it 'should keep cookies between rediects' do
603
+ @request.options[:headers] = {'Cookie' => 'keep=me'}
604
+ @redirect['Set-Cookie'] = 'foo=tar;'
605
+ @request.perform
606
+ expect(@request.options[:headers]['Cookie']).to match(/keep=me/)
607
+ end
608
+
609
+ it "should handle multiple Set-Cookie headers between redirects" do
610
+ @redirect.add_field 'set-cookie', 'foo=bar; name=value; HTTPOnly'
611
+ @redirect.add_field 'set-cookie', 'one=1; two=2; HTTPOnly'
612
+ @request.perform
613
+ expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
614
+ expect(@request.options[:headers]['Cookie']).to match(/name=value/)
615
+ expect(@request.options[:headers]['Cookie']).to match(/one=1/)
616
+ expect(@request.options[:headers]['Cookie']).to match(/two=2/)
617
+ end
618
+
619
+ it 'should make resulting request a get request if it not already' do
620
+ @request.http_method = Net::HTTP::Delete
621
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
622
+ expect(@request.http_method).to eq(Net::HTTP::Get)
623
+ end
624
+
625
+ it 'should not make resulting request a get request if options[:maintain_method_across_redirects] is true' do
626
+ @request.options[:maintain_method_across_redirects] = true
627
+ @request.http_method = Net::HTTP::Delete
628
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
629
+ expect(@request.http_method).to eq(Net::HTTP::Delete)
630
+ end
631
+
632
+ it 'should log the redirection' do
633
+ logger_double = double
634
+ expect(logger_double).to receive(:info).twice
635
+ @request.options[:logger] = logger_double
636
+ @request.perform
637
+ end
638
+ end
639
+
640
+ describe "infinitely" do
641
+ before(:each) do
642
+ allow(@http).to receive(:request).and_return(@redirect)
643
+ end
644
+
645
+ it "should raise an exception" do
646
+ expect { @request.perform }.to raise_error(HTTParty::RedirectionTooDeep)
647
+ end
648
+ end
649
+ end
650
+
651
+ describe "a request that 303 redirects" do
652
+ before(:each) do
653
+ @redirect = stub_response("", 303)
654
+ @redirect['location'] = '/foo'
655
+
656
+ @ok = stub_response('<hash><foo>bar</foo></hash>', 200)
657
+ end
658
+
659
+ describe "once" do
660
+ before(:each) do
661
+ allow(@http).to receive(:request).and_return(@redirect, @ok)
662
+ end
663
+
664
+ it "should be handled by GET transparently" do
665
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
666
+ end
667
+
668
+ it "should be handled by POST transparently" do
669
+ @request.http_method = Net::HTTP::Post
670
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
671
+ end
672
+
673
+ it "should be handled by DELETE transparently" do
674
+ @request.http_method = Net::HTTP::Delete
675
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
676
+ end
677
+
678
+ it "should be handled by MOVE transparently" do
679
+ @request.http_method = Net::HTTP::Move
680
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
681
+ end
682
+
683
+ it "should be handled by COPY transparently" do
684
+ @request.http_method = Net::HTTP::Copy
685
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
686
+ end
687
+
688
+ it "should be handled by PATCH transparently" do
689
+ @request.http_method = Net::HTTP::Patch
690
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
691
+ end
692
+
693
+ it "should be handled by PUT transparently" do
694
+ @request.http_method = Net::HTTP::Put
695
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
696
+ end
697
+
698
+ it "should be handled by HEAD transparently" do
699
+ @request.http_method = Net::HTTP::Head
700
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
701
+ end
702
+
703
+ it "should be handled by OPTIONS transparently" do
704
+ @request.http_method = Net::HTTP::Options
705
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
706
+ end
707
+
708
+ it "should keep track of cookies between redirects" do
709
+ @redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
710
+ @request.perform
711
+ expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
712
+ expect(@request.options[:headers]['Cookie']).to match(/name=value/)
713
+ end
714
+
715
+ it 'should update cookies with rediects' do
716
+ @request.options[:headers] = {'Cookie' => 'foo=bar;'}
717
+ @redirect['Set-Cookie'] = 'foo=tar;'
718
+ @request.perform
719
+ expect(@request.options[:headers]['Cookie']).to match(/foo=tar/)
720
+ end
721
+
722
+ it 'should keep cookies between rediects' do
723
+ @request.options[:headers] = {'Cookie' => 'keep=me'}
724
+ @redirect['Set-Cookie'] = 'foo=tar;'
725
+ @request.perform
726
+ expect(@request.options[:headers]['Cookie']).to match(/keep=me/)
727
+ end
728
+
729
+ it "should handle multiple Set-Cookie headers between redirects" do
730
+ @redirect.add_field 'set-cookie', 'foo=bar; name=value; HTTPOnly'
731
+ @redirect.add_field 'set-cookie', 'one=1; two=2; HTTPOnly'
732
+ @request.perform
733
+ expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
734
+ expect(@request.options[:headers]['Cookie']).to match(/name=value/)
735
+ expect(@request.options[:headers]['Cookie']).to match(/one=1/)
736
+ expect(@request.options[:headers]['Cookie']).to match(/two=2/)
737
+ end
738
+
739
+ it 'should make resulting request a get request if it not already' do
740
+ @request.http_method = Net::HTTP::Delete
741
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
742
+ expect(@request.http_method).to eq(Net::HTTP::Get)
743
+ end
744
+
745
+ it 'should make resulting request a get request if options[:maintain_method_across_redirects] is false' do
746
+ @request.options[:maintain_method_across_redirects] = false
747
+ @request.http_method = Net::HTTP::Delete
748
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
749
+ expect(@request.http_method).to eq(Net::HTTP::Get)
750
+ end
751
+
752
+ it 'should make resulting request a get request if options[:maintain_method_across_redirects] is true but options[:resend_on_redirect] is false' do
753
+ @request.options[:maintain_method_across_redirects] = true
754
+ @request.options[:resend_on_redirect] = false
755
+ @request.http_method = Net::HTTP::Delete
756
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
757
+ expect(@request.http_method).to eq(Net::HTTP::Get)
758
+ end
759
+
760
+ it 'should not make resulting request a get request if options[:maintain_method_across_redirects] and options[:resend_on_redirect] is true' do
761
+ @request.options[:maintain_method_across_redirects] = true
762
+ @request.options[:resend_on_redirect] = true
763
+ @request.http_method = Net::HTTP::Delete
764
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
765
+ expect(@request.http_method).to eq(Net::HTTP::Delete)
766
+ end
767
+
768
+ it 'should log the redirection' do
769
+ logger_double = double
770
+ expect(logger_double).to receive(:info).twice
771
+ @request.options[:logger] = logger_double
772
+ @request.perform
773
+ end
774
+ end
775
+
776
+ describe "infinitely" do
777
+ before(:each) do
778
+ allow(@http).to receive(:request).and_return(@redirect)
779
+ end
780
+
781
+ it "should raise an exception" do
782
+ expect { @request.perform }.to raise_error(HTTParty::RedirectionTooDeep)
783
+ end
784
+ end
785
+ end
786
+
787
+ describe "#handle_deflation" do
788
+ context "context-encoding" do
789
+ before do
790
+ @request.options[:format] = :html
791
+ @last_response = double
792
+ allow(@last_response).to receive(:body).and_return('')
793
+ end
794
+
795
+ it "should inflate the gzipped body with content-encoding: gzip" do
796
+ allow(@last_response).to receive(:[]).with("content-encoding").and_return("gzip")
797
+ allow(@request).to receive(:last_response).and_return(@last_response)
798
+ expect(Zlib::GzipReader).to receive(:new).and_return(StringIO.new(''))
799
+ expect(@request.last_response).to receive(:delete).with('content-encoding')
800
+ @request.send(:handle_deflation)
801
+ end
802
+
803
+ it "should inflate the gzipped body with content-encoding: x-gzip" do
804
+ allow(@last_response).to receive(:[]).with("content-encoding").and_return("x-gzip")
805
+ allow(@request).to receive(:last_response).and_return(@last_response)
806
+ expect(Zlib::GzipReader).to receive(:new).and_return(StringIO.new(''))
807
+ expect(@request.last_response).to receive(:delete).with('content-encoding')
808
+ @request.send(:handle_deflation)
809
+ end
810
+
811
+ it "should inflate the deflated body" do
812
+ allow(@last_response).to receive(:[]).with("content-encoding").and_return("deflate")
813
+ allow(@request).to receive(:last_response).and_return(@last_response)
814
+ expect(Zlib::Inflate).to receive(:inflate).and_return('')
815
+ expect(@request.last_response).to receive(:delete).with('content-encoding')
816
+ @request.send(:handle_deflation)
817
+ end
818
+ end
819
+ end
820
+
821
+ context "with POST http method" do
822
+ it "should raise argument error if query is not a hash" do
823
+ expect {
824
+ HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', format: :xml, query: 'astring').perform
825
+ }.to raise_error(ArgumentError)
826
+ end
827
+ end
828
+
829
+ describe "argument validation" do
830
+ it "should raise argument error if basic_auth and digest_auth are both present" do
831
+ expect {
832
+ HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', basic_auth: {}, digest_auth: {}).perform
833
+ }.to raise_error(ArgumentError, "only one authentication method, :basic_auth or :digest_auth may be used at a time")
834
+ end
835
+
836
+ it "should raise argument error if basic_auth is not a hash" do
837
+ expect {
838
+ HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', basic_auth: %w(foo bar)).perform
839
+ }.to raise_error(ArgumentError, ":basic_auth must be a hash")
840
+ end
841
+
842
+ it "should raise argument error if digest_auth is not a hash" do
843
+ expect {
844
+ HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', digest_auth: %w(foo bar)).perform
845
+ }.to raise_error(ArgumentError, ":digest_auth must be a hash")
846
+ end
847
+
848
+ it "should raise argument error if headers is not a hash" do
849
+ expect {
850
+ HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', headers: %w(foo bar)).perform
851
+ }.to raise_error(ArgumentError, ":headers must be a hash")
852
+ end
853
+
854
+ it "should raise argument error if options method is not http accepted method" do
855
+ expect {
856
+ HTTParty::Request.new('SuperPost', 'http://api.foo.com/v1').perform
857
+ }.to raise_error(ArgumentError, "only get, post, patch, put, delete, head, and options methods are supported")
858
+ end
859
+
860
+ it "should raise argument error if http method is post and query is not hash" do
861
+ expect {
862
+ HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', query: "message: hello").perform
863
+ }.to raise_error(ArgumentError, ":query must be hash if using HTTP Post")
864
+ end
865
+
866
+ it "should raise RedirectionTooDeep error if limit is negative" do
867
+ expect {
868
+ HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', limit: -1).perform
869
+ }.to raise_error(HTTParty::RedirectionTooDeep, 'HTTP redirects too deep')
870
+ end
871
+ end
872
+ end