httparty 0.17.0 → 0.17.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of httparty might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Changelog.md +7 -0
- data/Gemfile +1 -0
- data/httparty.gemspec +0 -1
- data/lib/httparty.rb +2 -18
- data/lib/httparty/connection_adapter.rb +10 -0
- data/lib/httparty/headers_processor.rb +30 -0
- data/lib/httparty/request.rb +4 -4
- data/lib/httparty/version.rb +1 -1
- metadata +4 -103
- data/features/basic_authentication.feature +0 -20
- data/features/command_line.feature +0 -95
- data/features/deals_with_http_error_codes.feature +0 -26
- data/features/digest_authentication.feature +0 -30
- data/features/handles_compressed_responses.feature +0 -27
- data/features/handles_multiple_formats.feature +0 -57
- data/features/steps/env.rb +0 -27
- data/features/steps/httparty_response_steps.rb +0 -56
- data/features/steps/httparty_steps.rb +0 -43
- data/features/steps/mongrel_helper.rb +0 -127
- data/features/steps/remote_service_steps.rb +0 -92
- data/features/supports_read_timeout_option.feature +0 -13
- data/features/supports_redirection.feature +0 -22
- data/features/supports_timeout_option.feature +0 -13
- data/spec/fixtures/delicious.xml +0 -23
- data/spec/fixtures/empty.xml +0 -0
- data/spec/fixtures/example.html +0 -10
- data/spec/fixtures/ssl/generate.sh +0 -29
- data/spec/fixtures/ssl/generated/bogushost.crt +0 -29
- data/spec/fixtures/ssl/generated/ca.crt +0 -31
- data/spec/fixtures/ssl/generated/ca.key +0 -52
- data/spec/fixtures/ssl/generated/selfsigned.crt +0 -29
- data/spec/fixtures/ssl/generated/server.crt +0 -30
- data/spec/fixtures/ssl/generated/server.key +0 -52
- data/spec/fixtures/ssl/openssl-exts.cnf +0 -9
- data/spec/fixtures/tiny.gif +0 -0
- data/spec/fixtures/twitter.csv +0 -2
- data/spec/fixtures/twitter.json +0 -1
- data/spec/fixtures/twitter.xml +0 -403
- data/spec/fixtures/undefined_method_add_node_for_nil.xml +0 -2
- data/spec/httparty/connection_adapter_spec.rb +0 -628
- data/spec/httparty/cookie_hash_spec.rb +0 -100
- data/spec/httparty/exception_spec.rb +0 -45
- data/spec/httparty/hash_conversions_spec.rb +0 -58
- data/spec/httparty/logger/apache_formatter_spec.rb +0 -40
- data/spec/httparty/logger/curl_formatter_spec.rb +0 -119
- data/spec/httparty/logger/logger_spec.rb +0 -43
- data/spec/httparty/logger/logstash_formatter_spec.rb +0 -44
- data/spec/httparty/net_digest_auth_spec.rb +0 -270
- data/spec/httparty/parser_spec.rb +0 -190
- data/spec/httparty/request/body_spec.rb +0 -165
- data/spec/httparty/request_spec.rb +0 -1389
- data/spec/httparty/response_fragment_spec.rb +0 -17
- data/spec/httparty/response_spec.rb +0 -374
- data/spec/httparty/ssl_spec.rb +0 -82
- data/spec/httparty_spec.rb +0 -943
- data/spec/spec_helper.rb +0 -57
- data/spec/support/ssl_test_helper.rb +0 -47
- data/spec/support/ssl_test_server.rb +0 -80
- data/spec/support/stub_response.rb +0 -50
@@ -1,165 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'tempfile'
|
3
|
-
|
4
|
-
RSpec.describe HTTParty::Request::Body do
|
5
|
-
describe '#call' do
|
6
|
-
let(:options) { {} }
|
7
|
-
|
8
|
-
subject { described_class.new(params, options).call }
|
9
|
-
|
10
|
-
context 'when params is string' do
|
11
|
-
let(:params) { 'name=Bob%20Jones' }
|
12
|
-
|
13
|
-
it { is_expected.to eq params }
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'when params is hash' do
|
17
|
-
let(:params) { { people: ["Bob Jones", "Mike Smith"] } }
|
18
|
-
let(:converted_params) { "people[]=Bob%20Jones&people[]=Mike%20Smith"}
|
19
|
-
|
20
|
-
it { is_expected.to eq converted_params }
|
21
|
-
|
22
|
-
context 'when params has file' do
|
23
|
-
before do
|
24
|
-
allow(HTTParty::Request::MultipartBoundary)
|
25
|
-
.to receive(:generate).and_return("------------------------c772861a5109d5ef")
|
26
|
-
end
|
27
|
-
|
28
|
-
let(:file) { File.open('spec/fixtures/tiny.gif') }
|
29
|
-
let(:params) do
|
30
|
-
{
|
31
|
-
user: {
|
32
|
-
avatar: file,
|
33
|
-
first_name: 'John',
|
34
|
-
last_name: 'Doe',
|
35
|
-
enabled: true
|
36
|
-
}
|
37
|
-
}
|
38
|
-
end
|
39
|
-
let(:expected_file_name) { 'tiny.gif' }
|
40
|
-
let(:expected_file_contents) { "GIF89a\u0001\u0000\u0001\u0000\u0000\xFF\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0000;" }
|
41
|
-
let(:expected_content_type) { 'image/gif' }
|
42
|
-
let(:multipart_params) do
|
43
|
-
"--------------------------c772861a5109d5ef\r\n" \
|
44
|
-
"Content-Disposition: form-data; name=\"user[avatar]\"; filename=\"#{expected_file_name}\"\r\n" \
|
45
|
-
"Content-Type: #{expected_content_type}\r\n" \
|
46
|
-
"\r\n" \
|
47
|
-
"#{expected_file_contents}\r\n" \
|
48
|
-
"--------------------------c772861a5109d5ef\r\n" \
|
49
|
-
"Content-Disposition: form-data; name=\"user[first_name]\"\r\n" \
|
50
|
-
"\r\n" \
|
51
|
-
"John\r\n" \
|
52
|
-
"--------------------------c772861a5109d5ef\r\n" \
|
53
|
-
"Content-Disposition: form-data; name=\"user[last_name]\"\r\n" \
|
54
|
-
"\r\n" \
|
55
|
-
"Doe\r\n" \
|
56
|
-
"--------------------------c772861a5109d5ef\r\n" \
|
57
|
-
"Content-Disposition: form-data; name=\"user[enabled]\"\r\n" \
|
58
|
-
"\r\n" \
|
59
|
-
"true\r\n" \
|
60
|
-
"--------------------------c772861a5109d5ef--\r\n"
|
61
|
-
end
|
62
|
-
|
63
|
-
it { is_expected.to eq multipart_params }
|
64
|
-
|
65
|
-
context 'when passing multipart as an option' do
|
66
|
-
let(:options) { { force_multipart: true } }
|
67
|
-
let(:params) do
|
68
|
-
{
|
69
|
-
user: {
|
70
|
-
first_name: 'John',
|
71
|
-
last_name: 'Doe',
|
72
|
-
enabled: true
|
73
|
-
}
|
74
|
-
}
|
75
|
-
end
|
76
|
-
let(:multipart_params) do
|
77
|
-
"--------------------------c772861a5109d5ef\r\n" \
|
78
|
-
"Content-Disposition: form-data; name=\"user[first_name]\"\r\n" \
|
79
|
-
"\r\n" \
|
80
|
-
"John\r\n" \
|
81
|
-
"--------------------------c772861a5109d5ef\r\n" \
|
82
|
-
"Content-Disposition: form-data; name=\"user[last_name]\"\r\n" \
|
83
|
-
"\r\n" \
|
84
|
-
"Doe\r\n" \
|
85
|
-
"--------------------------c772861a5109d5ef\r\n" \
|
86
|
-
"Content-Disposition: form-data; name=\"user[enabled]\"\r\n" \
|
87
|
-
"\r\n" \
|
88
|
-
"true\r\n" \
|
89
|
-
"--------------------------c772861a5109d5ef--\r\n"
|
90
|
-
end
|
91
|
-
|
92
|
-
it { is_expected.to eq multipart_params }
|
93
|
-
|
94
|
-
end
|
95
|
-
|
96
|
-
context 'file object responds to original_filename' do
|
97
|
-
let(:some_temp_file) { Tempfile.new(['some_temp_file','.gif']) }
|
98
|
-
let(:expected_file_name) { "some_temp_file.gif" }
|
99
|
-
let(:expected_file_contents) { "Hello" }
|
100
|
-
let(:file) { double(:mocked_action_dispatch, path: some_temp_file.path, original_filename: 'some_temp_file.gif', read: expected_file_contents) }
|
101
|
-
|
102
|
-
before { some_temp_file.write('Hello') }
|
103
|
-
|
104
|
-
it { is_expected.to eq multipart_params }
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
describe '#multipart?' do
|
111
|
-
let(:force_multipart) { false }
|
112
|
-
let(:file) { File.open('spec/fixtures/tiny.gif') }
|
113
|
-
|
114
|
-
subject { described_class.new(params, force_multipart: force_multipart).multipart? }
|
115
|
-
|
116
|
-
context 'when params does not respond to to_hash' do
|
117
|
-
let(:params) { 'name=Bob%20Jones' }
|
118
|
-
|
119
|
-
it { is_expected.to be false }
|
120
|
-
end
|
121
|
-
|
122
|
-
context 'when params responds to to_hash' do
|
123
|
-
class HashLike
|
124
|
-
def initialize(hash)
|
125
|
-
@hash = hash
|
126
|
-
end
|
127
|
-
|
128
|
-
def to_hash
|
129
|
-
@hash
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
class ArrayLike
|
134
|
-
def initialize(ary)
|
135
|
-
@ary = ary
|
136
|
-
end
|
137
|
-
|
138
|
-
def to_ary
|
139
|
-
@ary
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
context 'when force_multipart is true' do
|
144
|
-
let(:params) { { name: 'Bob Jones' } }
|
145
|
-
let(:force_multipart) { true }
|
146
|
-
|
147
|
-
it { is_expected.to be true }
|
148
|
-
end
|
149
|
-
|
150
|
-
context 'when it does not contain a file' do
|
151
|
-
let(:hash_like_param) { HashLike.new(first: 'Bob', last: ArrayLike.new(['Jones'])) }
|
152
|
-
let(:params) { { name: ArrayLike.new([hash_like_param]) } }
|
153
|
-
|
154
|
-
it { is_expected.to eq false }
|
155
|
-
end
|
156
|
-
|
157
|
-
context 'when it contains file' do
|
158
|
-
let(:hash_like_param) { HashLike.new(first: 'Bob', last: 'Jones', file: ArrayLike.new([file])) }
|
159
|
-
let(:params) { { name: ArrayLike.new([hash_like_param]) } }
|
160
|
-
|
161
|
-
it { is_expected.to be true }
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
@@ -1,1389 +0,0 @@
|
|
1
|
-
require '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 "::JSON_API_QUERY_STRING_NORMALIZER" do
|
37
|
-
let(:normalizer) { HTTParty::Request::JSON_API_QUERY_STRING_NORMALIZER }
|
38
|
-
|
39
|
-
it "doesn't modify strings" do
|
40
|
-
query_string = normalizer["foo=bar&foo=baz"]
|
41
|
-
expect(CGI.unescape(query_string)).to eq("foo=bar&foo=baz")
|
42
|
-
end
|
43
|
-
|
44
|
-
context "when the query is an array" do
|
45
|
-
it "doesn't include brackets" do
|
46
|
-
query_string = normalizer[{page: 1, foo: %w(bar baz)}]
|
47
|
-
expect(CGI.unescape(query_string)).to eq("foo=bar,baz&page=1")
|
48
|
-
end
|
49
|
-
|
50
|
-
it "URI encodes array values" do
|
51
|
-
query_string = normalizer[{people: ["Otis Redding", "Bob Marley", "Tim & Jon"], page: 1, xyzzy: 3}]
|
52
|
-
expect(query_string).to eq("page=1&people=Otis%20Redding,Bob%20Marley,Tim%20%26%20Jon&xyzzy=3")
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context "when the query is a hash" do
|
57
|
-
it "correctly handles nil values" do
|
58
|
-
query_string = normalizer[{page: 1, per_page: nil}]
|
59
|
-
expect(query_string).to eq('page=1&per_page')
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
describe "initialization" do
|
65
|
-
it "sets parser to HTTParty::Parser" do
|
66
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com')
|
67
|
-
expect(request.parser).to eq(HTTParty::Parser)
|
68
|
-
end
|
69
|
-
|
70
|
-
it "sets parser to the optional parser" do
|
71
|
-
my_parser = lambda {}
|
72
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', parser: my_parser)
|
73
|
-
expect(request.parser).to eq(my_parser)
|
74
|
-
end
|
75
|
-
|
76
|
-
it "sets connection_adapter to HTTParty::ConnectionAdapter" do
|
77
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com')
|
78
|
-
expect(request.connection_adapter).to eq(HTTParty::ConnectionAdapter)
|
79
|
-
end
|
80
|
-
|
81
|
-
it "sets connection_adapter to the optional connection_adapter" do
|
82
|
-
my_adapter = lambda {}
|
83
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', connection_adapter: my_adapter)
|
84
|
-
expect(request.connection_adapter).to eq(my_adapter)
|
85
|
-
end
|
86
|
-
|
87
|
-
context "when using a query string" do
|
88
|
-
context "and it has an empty array" do
|
89
|
-
it "sets correct query string" do
|
90
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', query: { fake_array: [] })
|
91
|
-
|
92
|
-
expect(request.uri).to eq(URI.parse("http://google.com/?fake_array[]="))
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
context "when sending an array with only one element" do
|
97
|
-
it "sets correct query" do
|
98
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', query: { fake_array: [1] })
|
99
|
-
|
100
|
-
expect(request.uri).to eq(URI.parse("http://google.com/?fake_array[]=1"))
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
context "when basic authentication credentials provided in uri" do
|
106
|
-
context "when basic auth options wasn't set explicitly" do
|
107
|
-
it "sets basic auth from uri" do
|
108
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://user1:pass1@example.com')
|
109
|
-
expect(request.options[:basic_auth]).to eq({username: 'user1', password: 'pass1'})
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
context "when basic auth options was set explicitly" do
|
114
|
-
it "uses basic auth from url anyway" do
|
115
|
-
basic_auth = {username: 'user2', password: 'pass2'}
|
116
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://user1:pass1@example.com', basic_auth: basic_auth)
|
117
|
-
expect(request.options[:basic_auth]).to eq({username: 'user1', password: 'pass1'})
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
describe "#format" do
|
124
|
-
context "request yet to be made" do
|
125
|
-
it "returns format option" do
|
126
|
-
request = HTTParty::Request.new 'get', '/', format: :xml
|
127
|
-
expect(request.format).to eq(:xml)
|
128
|
-
end
|
129
|
-
|
130
|
-
it "returns nil format" do
|
131
|
-
request = HTTParty::Request.new 'get', '/'
|
132
|
-
expect(request.format).to be_nil
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
context "request has been made" do
|
137
|
-
it "returns format option" do
|
138
|
-
request = HTTParty::Request.new 'get', '/', format: :xml
|
139
|
-
request.last_response = double
|
140
|
-
expect(request.format).to eq(:xml)
|
141
|
-
end
|
142
|
-
|
143
|
-
it "returns the content-type from the last response when the option is not set" do
|
144
|
-
request = HTTParty::Request.new 'get', '/'
|
145
|
-
response = double
|
146
|
-
expect(response).to receive(:[]).with('content-type').and_return('text/json')
|
147
|
-
request.last_response = response
|
148
|
-
expect(request.format).to eq(:json)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
context "options" do
|
154
|
-
it "should use basic auth when configured" do
|
155
|
-
@request.options[:basic_auth] = {username: 'foobar', password: 'secret'}
|
156
|
-
@request.send(:setup_raw_request)
|
157
|
-
expect(@request.instance_variable_get(:@raw_request)['authorization']).not_to be_nil
|
158
|
-
end
|
159
|
-
|
160
|
-
context 'digest_auth' do
|
161
|
-
before do
|
162
|
-
response_sequence = [
|
163
|
-
{
|
164
|
-
status: ['401', 'Unauthorized' ], headers: {
|
165
|
-
www_authenticate: 'Digest realm="Log Viewer", qop="auth", nonce="2CA0EC6B0E126C4800E56BA0C0003D3C", opaque="5ccc069c403ebaf9f0171e9517f40e41", stale=false',
|
166
|
-
set_cookie: 'custom-cookie=1234567'
|
167
|
-
}
|
168
|
-
},
|
169
|
-
{ status: ['200', 'OK'] }
|
170
|
-
]
|
171
|
-
stub_request(:get, 'http://api.foo.com/v1').to_return(response_sequence)
|
172
|
-
end
|
173
|
-
|
174
|
-
it 'should not send credentials more than once' do
|
175
|
-
response_sequence = [
|
176
|
-
{
|
177
|
-
status: ['401', 'Unauthorized' ], headers: {
|
178
|
-
www_authenticate: 'Digest realm="Log Viewer", qop="auth", nonce="2CA0EC6B0E126C4800E56BA0C0003D3C", opaque="5ccc069c403ebaf9f0171e9517f40e41", stale=false',
|
179
|
-
set_cookie: 'custom-cookie=1234567'
|
180
|
-
}
|
181
|
-
},
|
182
|
-
{
|
183
|
-
status: ['401', 'Unauthorized' ], headers: {
|
184
|
-
www_authenticate: 'Digest realm="Log Viewer", qop="auth", nonce="2CA0EC6B0E126C4800E56BA0C0003D3C", opaque="5ccc069c403ebaf9f0171e9517f40e41", stale=false',
|
185
|
-
set_cookie: 'custom-cookie=1234567'
|
186
|
-
}
|
187
|
-
},
|
188
|
-
{ status: ['404', 'Not found'] }
|
189
|
-
]
|
190
|
-
stub_request(:get, 'http://api.foo.com/v1').to_return(response_sequence)
|
191
|
-
|
192
|
-
@request.options[:digest_auth] = {username: 'foobar', password: 'secret'}
|
193
|
-
response = @request.perform { |v| }
|
194
|
-
expect(response.code).to eq(401)
|
195
|
-
|
196
|
-
raw_request = @request.instance_variable_get(:@raw_request)
|
197
|
-
expect(raw_request['Authorization']).not_to be_nil
|
198
|
-
end
|
199
|
-
|
200
|
-
it 'should not be used when configured and the response is 200' do
|
201
|
-
stub_request(:get, 'http://api.foo.com/v1').to_return(status: 200)
|
202
|
-
@request.options[:digest_auth] = {username: 'foobar', password: 'secret'}
|
203
|
-
response = @request.perform { |v| }
|
204
|
-
expect(response.code).to eq(200)
|
205
|
-
|
206
|
-
|
207
|
-
raw_request = @request.instance_variable_get(:@raw_request)
|
208
|
-
expect(raw_request['Authorization']).to be_nil
|
209
|
-
end
|
210
|
-
|
211
|
-
it "should be used when configured and the response is 401" do
|
212
|
-
@request.options[:digest_auth] = {username: 'foobar', password: 'secret'}
|
213
|
-
response = @request.perform { |v| }
|
214
|
-
expect(response.code).to eq(200)
|
215
|
-
|
216
|
-
raw_request = @request.instance_variable_get(:@raw_request)
|
217
|
-
expect(raw_request['Authorization']).not_to be_nil
|
218
|
-
end
|
219
|
-
|
220
|
-
it 'should maintain cookies returned from a 401 response' do
|
221
|
-
@request.options[:digest_auth] = {username: 'foobar', password: 'secret'}
|
222
|
-
response = @request.perform {|v|}
|
223
|
-
expect(response.code).to eq(200)
|
224
|
-
|
225
|
-
raw_request = @request.instance_variable_get(:@raw_request)
|
226
|
-
expect(raw_request.get_fields('cookie')).to eql ["custom-cookie=1234567"]
|
227
|
-
end
|
228
|
-
|
229
|
-
it 'should merge cookies from request and a 401 response' do
|
230
|
-
|
231
|
-
@request.options[:digest_auth] = {username: 'foobar', password: 'secret'}
|
232
|
-
@request.options[:headers] = {'cookie' => 'request-cookie=test'}
|
233
|
-
response = @request.perform {|v|}
|
234
|
-
expect(response.code).to eq(200)
|
235
|
-
|
236
|
-
raw_request = @request.instance_variable_get(:@raw_request)
|
237
|
-
expect(raw_request.get_fields('cookie')).to eql ['request-cookie=test', 'custom-cookie=1234567']
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
it 'should use body_stream when configured' do
|
242
|
-
stream = StringIO.new('foo')
|
243
|
-
request = HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', body_stream: stream)
|
244
|
-
request.send(:setup_raw_request)
|
245
|
-
expect(request.instance_variable_get(:@raw_request).body_stream).to eq(stream)
|
246
|
-
end
|
247
|
-
|
248
|
-
it 'should normalize base uri when specified as request option' do
|
249
|
-
stub_request(:get, 'http://foo.com/resource').to_return(body: 'Bar')
|
250
|
-
response = HTTParty.get('/resource', {
|
251
|
-
base_uri: 'foo.com'
|
252
|
-
})
|
253
|
-
expect(response.code).to eq(200)
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
describe "#uri" do
|
258
|
-
context "redirects" do
|
259
|
-
it "returns correct path when the server sets the location header to a filename" do
|
260
|
-
@request.last_uri = URI.parse("http://example.com/foo/bar")
|
261
|
-
@request.path = URI.parse("bar?foo=bar")
|
262
|
-
@request.redirect = true
|
263
|
-
|
264
|
-
expect(@request.uri).to eq(URI.parse("http://example.com/foo/bar?foo=bar"))
|
265
|
-
end
|
266
|
-
|
267
|
-
context "location header is an absolute path" do
|
268
|
-
it "returns correct path when location has leading slash" do
|
269
|
-
@request.last_uri = URI.parse("http://example.com/foo/bar")
|
270
|
-
@request.path = URI.parse("/bar?foo=bar")
|
271
|
-
@request.redirect = true
|
272
|
-
|
273
|
-
expect(@request.uri).to eq(URI.parse("http://example.com/bar?foo=bar"))
|
274
|
-
end
|
275
|
-
|
276
|
-
it "returns the correct path when location has no leading slash" do
|
277
|
-
@request.last_uri = URI.parse("http://example.com")
|
278
|
-
@request.path = URI.parse("bar/")
|
279
|
-
@request.redirect = true
|
280
|
-
|
281
|
-
expect(@request.uri).to eq(URI.parse("http://example.com/bar/"))
|
282
|
-
end
|
283
|
-
end
|
284
|
-
it "returns correct path when the server sets the location header to a full uri" do
|
285
|
-
@request.last_uri = URI.parse("http://example.com/foo/bar")
|
286
|
-
@request.path = URI.parse("http://example.com/bar?foo=bar")
|
287
|
-
@request.redirect = true
|
288
|
-
|
289
|
-
expect(@request.uri).to eq(URI.parse("http://example.com/bar?foo=bar"))
|
290
|
-
end
|
291
|
-
|
292
|
-
it "returns correct path when the server sets the location header to a network-path reference" do
|
293
|
-
@request.last_uri = URI.parse("https://example.com")
|
294
|
-
@request.path = URI.parse("//www.example.com")
|
295
|
-
@request.redirect = true
|
296
|
-
|
297
|
-
expect(@request.uri).to eq(URI.parse("https://www.example.com"))
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
context "query strings" do
|
302
|
-
it "does not add an empty query string when default_params are blank" do
|
303
|
-
@request.options[:default_params] = {}
|
304
|
-
expect(@request.uri.query).to be_nil
|
305
|
-
end
|
306
|
-
|
307
|
-
it "respects the query string normalization proc" do
|
308
|
-
empty_proc = lambda {|qs| "I"}
|
309
|
-
@request.options[:query_string_normalizer] = empty_proc
|
310
|
-
@request.options[:query] = {foo: :bar}
|
311
|
-
expect(CGI.unescape(@request.uri.query)).to eq("I")
|
312
|
-
end
|
313
|
-
|
314
|
-
it "does not append an ampersand when queries are embedded in paths" do
|
315
|
-
@request.path = "/path?a=1"
|
316
|
-
@request.options[:query] = {}
|
317
|
-
expect(@request.uri.query).to eq("a=1")
|
318
|
-
end
|
319
|
-
|
320
|
-
it "does not duplicate query string parameters when uri is called twice" do
|
321
|
-
@request.options[:query] = {foo: :bar}
|
322
|
-
@request.uri
|
323
|
-
expect(@request.uri.query).to eq("foo=bar")
|
324
|
-
end
|
325
|
-
|
326
|
-
context "when representing an array" do
|
327
|
-
it "returns a Rails style query string" do
|
328
|
-
@request.options[:query] = {foo: %w(bar baz)}
|
329
|
-
expect(CGI.unescape(@request.uri.query)).to eq("foo[]=bar&foo[]=baz")
|
330
|
-
end
|
331
|
-
end
|
332
|
-
end
|
333
|
-
end
|
334
|
-
|
335
|
-
describe "#setup_raw_request" do
|
336
|
-
context "when query_string_normalizer is set" do
|
337
|
-
it "sets the body to the return value of the proc" do
|
338
|
-
@request.options[:query_string_normalizer] = HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER
|
339
|
-
@request.options[:body] = {page: 1, foo: %w(bar baz)}
|
340
|
-
@request.send(:setup_raw_request)
|
341
|
-
body = @request.instance_variable_get(:@raw_request).body
|
342
|
-
expect(CGI.unescape(body)).to eq("foo=bar&foo=baz&page=1")
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
|
-
context "when mulipart" do
|
347
|
-
subject(:headers) do
|
348
|
-
@request.send(:setup_raw_request)
|
349
|
-
headers = @request.instance_variable_get(:@raw_request).each_header.to_a
|
350
|
-
Hash[*headers.flatten] # Ruby 2.0 doesn't have Array#to_h
|
351
|
-
end
|
352
|
-
|
353
|
-
context "when body contains file" do
|
354
|
-
it "sets header Content-Type: multipart/form-data; boundary=" do
|
355
|
-
@request.options[:body] = {file: File.open(File::NULL, 'r')}
|
356
|
-
|
357
|
-
expect(headers['content-type']).to match(%r{^multipart/form-data; boundary=---})
|
358
|
-
end
|
359
|
-
|
360
|
-
context "and header Content-Type is provided" do
|
361
|
-
it "overwrites the header to: multipart/form-data; boundary=" do
|
362
|
-
@request.options[:body] = {file: File.open(File::NULL, 'r')}
|
363
|
-
@request.options[:headers] = {'Content-Type' => 'application/x-www-form-urlencoded'}
|
364
|
-
|
365
|
-
expect(headers['content-type']).to match(%r{^multipart/form-data; boundary=---})
|
366
|
-
end
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
context 'when mulipart option is provided' do
|
371
|
-
it "sets header Content-Type: multipart/form-data; boundary=" do
|
372
|
-
@request.options[:body] = { text: 'something' }
|
373
|
-
@request.options[:multipart] = true
|
374
|
-
|
375
|
-
expect(headers['content-type']).to match(%r{^multipart/form-data; boundary=---})
|
376
|
-
end
|
377
|
-
end
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
describe 'http' do
|
382
|
-
it "should get a connection from the connection_adapter" do
|
383
|
-
http = Net::HTTP.new('google.com')
|
384
|
-
adapter = double('adapter')
|
385
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'https://api.foo.com/v1:443', connection_adapter: adapter)
|
386
|
-
expect(adapter).to receive(:call).with(request.uri, request.options).and_return(http)
|
387
|
-
expect(request.send(:http)).to be http
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
describe '#format_from_mimetype' do
|
392
|
-
it 'should handle text/xml' do
|
393
|
-
["text/xml", "text/xml; charset=iso8859-1"].each do |ct|
|
394
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:xml)
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
|
-
it 'should handle application/xml' do
|
399
|
-
["application/xml", "application/xml; charset=iso8859-1"].each do |ct|
|
400
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:xml)
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
|
-
it 'should handle text/json' do
|
405
|
-
["text/json", "text/json; charset=iso8859-1"].each do |ct|
|
406
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:json)
|
407
|
-
end
|
408
|
-
end
|
409
|
-
|
410
|
-
it 'should handle application/vnd.api+json' do
|
411
|
-
["application/vnd.api+json", "application/vnd.api+json; charset=iso8859-1"].each do |ct|
|
412
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:json)
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
it 'should handle application/hal+json' do
|
417
|
-
["application/hal+json", "application/hal+json; charset=iso8859-1"].each do |ct|
|
418
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:json)
|
419
|
-
end
|
420
|
-
end
|
421
|
-
|
422
|
-
it 'should handle application/json' do
|
423
|
-
["application/json", "application/json; charset=iso8859-1"].each do |ct|
|
424
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:json)
|
425
|
-
end
|
426
|
-
end
|
427
|
-
|
428
|
-
it 'should handle text/csv' do
|
429
|
-
["text/csv", "text/csv; charset=iso8859-1"].each do |ct|
|
430
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:csv)
|
431
|
-
end
|
432
|
-
end
|
433
|
-
|
434
|
-
it 'should handle application/csv' do
|
435
|
-
["application/csv", "application/csv; charset=iso8859-1"].each do |ct|
|
436
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:csv)
|
437
|
-
end
|
438
|
-
end
|
439
|
-
|
440
|
-
it 'should handle text/comma-separated-values' do
|
441
|
-
["text/comma-separated-values", "text/comma-separated-values; charset=iso8859-1"].each do |ct|
|
442
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:csv)
|
443
|
-
end
|
444
|
-
end
|
445
|
-
|
446
|
-
it 'should handle text/javascript' do
|
447
|
-
["text/javascript", "text/javascript; charset=iso8859-1"].each do |ct|
|
448
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:plain)
|
449
|
-
end
|
450
|
-
end
|
451
|
-
|
452
|
-
it 'should handle application/javascript' do
|
453
|
-
["application/javascript", "application/javascript; charset=iso8859-1"].each do |ct|
|
454
|
-
expect(@request.send(:format_from_mimetype, ct)).to eq(:plain)
|
455
|
-
end
|
456
|
-
end
|
457
|
-
|
458
|
-
it "returns nil for an unrecognized mimetype" do
|
459
|
-
expect(@request.send(:format_from_mimetype, "application/atom+xml")).to be_nil
|
460
|
-
end
|
461
|
-
|
462
|
-
it "returns nil when using a default parser" do
|
463
|
-
@request.options[:parser] = lambda {}
|
464
|
-
expect(@request.send(:format_from_mimetype, "text/json")).to be_nil
|
465
|
-
end
|
466
|
-
end
|
467
|
-
|
468
|
-
describe 'parsing responses' do
|
469
|
-
it 'should handle xml automatically' do
|
470
|
-
xml = '<books><book><id>1234</id><name>Foo Bar!</name></book></books>'
|
471
|
-
@request.options[:format] = :xml
|
472
|
-
expect(@request.send(:parse_response, xml)).to eq({'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}})
|
473
|
-
end
|
474
|
-
|
475
|
-
it 'should handle utf-8 bom in xml' do
|
476
|
-
xml = "\xEF\xBB\xBF<books><book><id>1234</id><name>Foo Bar!</name></book></books>"
|
477
|
-
@request.options[:format] = :xml
|
478
|
-
expect(@request.send(:parse_response, xml)).to eq({'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}})
|
479
|
-
end
|
480
|
-
|
481
|
-
it 'should handle csv automatically' do
|
482
|
-
csv = ['"id","Name"', '"1234","Foo Bar!"'].join("\n")
|
483
|
-
@request.options[:format] = :csv
|
484
|
-
expect(@request.send(:parse_response, csv)).to eq([%w(id Name), ["1234", "Foo Bar!"]])
|
485
|
-
end
|
486
|
-
|
487
|
-
it 'should handle json automatically' do
|
488
|
-
json = '{"books": {"book": {"name": "Foo Bar!", "id": "1234"}}}'
|
489
|
-
@request.options[:format] = :json
|
490
|
-
expect(@request.send(:parse_response, json)).to eq({'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}})
|
491
|
-
end
|
492
|
-
|
493
|
-
it 'should handle utf-8 bom in json' do
|
494
|
-
json = "\xEF\xBB\xBF{\"books\": {\"book\": {\"name\": \"Foo Bar!\", \"id\": \"1234\"}}}"
|
495
|
-
@request.options[:format] = :json
|
496
|
-
expect(@request.send(:parse_response, json)).to eq({'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}})
|
497
|
-
end
|
498
|
-
|
499
|
-
it "should include any HTTP headers in the returned response" do
|
500
|
-
@request.options[:format] = :html
|
501
|
-
response = stub_response "Content"
|
502
|
-
response.initialize_http_header("key" => "value")
|
503
|
-
|
504
|
-
expect(@request.perform.headers).to eq({ "key" => ["value"] })
|
505
|
-
end
|
506
|
-
|
507
|
-
if "".respond_to?(:encoding)
|
508
|
-
context 'when body has ascii-8bit encoding' do
|
509
|
-
let(:response) { stub_response "Content".force_encoding('ascii-8bit') }
|
510
|
-
|
511
|
-
it "processes charset in content type properly" do
|
512
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-8")
|
513
|
-
resp = @request.perform
|
514
|
-
|
515
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-8"))
|
516
|
-
end
|
517
|
-
|
518
|
-
it "processes charset in content type properly if it has a different case" do
|
519
|
-
response.initialize_http_header("Content-Type" => "text/plain;CHARSET = utf-8")
|
520
|
-
resp = @request.perform
|
521
|
-
|
522
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-8"))
|
523
|
-
end
|
524
|
-
|
525
|
-
it "processes quoted charset in content type properly" do
|
526
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = \"utf-8\"")
|
527
|
-
resp = @request.perform
|
528
|
-
|
529
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-8"))
|
530
|
-
end
|
531
|
-
|
532
|
-
context 'when stubed body is frozen' do
|
533
|
-
let(:response) do
|
534
|
-
stub_response "Content".force_encoding('ascii-8bit').freeze
|
535
|
-
end
|
536
|
-
|
537
|
-
it 'processes frozen body correctly' do
|
538
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-8")
|
539
|
-
resp = @request.perform
|
540
|
-
|
541
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-8"))
|
542
|
-
end
|
543
|
-
end
|
544
|
-
end
|
545
|
-
|
546
|
-
it "should process response with a nil body" do
|
547
|
-
response = stub_response nil
|
548
|
-
response.initialize_http_header("Content-Type" => "text/html;charset=UTF-8")
|
549
|
-
resp = @request.perform
|
550
|
-
|
551
|
-
expect(resp.body).to be_nil
|
552
|
-
end
|
553
|
-
|
554
|
-
context 'when assume_utf16_is_big_endian is true' do
|
555
|
-
before { @request.options[:assume_utf16_is_big_endian] = true }
|
556
|
-
|
557
|
-
it "should process utf-16 charset with little endian bom correctly" do
|
558
|
-
response = stub_response "\xFF\xFEC\x00o\x00n\x00t\x00e\x00n\x00t\x00"
|
559
|
-
|
560
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-16")
|
561
|
-
resp = @request.perform
|
562
|
-
|
563
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-16LE"))
|
564
|
-
end
|
565
|
-
|
566
|
-
it 'processes stubbed frozen body correctly' do
|
567
|
-
response = stub_response "\xFF\xFEC\x00o\x00n\x00t\x00e\x00n\x00t\x00".freeze
|
568
|
-
|
569
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-16")
|
570
|
-
resp = @request.perform
|
571
|
-
|
572
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-16LE"))
|
573
|
-
end
|
574
|
-
end
|
575
|
-
|
576
|
-
it "should process utf-16 charset with big endian bom correctly" do
|
577
|
-
@request.options[:assume_utf16_is_big_endian] = false
|
578
|
-
|
579
|
-
response = stub_response "\xFE\xFF\x00C\x00o\x00n\x00t\x00e\x00n\x00t"
|
580
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-16")
|
581
|
-
resp = @request.perform
|
582
|
-
|
583
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-16BE"))
|
584
|
-
end
|
585
|
-
|
586
|
-
it "should assume utf-16 little endian if options has been chosen" do
|
587
|
-
@request.options[:assume_utf16_is_big_endian] = false
|
588
|
-
|
589
|
-
response = stub_response "C\x00o\x00n\x00t\x00e\x00n\x00t\x00"
|
590
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-16")
|
591
|
-
resp = @request.perform
|
592
|
-
|
593
|
-
expect(resp.body.encoding).to eq(Encoding.find("UTF-16LE"))
|
594
|
-
end
|
595
|
-
|
596
|
-
it "should perform no encoding if the charset is not available" do
|
597
|
-
response = stub_response "Content"
|
598
|
-
response.initialize_http_header("Content-Type" => "text/plain;charset = utf-lols")
|
599
|
-
resp = @request.perform
|
600
|
-
|
601
|
-
# This encoding does not exist, thus the string should not be encodd with it
|
602
|
-
|
603
|
-
expect(resp.body).to eq("Content")
|
604
|
-
expect(resp.body.encoding).to eq("Content".encoding)
|
605
|
-
end
|
606
|
-
|
607
|
-
it "should perform no encoding if the content type is specified but no charset is specified" do
|
608
|
-
response = stub_response "Content"
|
609
|
-
response.initialize_http_header("Content-Type" => "text/plain")
|
610
|
-
resp = @request.perform
|
611
|
-
|
612
|
-
expect(resp.body).to eq("Content")
|
613
|
-
expect(resp.body.encoding).to eq("Content".encoding)
|
614
|
-
end
|
615
|
-
end
|
616
|
-
|
617
|
-
describe 'with non-200 responses' do
|
618
|
-
context "3xx responses" do
|
619
|
-
it 'returns a valid object for 304 not modified' do
|
620
|
-
stub_response '', 304
|
621
|
-
resp = @request.perform
|
622
|
-
expect(resp.code).to eq(304)
|
623
|
-
expect(resp.body).to eq('')
|
624
|
-
expect(resp).to be_nil
|
625
|
-
end
|
626
|
-
|
627
|
-
it "redirects if a 300 contains a location header" do
|
628
|
-
redirect = stub_response '', 300
|
629
|
-
redirect['location'] = 'http://foo.com/foo'
|
630
|
-
ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
631
|
-
allow(@http).to receive(:request).and_return(redirect, ok)
|
632
|
-
response = @request.perform
|
633
|
-
expect(response.request.base_uri.to_s).to eq("http://foo.com")
|
634
|
-
expect(response.request.path.to_s).to eq("http://foo.com/foo")
|
635
|
-
expect(response.request.uri.request_uri).to eq("/foo")
|
636
|
-
expect(response.request.uri.to_s).to eq("http://foo.com/foo")
|
637
|
-
expect(response.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
638
|
-
end
|
639
|
-
|
640
|
-
it "calls block given to perform with each redirect" do
|
641
|
-
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://test.com/redirect', format: :xml)
|
642
|
-
stub_request(:get, 'http://test.com/redirect')
|
643
|
-
.to_return(
|
644
|
-
status: [300, 'REDIRECT'],
|
645
|
-
headers: { location: 'http://api.foo.com/v2' }
|
646
|
-
)
|
647
|
-
stub_request(:get, 'http://api.foo.com/v2')
|
648
|
-
.to_return(body: '<hash><foo>bar</foo></hash>')
|
649
|
-
body = ""
|
650
|
-
@request.perform { |chunk| body += chunk }
|
651
|
-
expect(body.length).to eq(27)
|
652
|
-
end
|
653
|
-
|
654
|
-
it "redirects if a 300 contains a relative location header" do
|
655
|
-
redirect = stub_response '', 300
|
656
|
-
redirect['location'] = '/foo/bar'
|
657
|
-
ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
658
|
-
allow(@http).to receive(:request).and_return(redirect, ok)
|
659
|
-
response = @request.perform
|
660
|
-
expect(response.request.base_uri.to_s).to eq("http://api.foo.com")
|
661
|
-
expect(response.request.path.to_s).to eq("/foo/bar")
|
662
|
-
expect(response.request.uri.request_uri).to eq("/foo/bar")
|
663
|
-
expect(response.request.uri.to_s).to eq("http://api.foo.com/foo/bar")
|
664
|
-
expect(response.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
665
|
-
end
|
666
|
-
|
667
|
-
it "handles multiple redirects and relative location headers on different hosts" do
|
668
|
-
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://test.com/redirect', format: :xml)
|
669
|
-
stub_request(:get, 'http://test.com/redirect')
|
670
|
-
.to_return(
|
671
|
-
status: [300, 'REDIRECT'],
|
672
|
-
headers: { location: "http://api.foo.com/v2" }
|
673
|
-
)
|
674
|
-
stub_request(:get, 'http://api.foo.com/v2')
|
675
|
-
.to_return(
|
676
|
-
status: [300, 'REDIRECT'],
|
677
|
-
headers: { location: '/v3' }
|
678
|
-
)
|
679
|
-
stub_request(:get, 'http://api.foo.com/v3')
|
680
|
-
.to_return(body: '<hash><foo>bar</foo></hash>')
|
681
|
-
response = @request.perform
|
682
|
-
expect(response.request.base_uri.to_s).to eq("http://api.foo.com")
|
683
|
-
expect(response.request.path.to_s).to eq("/v3")
|
684
|
-
expect(response.request.uri.request_uri).to eq("/v3")
|
685
|
-
expect(response.request.uri.to_s).to eq("http://api.foo.com/v3")
|
686
|
-
expect(response.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
687
|
-
end
|
688
|
-
|
689
|
-
it "raises an error if redirect has duplicate location header" do
|
690
|
-
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://test.com/redirect', format: :xml)
|
691
|
-
stub_request(:get, 'http://test.com/redirect')
|
692
|
-
.to_return(
|
693
|
-
status: [300, 'REDIRECT'],
|
694
|
-
headers: {
|
695
|
-
location: ['http://api.foo.com/v2', 'http://api.foo.com/v2']
|
696
|
-
}
|
697
|
-
)
|
698
|
-
expect {@request.perform}.to raise_error(HTTParty::DuplicateLocationHeader)
|
699
|
-
end
|
700
|
-
|
701
|
-
it "returns the HTTParty::Response when the 300 does not contain a location header" do
|
702
|
-
stub_response '', 300
|
703
|
-
expect(HTTParty::Response).to be === @request.perform
|
704
|
-
end
|
705
|
-
|
706
|
-
it "redirects including port" do
|
707
|
-
stub_request(:get, 'http://withport.com:3000/v1')
|
708
|
-
.to_return(
|
709
|
-
status: [301, 'Moved Permanently'],
|
710
|
-
headers: { location: 'http://withport.com:3000/v2' }
|
711
|
-
)
|
712
|
-
stub_request(:get, 'http://withport.com:3000/v2')
|
713
|
-
.to_return(status: 200)
|
714
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://withport.com:3000/v1')
|
715
|
-
response = request.perform
|
716
|
-
expect(response.request.base_uri.to_s).to eq("http://withport.com:3000")
|
717
|
-
end
|
718
|
-
end
|
719
|
-
|
720
|
-
it 'should return a valid object for 4xx response' do
|
721
|
-
stub_response '<foo><bar>yes</bar></foo>', 401
|
722
|
-
resp = @request.perform
|
723
|
-
expect(resp.code).to eq(401)
|
724
|
-
expect(resp.body).to eq("<foo><bar>yes</bar></foo>")
|
725
|
-
expect(resp['foo']['bar']).to eq("yes")
|
726
|
-
end
|
727
|
-
|
728
|
-
it 'should return a valid object for 5xx response' do
|
729
|
-
stub_response '<foo><bar>error</bar></foo>', 500
|
730
|
-
resp = @request.perform
|
731
|
-
expect(resp.code).to eq(500)
|
732
|
-
expect(resp.body).to eq("<foo><bar>error</bar></foo>")
|
733
|
-
expect(resp['foo']['bar']).to eq("error")
|
734
|
-
end
|
735
|
-
|
736
|
-
it "parses response lazily so codes can be checked prior" do
|
737
|
-
stub_response 'not xml', 500
|
738
|
-
@request.options[:format] = :xml
|
739
|
-
expect {
|
740
|
-
response = @request.perform
|
741
|
-
expect(response.code).to eq(500)
|
742
|
-
expect(response.body).to eq('not xml')
|
743
|
-
}.not_to raise_error
|
744
|
-
end
|
745
|
-
end
|
746
|
-
end
|
747
|
-
|
748
|
-
it "should not attempt to parse empty responses" do
|
749
|
-
[204, 304].each do |code|
|
750
|
-
stub_response "", code
|
751
|
-
|
752
|
-
@request.options[:format] = :xml
|
753
|
-
expect(@request.perform).to be_nil
|
754
|
-
end
|
755
|
-
end
|
756
|
-
|
757
|
-
it "should not fail for missing mime type" do
|
758
|
-
stub_response "Content for you"
|
759
|
-
@request.options[:format] = :html
|
760
|
-
expect(@request.perform.parsed_response).to eq('Content for you')
|
761
|
-
end
|
762
|
-
|
763
|
-
[300, 301, 302, 305].each do |code|
|
764
|
-
describe "a request that #{code} redirects" do
|
765
|
-
before(:each) do
|
766
|
-
@redirect = stub_response("", code)
|
767
|
-
@redirect['location'] = '/foo'
|
768
|
-
|
769
|
-
@ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
770
|
-
end
|
771
|
-
|
772
|
-
describe "once" do
|
773
|
-
before(:each) do
|
774
|
-
allow(@http).to receive(:request).and_return(@redirect, @ok)
|
775
|
-
end
|
776
|
-
|
777
|
-
it "should be handled by GET transparently" do
|
778
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
779
|
-
end
|
780
|
-
|
781
|
-
it "should be handled by POST transparently" do
|
782
|
-
@request.http_method = Net::HTTP::Post
|
783
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
784
|
-
end
|
785
|
-
|
786
|
-
it "should be handled by DELETE transparently" do
|
787
|
-
@request.http_method = Net::HTTP::Delete
|
788
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
789
|
-
end
|
790
|
-
|
791
|
-
it "should be handled by MOVE transparently" do
|
792
|
-
@request.http_method = Net::HTTP::Move
|
793
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
794
|
-
end
|
795
|
-
|
796
|
-
it "should be handled by COPY transparently" do
|
797
|
-
@request.http_method = Net::HTTP::Copy
|
798
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
799
|
-
end
|
800
|
-
|
801
|
-
it "should be handled by PATCH transparently" do
|
802
|
-
@request.http_method = Net::HTTP::Patch
|
803
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
804
|
-
end
|
805
|
-
|
806
|
-
it "should be handled by PUT transparently" do
|
807
|
-
@request.http_method = Net::HTTP::Put
|
808
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
809
|
-
end
|
810
|
-
|
811
|
-
it "should be handled by HEAD transparently" do
|
812
|
-
@request.http_method = Net::HTTP::Head
|
813
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
814
|
-
end
|
815
|
-
|
816
|
-
it "should be handled by OPTIONS transparently" do
|
817
|
-
@request.http_method = Net::HTTP::Options
|
818
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
819
|
-
end
|
820
|
-
|
821
|
-
it "should be handled by MKCOL transparently" do
|
822
|
-
@request.http_method = Net::HTTP::Mkcol
|
823
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
824
|
-
end
|
825
|
-
|
826
|
-
it "should be handled by LOCK transparently" do
|
827
|
-
@request.http_method = Net::HTTP::Lock
|
828
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
829
|
-
end
|
830
|
-
|
831
|
-
it "should be handled by UNLOCK transparently" do
|
832
|
-
@request.http_method = Net::HTTP::Unlock
|
833
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
834
|
-
end
|
835
|
-
|
836
|
-
it "should keep track of cookies between redirects" do
|
837
|
-
@redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
|
838
|
-
@request.perform
|
839
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
840
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
841
|
-
end
|
842
|
-
|
843
|
-
it 'should update cookies with redirects' do
|
844
|
-
@request.options[:headers] = {'Cookie' => 'foo=bar;'}
|
845
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
846
|
-
@request.perform
|
847
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=tar/)
|
848
|
-
end
|
849
|
-
|
850
|
-
it 'should keep cookies between redirects' do
|
851
|
-
@request.options[:headers] = {'Cookie' => 'keep=me'}
|
852
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
853
|
-
@request.perform
|
854
|
-
expect(@request.options[:headers]['Cookie']).to match(/keep=me/)
|
855
|
-
end
|
856
|
-
|
857
|
-
it "should handle multiple Set-Cookie headers between redirects" do
|
858
|
-
@redirect.add_field 'set-cookie', 'foo=bar; name=value; HTTPOnly'
|
859
|
-
@redirect.add_field 'set-cookie', 'one=1; two=2; HTTPOnly'
|
860
|
-
@request.perform
|
861
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
862
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
863
|
-
expect(@request.options[:headers]['Cookie']).to match(/one=1/)
|
864
|
-
expect(@request.options[:headers]['Cookie']).to match(/two=2/)
|
865
|
-
end
|
866
|
-
|
867
|
-
it 'should make resulting request a get request if it not already' do
|
868
|
-
@request.http_method = Net::HTTP::Delete
|
869
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
870
|
-
expect(@request.http_method).to eq(Net::HTTP::Get)
|
871
|
-
end
|
872
|
-
|
873
|
-
it 'should not make resulting request a get request if options[:maintain_method_across_redirects] is true' do
|
874
|
-
@request.options[:maintain_method_across_redirects] = true
|
875
|
-
@request.http_method = Net::HTTP::Delete
|
876
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
877
|
-
expect(@request.http_method).to eq(Net::HTTP::Delete)
|
878
|
-
end
|
879
|
-
|
880
|
-
it 'should log the redirection' do
|
881
|
-
logger_double = double
|
882
|
-
expect(logger_double).to receive(:info).twice
|
883
|
-
@request.options[:logger] = logger_double
|
884
|
-
@request.perform
|
885
|
-
end
|
886
|
-
end
|
887
|
-
|
888
|
-
describe "infinitely" do
|
889
|
-
before(:each) do
|
890
|
-
allow(@http).to receive(:request).and_return(@redirect)
|
891
|
-
end
|
892
|
-
|
893
|
-
it "should raise an exception" do
|
894
|
-
expect { @request.perform }.to raise_error(HTTParty::RedirectionTooDeep)
|
895
|
-
end
|
896
|
-
end
|
897
|
-
end
|
898
|
-
end
|
899
|
-
|
900
|
-
describe "a request that 303 redirects" do
|
901
|
-
before(:each) do
|
902
|
-
@redirect = stub_response("", 303)
|
903
|
-
@redirect['location'] = '/foo'
|
904
|
-
|
905
|
-
@ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
906
|
-
end
|
907
|
-
|
908
|
-
describe "once" do
|
909
|
-
before(:each) do
|
910
|
-
allow(@http).to receive(:request).and_return(@redirect, @ok)
|
911
|
-
end
|
912
|
-
|
913
|
-
it "should be handled by GET transparently" do
|
914
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
915
|
-
end
|
916
|
-
|
917
|
-
it "should be handled by POST transparently" do
|
918
|
-
@request.http_method = Net::HTTP::Post
|
919
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
920
|
-
end
|
921
|
-
|
922
|
-
it "should be handled by DELETE transparently" do
|
923
|
-
@request.http_method = Net::HTTP::Delete
|
924
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
925
|
-
end
|
926
|
-
|
927
|
-
it "should be handled by MOVE transparently" do
|
928
|
-
@request.http_method = Net::HTTP::Move
|
929
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
930
|
-
end
|
931
|
-
|
932
|
-
it "should be handled by COPY transparently" do
|
933
|
-
@request.http_method = Net::HTTP::Copy
|
934
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
935
|
-
end
|
936
|
-
|
937
|
-
it "should be handled by PATCH transparently" do
|
938
|
-
@request.http_method = Net::HTTP::Patch
|
939
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
940
|
-
end
|
941
|
-
|
942
|
-
it "should be handled by PUT transparently" do
|
943
|
-
@request.http_method = Net::HTTP::Put
|
944
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
945
|
-
end
|
946
|
-
|
947
|
-
it "should be handled by HEAD transparently" do
|
948
|
-
@request.http_method = Net::HTTP::Head
|
949
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
950
|
-
end
|
951
|
-
|
952
|
-
it "should be handled by OPTIONS transparently" do
|
953
|
-
@request.http_method = Net::HTTP::Options
|
954
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
955
|
-
end
|
956
|
-
|
957
|
-
it "should be handled by MKCOL transparently" do
|
958
|
-
@request.http_method = Net::HTTP::Mkcol
|
959
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
960
|
-
end
|
961
|
-
|
962
|
-
it "should be handled by LOCK transparently" do
|
963
|
-
@request.http_method = Net::HTTP::Lock
|
964
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
965
|
-
end
|
966
|
-
|
967
|
-
it "should be handled by UNLOCK transparently" do
|
968
|
-
@request.http_method = Net::HTTP::Unlock
|
969
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
970
|
-
end
|
971
|
-
|
972
|
-
it "should keep track of cookies between redirects" do
|
973
|
-
@redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
|
974
|
-
@request.perform
|
975
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
976
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
977
|
-
end
|
978
|
-
|
979
|
-
it 'should update cookies with redirects' do
|
980
|
-
@request.options[:headers] = {'Cookie' => 'foo=bar;'}
|
981
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
982
|
-
@request.perform
|
983
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=tar/)
|
984
|
-
end
|
985
|
-
|
986
|
-
it 'should keep cookies between redirects' do
|
987
|
-
@request.options[:headers] = {'Cookie' => 'keep=me'}
|
988
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
989
|
-
@request.perform
|
990
|
-
expect(@request.options[:headers]['Cookie']).to match(/keep=me/)
|
991
|
-
end
|
992
|
-
|
993
|
-
it "should handle multiple Set-Cookie headers between redirects" do
|
994
|
-
@redirect.add_field 'set-cookie', 'foo=bar; name=value; HTTPOnly'
|
995
|
-
@redirect.add_field 'set-cookie', 'one=1; two=2; HTTPOnly'
|
996
|
-
@request.perform
|
997
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
998
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
999
|
-
expect(@request.options[:headers]['Cookie']).to match(/one=1/)
|
1000
|
-
expect(@request.options[:headers]['Cookie']).to match(/two=2/)
|
1001
|
-
end
|
1002
|
-
|
1003
|
-
it 'should make resulting request a get request if it not already' do
|
1004
|
-
@request.http_method = Net::HTTP::Delete
|
1005
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1006
|
-
expect(@request.http_method).to eq(Net::HTTP::Get)
|
1007
|
-
end
|
1008
|
-
|
1009
|
-
it 'should make resulting request a get request if options[:maintain_method_across_redirects] is false' do
|
1010
|
-
@request.options[:maintain_method_across_redirects] = false
|
1011
|
-
@request.http_method = Net::HTTP::Delete
|
1012
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1013
|
-
expect(@request.http_method).to eq(Net::HTTP::Get)
|
1014
|
-
end
|
1015
|
-
|
1016
|
-
it 'should make resulting request a get request if options[:maintain_method_across_redirects] is true but options[:resend_on_redirect] is false' do
|
1017
|
-
@request.options[:maintain_method_across_redirects] = true
|
1018
|
-
@request.options[:resend_on_redirect] = false
|
1019
|
-
@request.http_method = Net::HTTP::Delete
|
1020
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1021
|
-
expect(@request.http_method).to eq(Net::HTTP::Get)
|
1022
|
-
end
|
1023
|
-
|
1024
|
-
it 'should not make resulting request a get request if options[:maintain_method_across_redirects] and options[:resend_on_redirect] is true' do
|
1025
|
-
@request.options[:maintain_method_across_redirects] = true
|
1026
|
-
@request.options[:resend_on_redirect] = true
|
1027
|
-
@request.http_method = Net::HTTP::Delete
|
1028
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1029
|
-
expect(@request.http_method).to eq(Net::HTTP::Delete)
|
1030
|
-
end
|
1031
|
-
|
1032
|
-
it 'should log the redirection' do
|
1033
|
-
logger_double = double
|
1034
|
-
expect(logger_double).to receive(:info).twice
|
1035
|
-
@request.options[:logger] = logger_double
|
1036
|
-
@request.perform
|
1037
|
-
end
|
1038
|
-
end
|
1039
|
-
|
1040
|
-
describe "infinitely" do
|
1041
|
-
before(:each) do
|
1042
|
-
allow(@http).to receive(:request).and_return(@redirect)
|
1043
|
-
end
|
1044
|
-
|
1045
|
-
it "should raise an exception" do
|
1046
|
-
expect { @request.perform }.to raise_error(HTTParty::RedirectionTooDeep)
|
1047
|
-
end
|
1048
|
-
end
|
1049
|
-
end
|
1050
|
-
|
1051
|
-
describe "a request that returns 304" do
|
1052
|
-
before(:each) do
|
1053
|
-
@redirect = stub_response("", 304)
|
1054
|
-
@redirect['location'] = '/foo'
|
1055
|
-
end
|
1056
|
-
|
1057
|
-
before(:each) do
|
1058
|
-
allow(@http).to receive(:request).and_return(@redirect)
|
1059
|
-
end
|
1060
|
-
|
1061
|
-
it "should report 304 with a GET request" do
|
1062
|
-
expect(@request.perform.code).to eq(304)
|
1063
|
-
end
|
1064
|
-
|
1065
|
-
it "should report 304 with a POST request" do
|
1066
|
-
@request.http_method = Net::HTTP::Post
|
1067
|
-
expect(@request.perform.code).to eq(304)
|
1068
|
-
end
|
1069
|
-
|
1070
|
-
it "should report 304 with a DELETE request" do
|
1071
|
-
@request.http_method = Net::HTTP::Delete
|
1072
|
-
expect(@request.perform.code).to eq(304)
|
1073
|
-
end
|
1074
|
-
|
1075
|
-
it "should report 304 with a MOVE request" do
|
1076
|
-
@request.http_method = Net::HTTP::Move
|
1077
|
-
expect(@request.perform.code).to eq(304)
|
1078
|
-
end
|
1079
|
-
|
1080
|
-
it "should report 304 with a COPY request" do
|
1081
|
-
@request.http_method = Net::HTTP::Copy
|
1082
|
-
expect(@request.perform.code).to eq(304)
|
1083
|
-
end
|
1084
|
-
|
1085
|
-
it "should report 304 with a PATCH request" do
|
1086
|
-
@request.http_method = Net::HTTP::Patch
|
1087
|
-
expect(@request.perform.code).to eq(304)
|
1088
|
-
end
|
1089
|
-
|
1090
|
-
it "should report 304 with a PUT request" do
|
1091
|
-
@request.http_method = Net::HTTP::Put
|
1092
|
-
expect(@request.perform.code).to eq(304)
|
1093
|
-
end
|
1094
|
-
|
1095
|
-
it "should report 304 with a HEAD request" do
|
1096
|
-
@request.http_method = Net::HTTP::Head
|
1097
|
-
expect(@request.perform.code).to eq(304)
|
1098
|
-
end
|
1099
|
-
|
1100
|
-
it "should report 304 with a OPTIONS request" do
|
1101
|
-
@request.http_method = Net::HTTP::Options
|
1102
|
-
expect(@request.perform.code).to eq(304)
|
1103
|
-
end
|
1104
|
-
|
1105
|
-
it "should report 304 with a MKCOL request" do
|
1106
|
-
@request.http_method = Net::HTTP::Mkcol
|
1107
|
-
expect(@request.perform.code).to eq(304)
|
1108
|
-
end
|
1109
|
-
|
1110
|
-
it "should be handled by LOCK transparently" do
|
1111
|
-
@request.http_method = Net::HTTP::Lock
|
1112
|
-
expect(@request.perform.code).to eq(304)
|
1113
|
-
end
|
1114
|
-
|
1115
|
-
it "should be handled by UNLOCK transparently" do
|
1116
|
-
@request.http_method = Net::HTTP::Unlock
|
1117
|
-
expect(@request.perform.code).to eq(304)
|
1118
|
-
end
|
1119
|
-
|
1120
|
-
it 'should not log the redirection' do
|
1121
|
-
logger_double = double
|
1122
|
-
expect(logger_double).to receive(:info).once
|
1123
|
-
@request.options[:logger] = logger_double
|
1124
|
-
@request.perform
|
1125
|
-
end
|
1126
|
-
end
|
1127
|
-
|
1128
|
-
[307, 308].each do |code|
|
1129
|
-
describe "a request that #{code} redirects" do
|
1130
|
-
before(:each) do
|
1131
|
-
@redirect = stub_response("", code)
|
1132
|
-
@redirect['location'] = '/foo'
|
1133
|
-
|
1134
|
-
@ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
1135
|
-
end
|
1136
|
-
|
1137
|
-
describe "once" do
|
1138
|
-
before(:each) do
|
1139
|
-
allow(@http).to receive(:request).and_return(@redirect, @ok)
|
1140
|
-
end
|
1141
|
-
|
1142
|
-
it "should be handled by GET transparently" do
|
1143
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1144
|
-
end
|
1145
|
-
|
1146
|
-
it "should be handled by POST transparently" do
|
1147
|
-
@request.http_method = Net::HTTP::Post
|
1148
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1149
|
-
end
|
1150
|
-
|
1151
|
-
it "should be handled by DELETE transparently" do
|
1152
|
-
@request.http_method = Net::HTTP::Delete
|
1153
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1154
|
-
end
|
1155
|
-
|
1156
|
-
it "should be handled by MOVE transparently" do
|
1157
|
-
@request.http_method = Net::HTTP::Move
|
1158
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1159
|
-
end
|
1160
|
-
|
1161
|
-
it "should be handled by COPY transparently" do
|
1162
|
-
@request.http_method = Net::HTTP::Copy
|
1163
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1164
|
-
end
|
1165
|
-
|
1166
|
-
it "should be handled by PATCH transparently" do
|
1167
|
-
@request.http_method = Net::HTTP::Patch
|
1168
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1169
|
-
end
|
1170
|
-
|
1171
|
-
it "should be handled by PUT transparently" do
|
1172
|
-
@request.http_method = Net::HTTP::Put
|
1173
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1174
|
-
end
|
1175
|
-
|
1176
|
-
it "should be handled by HEAD transparently" do
|
1177
|
-
@request.http_method = Net::HTTP::Head
|
1178
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1179
|
-
end
|
1180
|
-
|
1181
|
-
it "should be handled by OPTIONS transparently" do
|
1182
|
-
@request.http_method = Net::HTTP::Options
|
1183
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1184
|
-
end
|
1185
|
-
|
1186
|
-
it "should be handled by MKCOL transparently" do
|
1187
|
-
@request.http_method = Net::HTTP::Mkcol
|
1188
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1189
|
-
end
|
1190
|
-
|
1191
|
-
it "should be handled by LOCK transparently" do
|
1192
|
-
@request.http_method = Net::HTTP::Lock
|
1193
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1194
|
-
end
|
1195
|
-
|
1196
|
-
it "should be handled by UNLOCK transparently" do
|
1197
|
-
@request.http_method = Net::HTTP::Unlock
|
1198
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1199
|
-
end
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
it "should keep track of cookies between redirects" do
|
1204
|
-
@redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
|
1205
|
-
@request.perform
|
1206
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
1207
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
1208
|
-
end
|
1209
|
-
|
1210
|
-
it 'should update cookies with redirects' do
|
1211
|
-
@request.options[:headers] = {'Cookie' => 'foo=bar;'}
|
1212
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
1213
|
-
@request.perform
|
1214
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=tar/)
|
1215
|
-
end
|
1216
|
-
|
1217
|
-
it 'should keep cookies between redirects' do
|
1218
|
-
@request.options[:headers] = {'Cookie' => 'keep=me'}
|
1219
|
-
@redirect['Set-Cookie'] = 'foo=tar;'
|
1220
|
-
@request.perform
|
1221
|
-
expect(@request.options[:headers]['Cookie']).to match(/keep=me/)
|
1222
|
-
end
|
1223
|
-
|
1224
|
-
it "should handle multiple Set-Cookie headers between redirects" do
|
1225
|
-
@redirect.add_field 'set-cookie', 'foo=bar; name=value; HTTPOnly'
|
1226
|
-
@redirect.add_field 'set-cookie', 'one=1; two=2; HTTPOnly'
|
1227
|
-
@request.perform
|
1228
|
-
expect(@request.options[:headers]['Cookie']).to match(/foo=bar/)
|
1229
|
-
expect(@request.options[:headers]['Cookie']).to match(/name=value/)
|
1230
|
-
expect(@request.options[:headers]['Cookie']).to match(/one=1/)
|
1231
|
-
expect(@request.options[:headers]['Cookie']).to match(/two=2/)
|
1232
|
-
end
|
1233
|
-
|
1234
|
-
it 'should maintain method in resulting request' do
|
1235
|
-
@request.http_method = Net::HTTP::Delete
|
1236
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1237
|
-
expect(@request.http_method).to eq(Net::HTTP::Delete)
|
1238
|
-
end
|
1239
|
-
|
1240
|
-
it 'should maintain method in resulting request if options[:maintain_method_across_redirects] is false' do
|
1241
|
-
@request.options[:maintain_method_across_redirects] = false
|
1242
|
-
@request.http_method = Net::HTTP::Delete
|
1243
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1244
|
-
expect(@request.http_method).to eq(Net::HTTP::Delete)
|
1245
|
-
end
|
1246
|
-
|
1247
|
-
it 'should maintain method in resulting request if options[:maintain_method_across_redirects] is true' do
|
1248
|
-
@request.options[:maintain_method_across_redirects] = true
|
1249
|
-
@request.http_method = Net::HTTP::Delete
|
1250
|
-
expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
|
1251
|
-
expect(@request.http_method).to eq(Net::HTTP::Delete)
|
1252
|
-
end
|
1253
|
-
|
1254
|
-
it 'should log the redirection' do
|
1255
|
-
logger_double = double
|
1256
|
-
expect(logger_double).to receive(:info).twice
|
1257
|
-
@request.options[:logger] = logger_double
|
1258
|
-
@request.perform
|
1259
|
-
end
|
1260
|
-
end
|
1261
|
-
|
1262
|
-
describe "infinitely" do
|
1263
|
-
before(:each) do
|
1264
|
-
allow(@http).to receive(:request).and_return(@redirect)
|
1265
|
-
end
|
1266
|
-
|
1267
|
-
it "should raise an exception" do
|
1268
|
-
expect { @request.perform }.to raise_error(HTTParty::RedirectionTooDeep)
|
1269
|
-
end
|
1270
|
-
end
|
1271
|
-
end
|
1272
|
-
end
|
1273
|
-
|
1274
|
-
describe "#send_authorization_header?" do
|
1275
|
-
context "basic_auth" do
|
1276
|
-
before do
|
1277
|
-
@credentials = { username: "username", password: "password" }
|
1278
|
-
@authorization = "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
|
1279
|
-
@request.options[:basic_auth] = @credentials
|
1280
|
-
@redirect = stub_response("", 302)
|
1281
|
-
@ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
1282
|
-
end
|
1283
|
-
|
1284
|
-
before(:each) do
|
1285
|
-
allow(@http).to receive(:request).and_return(@redirect, @ok)
|
1286
|
-
end
|
1287
|
-
|
1288
|
-
it "should not send Authorization header when redirecting to a different host" do
|
1289
|
-
@redirect['location'] = 'http://example.com/'
|
1290
|
-
@request.perform
|
1291
|
-
@request.send(:setup_raw_request)
|
1292
|
-
expect(@request.instance_variable_get(:@raw_request)['authorization']).to be_nil
|
1293
|
-
end
|
1294
|
-
|
1295
|
-
it "should send Authorization header when redirecting to a relative path" do
|
1296
|
-
@redirect['location'] = '/v3'
|
1297
|
-
@request.perform
|
1298
|
-
@request.send(:setup_raw_request)
|
1299
|
-
expect(@request.instance_variable_get(:@raw_request)['authorization']).to eq(@authorization)
|
1300
|
-
end
|
1301
|
-
|
1302
|
-
it "should send Authorization header when redirecting to the same host" do
|
1303
|
-
@redirect['location'] = 'http://api.foo.com/v2'
|
1304
|
-
@request.perform
|
1305
|
-
@request.send(:setup_raw_request)
|
1306
|
-
expect(@request.instance_variable_get(:@raw_request)['authorization']).to eq(@authorization)
|
1307
|
-
end
|
1308
|
-
|
1309
|
-
it "should send Authorization header when redirecting to a different port on the same host" do
|
1310
|
-
@redirect['location'] = 'http://api.foo.com:3000/v3'
|
1311
|
-
@request.perform
|
1312
|
-
@request.send(:setup_raw_request)
|
1313
|
-
expect(@request.instance_variable_get(:@raw_request)['authorization']).to eq(@authorization)
|
1314
|
-
end
|
1315
|
-
end
|
1316
|
-
end
|
1317
|
-
|
1318
|
-
context "with POST http method" do
|
1319
|
-
it "should raise argument error if query is not a hash" do
|
1320
|
-
expect {
|
1321
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', format: :xml, query: 'astring').perform
|
1322
|
-
}.to raise_error(ArgumentError)
|
1323
|
-
end
|
1324
|
-
end
|
1325
|
-
|
1326
|
-
describe "argument validation" do
|
1327
|
-
it "should raise argument error if basic_auth and digest_auth are both present" do
|
1328
|
-
expect {
|
1329
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', basic_auth: {}, digest_auth: {}).perform
|
1330
|
-
}.to raise_error(ArgumentError, "only one authentication method, :basic_auth or :digest_auth may be used at a time")
|
1331
|
-
end
|
1332
|
-
|
1333
|
-
it "should raise argument error if basic_auth is not a hash" do
|
1334
|
-
expect {
|
1335
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', basic_auth: %w(foo bar)).perform
|
1336
|
-
}.to raise_error(ArgumentError, ":basic_auth must be a hash")
|
1337
|
-
end
|
1338
|
-
|
1339
|
-
it "should raise argument error if digest_auth is not a hash" do
|
1340
|
-
expect {
|
1341
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', digest_auth: %w(foo bar)).perform
|
1342
|
-
}.to raise_error(ArgumentError, ":digest_auth must be a hash")
|
1343
|
-
end
|
1344
|
-
|
1345
|
-
it "should raise argument error if headers is not a hash" do
|
1346
|
-
expect {
|
1347
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', headers: %w(foo bar)).perform
|
1348
|
-
}.to raise_error(ArgumentError, ":headers must be a hash")
|
1349
|
-
end
|
1350
|
-
|
1351
|
-
it "should raise argument error if options method is not http accepted method" do
|
1352
|
-
expect {
|
1353
|
-
HTTParty::Request.new('SuperPost', 'http://api.foo.com/v1').perform
|
1354
|
-
}.to raise_error(ArgumentError, "only get, post, patch, put, delete, head, and options methods are supported")
|
1355
|
-
end
|
1356
|
-
|
1357
|
-
it "should raise argument error if http method is post and query is not hash" do
|
1358
|
-
expect {
|
1359
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', query: "message: hello").perform
|
1360
|
-
}.to raise_error(ArgumentError, ":query must be hash if using HTTP Post")
|
1361
|
-
end
|
1362
|
-
|
1363
|
-
it "should raise RedirectionTooDeep error if limit is negative" do
|
1364
|
-
expect {
|
1365
|
-
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', limit: -1).perform
|
1366
|
-
}.to raise_error(HTTParty::RedirectionTooDeep, 'HTTP redirects too deep')
|
1367
|
-
end
|
1368
|
-
end
|
1369
|
-
|
1370
|
-
context 'with Accept-Encoding header' do
|
1371
|
-
it 'should disable content decoding if present' do
|
1372
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', headers:{'Accept-Encoding' => 'custom'})
|
1373
|
-
request.send(:setup_raw_request)
|
1374
|
-
expect(request.instance_variable_get(:@raw_request).decode_content).to eq(false)
|
1375
|
-
end
|
1376
|
-
|
1377
|
-
it 'should disable content decoding if present and lowercase' do
|
1378
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', headers:{'accept-encoding' => 'custom'})
|
1379
|
-
request.send(:setup_raw_request)
|
1380
|
-
expect(request.instance_variable_get(:@raw_request).decode_content).to eq(false)
|
1381
|
-
end
|
1382
|
-
|
1383
|
-
it 'should disable content decoding if present' do
|
1384
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1')
|
1385
|
-
request.send(:setup_raw_request)
|
1386
|
-
expect(request.instance_variable_get(:@raw_request).decode_content).to eq(true)
|
1387
|
-
end
|
1388
|
-
end
|
1389
|
-
end
|