-
Notifications
You must be signed in to change notification settings - Fork 555
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Follow redirects returned from stubbed responses #237
Comments
Is this fixed ? |
ahh sorry, closed this one by mistake :) |
Same with 301 and Typhoeus (302 not tested) #!/usr/bin/env ruby
require 'rubygems'
require 'typhoeus'
require 'webmock'
include WebMock::API
url = 'https://updown.io:443/'
redirection = 'https://beta.updown.io:443/'
def call_url(url)
response = Typhoeus.get(url, :followlocation => true)
puts "#{url} : #{response.code}"
puts "headers_hash : #{response.headers_hash}"
end
puts "Typhoues #{Typhoeus::VERSION}"
puts "webmock #{WebMock::VERSION}"
puts
puts "Real:"
WebMock.allow_net_connect!
call_url(url)
puts "Webmock stub:"
WebMock.disable_net_connect!
stub_request(:get, url).to_return(:status => 301, :headers => { 'Location' => redirection })
stub_request(:get, redirection)
call_url(url) |
I was able to follow the redirection with the following hack/override: module WebMock
class StubRegistry
def evaluate_response_for_request(response, request_signature)
if [301, 302].include?(response.status[0])
request_signature.uri = response.headers['Location']
request_signature.method = :get
::WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
response_for_request(request_signature)
else
response.dup.evaluate(request_signature)
end
end
end
end However, it raises an error about the request being unregistered even if it appears in the registered request stubs:
Full test file is there: https://gist.github.com/erwanlr/9892510 |
@erwanlr WebMock internally stores uri's as Addressable::URI. |
Humm, I thought I had tested this xD, it's working now. However, Typhoeus (and maybe other Adapters) must have a specific response headers for the Typhoeus::Response#redirections to work properly e.g, with Typhoeus, all redirected response headers must be in the final headers:
But I have no idea how to do this in WebMock :/ |
Tried to implement this for Typhoeus but it wasn't successful as the WebMock::Response#headers are a hash and therefore we can't add the headers from the redirect's responses (as duplicate keys will be merged) Could @i0rek or one of the Typhoeus' dev have a look at this please ? |
I played around with it. I found a hacky solution to sneak in the diff --git a/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb b/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb
index bc36271..f4712c6 100644
--- a/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb
+++ b/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb
@@ -79,7 +79,11 @@ if defined?(Typhoeus)
webmock_response = WebMock::Response.new
webmock_response.status = [typhoeus_response.code, typhoeus_response.status_message]
webmock_response.body = typhoeus_response.body
- webmock_response.headers = typhoeus_response.headers
+ if typhoeus_response.response_headers && @disabled == true
+ webmock_response.headers = {"Raw-Headers-X-Typhoeus-012834701893274023" => typhoeus_response.response_headers.dup}
+ else
+ webmock_response.headers = typhoeus_response.headers
+ end
webmock_response
end
@@ -96,9 +100,14 @@ if defined?(Typhoeus)
::Typhoeus::Response.new(
:code => webmock_response.status[0],
:status_message => webmock_response.status[1],
- :body => webmock_response.body,
- :headers => webmock_response.headers
- )
+ :body => webmock_response.body
+ ).tap do |response|
+ if webmock_response.headers && response_headers = webmock_response.headers.delete("Raw-Headers-X-Typhoeus-012834701893274023")
+ response.instance_variable_set(:response_headers=, response_headers)
+ else
+ response.options[:headers] = webmock_response.headers
+ end
+ end
end
response.mock = :webmock
response I don't think I understand the problem yet. |
The problem is that I am unable to find a clean solution for the implementation of the typhoeus' redirects in WebMock :/ |
In your example you have stub_request(:get, "https://beta.updown.io/")
stub_request(:get, "https://updown.io/") But Typhoeus only does one request; libcurl takes care of the redirection. |
Not sure what you meant there :p This is the spec file I currently use: require 'typhoeus'
require 'webmock'
require 'webmock/rspec'
describe 'Typhoeus WebMock Redirects' do
let(:url) { 'http://gogle.com' }
let(:redirection) { 'http://www.malicious.net' }
# Typhoeus request params
let(:params) { {} }
before do
stub_request(:get, url).to_return(status: 301, headers: { location: redirection })
stub_request(:get, redirection).to_return(body: 'Owned')
@response = Typhoeus.get(url, params)
end
context 'when no --followlocation' do
it 'does not process the redirection' do
expect(@response.redirections).to be_empty
expect(@response.code).to eq 301
end
end
context 'when --followlocation' do
let(:params) { { followlocation: true } }
it 'follows the redirection' do
expect(@response.redirections).to_not be_empty
expect(@response.code).to eq 200
expect(@response.body).to rq 'Owned'
end
end
end |
@i0rek I see. If the redirects are handled internally by libcurl then there is now way for WebMock to intercept them. |
I don't think it is that hard @bblimke. require 'typhoeus'
require 'webmock'
require 'webmock/rspec'
describe 'Typhoeus WebMock Redirects' do
let(:url) { 'http://gogle.com' }
let(:redirection) { 'http://www.malicious.net' }
# Typhoeus request params
let(:params) { {} }
context 'when no --followlocation' do
before do
stub_request(:get, url).to_return(status: 301, headers: { location: redirection })
@response = Typhoeus.get(url, params)
end
it 'does not process the redirection' do
expect(@response.redirections).to be_empty
expect(@response.code).to eq 301
end
end
context 'when --followlocation' do before do
stub_request(:get, url).to_return(body: 'Owned')
@response = Typhoeus.get(url, params)
end
let(:params) { { followlocation: true } }
it 'follows the redirection' do
# expect(@response.redirections).to_not be_empty
expect(@response.code).to eq 200
expect(@response.body).to rq 'Owned'
end
end
end Expect for |
A request stubbed as 302 by webmock doesn't get followed using the
em-http-request
client despite the :redirect parameter.My test works fine with real HTTP connection,
But if I try to stub the two requests, after the first is done (the 302) em-http-request calls the headers AND callback callbacks in a row with the same headers (the first response) and without doing the second request.
Here is a demonstrating example: https://gist.github.com/4294952
I'm using webmock 1.9.0 and em-http-request 1.0.3.
The text was updated successfully, but these errors were encountered: