httpserious 0.13.5.lstoll1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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