mirror of
https://github.com/rest-client/rest-client.git
synced 2022-11-09 13:49:40 -05:00

This allows callers to actually determine whether a given request followed redirection, and if so, what the original responses to each intermediate request were. Due to the way the code is organized, the simplest way to achieve this involves storing the history on request objects as well. This isn't ideal, but will work for now.
219 lines
11 KiB
Ruby
219 lines
11 KiB
Ruby
require_relative '_lib'
|
|
|
|
describe RestClient::Response, :include_helpers do
|
|
before do
|
|
@net_http_res = double('net http response', :to_hash => {"Status" => ["200 OK"]}, :code => 200)
|
|
@example_url = 'http://example.com'
|
|
@request = double('http request', :user => nil, :password => nil, :url => @example_url, :redirection_history => nil)
|
|
@response = RestClient::Response.create('abc', @net_http_res, {}, @request)
|
|
end
|
|
|
|
it "behaves like string" do
|
|
@response.to_s.should eq 'abc'
|
|
@response.to_str.should eq 'abc'
|
|
|
|
@response.should_receive(:warn)
|
|
@response.to_i.should eq 0
|
|
end
|
|
|
|
it "accepts nil strings and sets it to empty for the case of HEAD" do
|
|
RestClient::Response.create(nil, @net_http_res, {}, @request).to_s.should eq ""
|
|
end
|
|
|
|
describe 'header processing' do
|
|
it "test headers and raw headers" do
|
|
@response.raw_headers["Status"][0].should eq "200 OK"
|
|
@response.headers[:status].should eq "200 OK"
|
|
end
|
|
|
|
it 'handles multiple headers by joining with comma' do
|
|
@net_http_res = double('net http response', :to_hash => {'My-Header' => ['foo', 'bar']}, :code => 200)
|
|
@example_url = 'http://example.com'
|
|
@request = double('http request', :user => nil, :password => nil, :url => @example_url, :redirection_history => nil)
|
|
@response = RestClient::Response.create('abc', @net_http_res, {}, @request)
|
|
|
|
@response.raw_headers['My-Header'].should eq ['foo', 'bar']
|
|
@response.headers[:my_header].should eq 'foo, bar'
|
|
end
|
|
end
|
|
|
|
describe "cookie processing" do
|
|
it "should correctly deal with one Set-Cookie header with one cookie inside" do
|
|
header_val = "main_page=main_page_no_rewrite; path=/; expires=Sat, 10-Jan-2037 15:03:14 GMT".freeze
|
|
|
|
net_http_res = double('net http response', :to_hash => {"etag" => ["\"e1ac1a2df945942ef4cac8116366baad\""], "set-cookie" => [header_val]})
|
|
response = RestClient::Response.create('abc', net_http_res, {}, @request)
|
|
response.headers[:set_cookie].should eq [header_val]
|
|
response.cookies.should eq({ "main_page" => "main_page_no_rewrite" })
|
|
end
|
|
|
|
it "should correctly deal with multiple cookies [multiple Set-Cookie headers]" do
|
|
net_http_res = double('net http response', :to_hash => {"etag" => ["\"e1ac1a2df945942ef4cac8116366baad\""], "set-cookie" => ["main_page=main_page_no_rewrite; path=/; expires=Sat, 10-Jan-2037 15:03:14 GMT", "remember_me=; path=/; expires=Sat, 10-Jan-2037 00:00:00 GMT", "user=somebody; path=/; expires=Sat, 10-Jan-2037 00:00:00 GMT"]})
|
|
response = RestClient::Response.create('abc', net_http_res, {}, @request)
|
|
response.headers[:set_cookie].should eq ["main_page=main_page_no_rewrite; path=/; expires=Sat, 10-Jan-2037 15:03:14 GMT", "remember_me=; path=/; expires=Sat, 10-Jan-2037 00:00:00 GMT", "user=somebody; path=/; expires=Sat, 10-Jan-2037 00:00:00 GMT"]
|
|
response.cookies.should eq({
|
|
"main_page" => "main_page_no_rewrite",
|
|
"remember_me" => "",
|
|
"user" => "somebody"
|
|
})
|
|
end
|
|
|
|
it "should correctly deal with multiple cookies [one Set-Cookie header with multiple cookies]" do
|
|
net_http_res = double('net http response', :to_hash => {"etag" => ["\"e1ac1a2df945942ef4cac8116366baad\""], "set-cookie" => ["main_page=main_page_no_rewrite; path=/; expires=Sat, 10-Jan-2037 15:03:14 GMT, remember_me=; path=/; expires=Sat, 10-Jan-2037 00:00:00 GMT, user=somebody; path=/; expires=Sat, 10-Jan-2037 00:00:00 GMT"]})
|
|
response = RestClient::Response.create('abc', net_http_res, {}, @request)
|
|
response.cookies.should eq({
|
|
"main_page" => "main_page_no_rewrite",
|
|
"remember_me" => "",
|
|
"user" => "somebody"
|
|
})
|
|
end
|
|
end
|
|
|
|
describe "exceptions processing" do
|
|
it "should return itself for normal codes" do
|
|
(200..206).each do |code|
|
|
net_http_res = response_double(:code => '200')
|
|
resp = RestClient::Response.create('abc', net_http_res, {}, @request)
|
|
resp.return!
|
|
end
|
|
end
|
|
|
|
it "should throw an exception for other codes" do
|
|
RestClient::Exceptions::EXCEPTIONS_MAP.each_key do |code|
|
|
unless (200..207).include? code
|
|
net_http_res = response_double(:code => code.to_i)
|
|
resp = RestClient::Response.create('abc', net_http_res, {}, @request)
|
|
lambda { resp.return! }.should raise_error
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
describe "redirection" do
|
|
|
|
it "follows a redirection when the request is a get" do
|
|
stub_request(:get, 'http://some/resource').to_return(:body => '', :status => 301, :headers => {'Location' => 'http://new/resource'})
|
|
stub_request(:get, 'http://new/resource').to_return(:body => 'Foo')
|
|
RestClient::Request.execute(:url => 'http://some/resource', :method => :get).body.should eq 'Foo'
|
|
end
|
|
|
|
it "keeps redirection history" do
|
|
stub_request(:get, 'http://some/resource').to_return(:body => '', :status => 301, :headers => {'Location' => 'http://new/resource'})
|
|
stub_request(:get, 'http://new/resource').to_return(:body => 'Foo')
|
|
r = RestClient::Request.execute(url: 'http://some/resource', method: :get)
|
|
r.body.should eq 'Foo'
|
|
r.history.length.should eq 1
|
|
r.history.fetch(0).should be_a(RestClient::Response)
|
|
r.history.fetch(0).code.should be 301
|
|
end
|
|
|
|
it "follows a redirection and keep the parameters" do
|
|
stub_request(:get, 'http://foo:bar@some/resource').with(:headers => {'Accept' => 'application/json'}).to_return(:body => '', :status => 301, :headers => {'Location' => 'http://new/resource'})
|
|
stub_request(:get, 'http://foo:bar@new/resource').with(:headers => {'Accept' => 'application/json'}).to_return(:body => 'Foo')
|
|
RestClient::Request.execute(:url => 'http://some/resource', :method => :get, :user => 'foo', :password => 'bar', :headers => {:accept => :json}).body.should eq 'Foo'
|
|
end
|
|
|
|
it "follows a redirection and keep the cookies" do
|
|
stub_request(:get, 'http://some/resource').to_return(:body => '', :status => 301, :headers => {'Set-Cookie' => 'Foo=Bar', 'Location' => 'http://some/new_resource', })
|
|
stub_request(:get, 'http://some/new_resource').with(:headers => {'Cookie' => 'Foo=Bar'}).to_return(:body => 'Qux')
|
|
RestClient::Request.execute(:url => 'http://some/resource', :method => :get).body.should eq 'Qux'
|
|
end
|
|
|
|
it 'does not keep cookies across domains' do
|
|
stub_request(:get, 'http://some/resource').to_return(:body => '', :status => 301, :headers => {'Set-Cookie' => 'Foo=Bar', 'Location' => 'http://new/resource', })
|
|
stub_request(:get, 'http://new/resource').with(:headers => {'Cookie' => ''}).to_return(:body => 'Qux')
|
|
RestClient::Request.execute(:url => 'http://some/resource', :method => :get).body.should eq 'Qux'
|
|
end
|
|
|
|
it "doesn't follow a 301 when the request is a post" do
|
|
net_http_res = response_double(:code => 301)
|
|
response = RestClient::Response.create('abc', net_http_res,
|
|
{:method => :post}, @request)
|
|
lambda {
|
|
response.return!
|
|
}.should raise_error(RestClient::MovedPermanently)
|
|
end
|
|
|
|
it "doesn't follow a 302 when the request is a post" do
|
|
net_http_res = response_double(:code => 302)
|
|
response = RestClient::Response.create('abc', net_http_res,
|
|
{:method => :post}, @request)
|
|
lambda {
|
|
response.return!
|
|
}.should raise_error(RestClient::Found)
|
|
end
|
|
|
|
it "doesn't follow a 307 when the request is a post" do
|
|
net_http_res = response_double(:code => 307)
|
|
response = RestClient::Response.create('abc', net_http_res,
|
|
{:method => :post}, @request)
|
|
lambda {
|
|
response.return!
|
|
}.should raise_error(RestClient::TemporaryRedirect)
|
|
end
|
|
|
|
it "doesn't follow a redirection when the request is a put" do
|
|
net_http_res = response_double(:code => 301)
|
|
response = RestClient::Response.create('abc', net_http_res,
|
|
{:method => :put}, @request)
|
|
lambda {
|
|
response.return!
|
|
}.should raise_error(RestClient::MovedPermanently)
|
|
end
|
|
|
|
it "follows a redirection when the request is a post and result is a 303" do
|
|
stub_request(:put, 'http://some/resource').to_return(:body => '', :status => 303, :headers => {'Location' => 'http://new/resource'})
|
|
stub_request(:get, 'http://new/resource').to_return(:body => 'Foo')
|
|
RestClient::Request.execute(:url => 'http://some/resource', :method => :put).body.should eq 'Foo'
|
|
end
|
|
|
|
it "follows a redirection when the request is a head" do
|
|
stub_request(:head, 'http://some/resource').to_return(:body => '', :status => 301, :headers => {'Location' => 'http://new/resource'})
|
|
stub_request(:head, 'http://new/resource').to_return(:body => 'Foo')
|
|
RestClient::Request.execute(:url => 'http://some/resource', :method => :head).body.should eq 'Foo'
|
|
end
|
|
|
|
it "handles redirects with relative paths" do
|
|
stub_request(:get, 'http://some/resource').to_return(:body => '', :status => 301, :headers => {'Location' => 'index'})
|
|
stub_request(:get, 'http://some/index').to_return(:body => 'Foo')
|
|
RestClient::Request.execute(:url => 'http://some/resource', :method => :get).body.should eq 'Foo'
|
|
end
|
|
|
|
it "handles redirects with relative path and query string" do
|
|
stub_request(:get, 'http://some/resource').to_return(:body => '', :status => 301, :headers => {'Location' => 'index?q=1'})
|
|
stub_request(:get, 'http://some/index?q=1').to_return(:body => 'Foo')
|
|
RestClient::Request.execute(:url => 'http://some/resource', :method => :get).body.should eq 'Foo'
|
|
end
|
|
|
|
it "follow a redirection when the request is a get and the response is in the 30x range" do
|
|
stub_request(:get, 'http://some/resource').to_return(:body => '', :status => 301, :headers => {'Location' => 'http://new/resource'})
|
|
stub_request(:get, 'http://new/resource').to_return(:body => 'Foo')
|
|
RestClient::Request.execute(:url => 'http://some/resource', :method => :get).body.should eq 'Foo'
|
|
end
|
|
|
|
it "follows no more than 10 redirections before raising error" do
|
|
stub_request(:get, 'http://some/redirect-1').to_return(:body => '', :status => 301, :headers => {'Location' => 'http://some/redirect-2'})
|
|
stub_request(:get, 'http://some/redirect-2').to_return(:body => '', :status => 301, :headers => {'Location' => 'http://some/redirect-2'})
|
|
lambda {
|
|
RestClient::Request.execute(url: 'http://some/redirect-1', method: :get)
|
|
}.should raise_error(RestClient::MovedPermanently) { |ex|
|
|
ex.response.history.each {|r| r.should be_a(RestClient::Response) }
|
|
ex.response.history.length.should eq 10
|
|
}
|
|
WebMock.should have_requested(:get, 'http://some/redirect-2').times(10)
|
|
end
|
|
|
|
it "follows no more than max_redirects redirections, if specified" do
|
|
stub_request(:get, 'http://some/redirect-1').to_return(:body => '', :status => 301, :headers => {'Location' => 'http://some/redirect-2'})
|
|
stub_request(:get, 'http://some/redirect-2').to_return(:body => '', :status => 301, :headers => {'Location' => 'http://some/redirect-2'})
|
|
lambda {
|
|
RestClient::Request.execute(url: 'http://some/redirect-1', method: :get, max_redirects: 5)
|
|
}.should raise_error(RestClient::MovedPermanently) { |ex|
|
|
ex.response.history.length.should eq 5
|
|
}
|
|
WebMock.should have_requested(:get, 'http://some/redirect-2').times(5)
|
|
end
|
|
end
|
|
|
|
end
|