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

Fix up cookie redirect functionality and tests.

- Store the request object on responses. We need this in order to be
  able to correctly process the cookie jar with the right request URI.
- Fix tests that rely on the old broken Set-Cookie processing code.
- Add test that cookies are not passed across domains on redirect.
This commit is contained in:
Andy Brody 2015-03-21 19:08:21 -07:00
parent 12e92312b9
commit c215b22bdb
7 changed files with 52 additions and 35 deletions

View file

@ -5,7 +5,7 @@ module RestClient
module AbstractResponse
attr_reader :net_http_res, :args
attr_reader :net_http_res, :args, :request
# HTTP status code
def code
@ -23,11 +23,17 @@ module RestClient
@raw_headers ||= @net_http_res.to_hash
end
def response_set_vars(net_http_res, args, request)
@net_http_res = net_http_res
@args = args
@request = request
end
# Hash of cookies extracted from response headers
def cookies
hash = {}
cookie_jar.cookies.each do |out, cookie|
cookie_jar.cookies.each do |cookie|
hash[cookie.name] = cookie.value
end
@ -43,7 +49,7 @@ module RestClient
jar = HTTP::CookieJar.new
headers.fetch(:set_cookie, []).each do |cookie|
jar.parse(cookie, @args.fetch(:url))
jar.parse(cookie, @request.url)
end
@cookie_jar = jar
@ -85,7 +91,7 @@ module RestClient
url = headers[:location]
if url !~ /^http/
url = URI.parse(args[:url]).merge(url).to_s
url = URI.parse(request.url).merge(url).to_s
end
new_args[:url] = url
if request

View file

@ -13,12 +13,13 @@ module RestClient
include AbstractResponse
attr_reader :file
attr_reader :file, :request
def initialize tempfile, net_http_res, args
def initialize(tempfile, net_http_res, args, request)
@net_http_res = net_http_res
@args = args
@file = tempfile
@request = request
end
def to_s

View file

@ -484,9 +484,9 @@ module RestClient
def process_result res, & block
if @raw_response
# We don't decode raw requests
response = RawResponse.new(@tf, res, args)
response = RawResponse.new(@tf, res, args, self)
else
response = Response.create(Request.decode(res['content-encoding'], res.body), res, args)
response = Response.create(Request.decode(res['content-encoding'], res.body), res, args, self)
end
if block_given?

View file

@ -6,17 +6,14 @@ module RestClient
include AbstractResponse
attr_accessor :args, :net_http_res
def body
self
end
def self.create body, net_http_res, args
def self.create body, net_http_res, args, request
result = body || ''
result.extend Response
result.net_http_res = net_http_res
result.args = args
result.response_set_vars(net_http_res, args, request)
result
end

View file

@ -8,16 +8,18 @@ describe RestClient::AbstractResponse do
attr_accessor :size
def initialize net_http_res, args
def initialize net_http_res, args, request
@net_http_res = net_http_res
@args = args
@request = request
end
end
before do
@net_http_res = double('net http response')
@response = MyAbstractResponse.new(@net_http_res, {})
@request = double('restclient request', :url => 'http://example.com')
@response = MyAbstractResponse.new(@net_http_res, {}, @request)
end
it "fetches the numeric response code" do
@ -53,7 +55,8 @@ describe RestClient::AbstractResponse do
it "extract strange cookies" do
@net_http_res.should_receive(:to_hash).and_return('set-cookie' => ['session_id=ZJ/HQVH6YE+rVkTpn0zvTQ==; path=/'])
@response.cookies.should eq({ 'session_id' => 'ZJ%2FHQVH6YE+rVkTpn0zvTQ%3D%3D' })
@response.headers.should eq({:set_cookie => ['session_id=ZJ/HQVH6YE+rVkTpn0zvTQ==; path=/']})
@response.cookies.should eq({ 'session_id' => 'ZJ/HQVH6YE+rVkTpn0zvTQ==' })
end
it "doesn't escape cookies" do

View file

@ -4,7 +4,8 @@ describe RestClient::RawResponse do
before do
@tf = double("Tempfile", :read => "the answer is 42", :open => true)
@net_http_res = double('net http response')
@response = RestClient::RawResponse.new(@tf, @net_http_res, {})
@request = double('http request')
@response = RestClient::RawResponse.new(@tf, @net_http_res, {}, @request)
end
it "behaves like string" do

View file

@ -3,8 +3,9 @@ require 'spec_helper'
describe RestClient::Response do
before do
@net_http_res = double('net http response', :to_hash => {"Status" => ["200 OK"]}, :code => 200)
@request = double('http request', :user => nil, :password => nil)
@response = RestClient::Response.create('abc', @net_http_res, {})
@example_url = 'http://example.com'
@request = double('http request', :user => nil, :password => nil, :url => @example_url)
@response = RestClient::Response.create('abc', @net_http_res, {}, @request)
end
it "behaves like string" do
@ -14,7 +15,7 @@ describe RestClient::Response do
end
it "accepts nil strings and sets it to empty for the case of HEAD" do
RestClient::Response.create(nil, @net_http_res, {}).to_s.should eq ""
RestClient::Response.create(nil, @net_http_res, {}, @request).to_s.should eq ""
end
it "test headers and raw headers" do
@ -24,16 +25,18 @@ describe RestClient::Response do
describe "cookie processing" do
it "should correctly deal with one Set-Cookie header with one cookie inside" do
net_http_res = double('net http response', :to_hash => {"etag" => ["\"e1ac1a2df945942ef4cac8116366baad\""], "set-cookie" => ["main_page=main_page_no_rewrite; path=/; expires=Tue, 20-Jan-2015 15:03:14 GMT"]})
response = RestClient::Response.create('abc', net_http_res, {})
response.headers[:set_cookie].should eq ["main_page=main_page_no_rewrite; path=/; expires=Tue, 20-Jan-2015 15:03:14 GMT"]
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=Tue, 20-Jan-2015 15:03:14 GMT", "remember_me=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT", "user=somebody; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"]})
response = RestClient::Response.create('abc', net_http_res, {})
response.headers[:set_cookie].should eq ["main_page=main_page_no_rewrite; path=/; expires=Tue, 20-Jan-2015 15:03:14 GMT", "remember_me=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT", "user=somebody; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"]
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" => "",
@ -42,8 +45,8 @@ describe RestClient::Response do
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=Tue, 20-Jan-2015 15:03:14 GMT, remember_me=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT, user=somebody; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"]})
response = RestClient::Response.create('abc', net_http_res, {})
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" => "",
@ -56,7 +59,7 @@ describe RestClient::Response do
it "should return itself for normal codes" do
(200..206).each do |code|
net_http_res = double('net http response', :code => '200')
response = RestClient::Response.create('abc', net_http_res, {})
response = RestClient::Response.create('abc', net_http_res, {}, @request)
response.return! @request
end
end
@ -65,7 +68,7 @@ describe RestClient::Response do
RestClient::Exceptions::EXCEPTIONS_MAP.each_key do |code|
unless (200..207).include? code
net_http_res = double('net http response', :code => code.to_i)
response = RestClient::Response.create('abc', net_http_res, {})
response = RestClient::Response.create('abc', net_http_res, {}, @request)
lambda { response.return!}.should raise_error
end
end
@ -88,32 +91,38 @@ describe RestClient::Response do
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' => 'Foo=Bar'}).to_return(:body => 'Qux')
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 = double('net http response', :code => 301)
response = RestClient::Response.create('abc', net_http_res, {:method => :post})
response = RestClient::Response.create('abc', net_http_res, {:method => :post}, @request)
lambda { response.return!(@request)}.should raise_error(RestClient::MovedPermanently)
end
it "doesn't follow a 302 when the request is a post" do
net_http_res = double('net http response', :code => 302)
response = RestClient::Response.create('abc', net_http_res, {:method => :post})
response = RestClient::Response.create('abc', net_http_res, {:method => :post}, @request)
lambda { response.return!(@request)}.should raise_error(RestClient::Found)
end
it "doesn't follow a 307 when the request is a post" do
net_http_res = double('net http response', :code => 307)
response = RestClient::Response.create('abc', net_http_res, {:method => :post})
response = RestClient::Response.create('abc', net_http_res, {:method => :post}, @request)
lambda { response.return!(@request)}.should raise_error(RestClient::TemporaryRedirect)
end
it "doesn't follow a redirection when the request is a put" do
net_http_res = double('net http response', :code => 301)
response = RestClient::Response.create('abc', net_http_res, {:method => :put})
response = RestClient::Response.create('abc', net_http_res, {:method => :put}, @request)
lambda { response.return!(@request)}.should raise_error(RestClient::MovedPermanently)
end