add integration tests for HTTP proxy support

Spins up a proxy server in a separate process, runs a few requests
through it with each adapter to verify that both proxy support and basic
authentication take effect.
This commit is contained in:
Mislav Marohnić 2013-07-25 17:15:30 +02:00
parent eed09439f7
commit 0a1deaf173
7 changed files with 96 additions and 4 deletions

View File

@ -6,6 +6,9 @@ module Faraday
case env[:status]
when 404
raise Faraday::Error::ResourceNotFound, response_values(env)
when 407
# mimic the behavior that we get with proxy requests with HTTPS
raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
when ClientErrorStatuses
raise Faraday::Error::ClientError, response_values(env)
end

41
script/proxy-server Executable file
View File

@ -0,0 +1,41 @@
#!/usr/bin/env ruby
# Usage: script/proxy-server [-p PORT] [-u USER:PASSWORD]
require 'webrick'
require 'webrick/httpproxy'
port = 4001
if found = ARGV.index('-p')
port = ARGV[found + 1].to_i
end
if found = ARGV.index('-u')
username, password = ARGV[found + 1].split(':', 2)
end
match_credentials = lambda { |credentials|
got_username, got_password = credentials.to_s.unpack("m*")[0].split(":", 2)
got_username == username && got_password == password
}
log_io = $stdout
log_io.sync = true
webrick_opts = {
:Port => port, :Logger => WEBrick::Log::new(log_io),
:AccessLog => [[log_io, "[%{X-Faraday-Adapter}i] %m %U -> %s %b"]],
:ProxyAuthProc => lambda { |req, res|
if username
type, credentials = req.header['proxy-authorization'].first.to_s.split(/\s+/, 2)
unless "Basic" == type && match_credentials.call(credentials)
raise WEBrick::HTTPStatus::ProxyAuthenticationRequired
end
end
}
}
proxy = WEBrick::HTTPProxyServer.new(webrick_opts)
trap(:TERM) { proxy.shutdown }
trap(:INT) { proxy.shutdown }
proxy.start

View File

@ -24,6 +24,7 @@ if [[ "$RUBYOPT" != *"bundler/setup"* ]]; then
fi
port=3999
proxy_port=3998
scheme=http
if [ "$SSL" = "yes" ]; then
@ -51,8 +52,14 @@ start_server() {
echo $!
}
start_proxy() {
mkdir -p log
script/proxy-server -p $proxy_port -u "faraday@test.local:there is cake" >log/proxy.log 2>&1 &
echo $!
}
server_started() {
lsof -i :$port >/dev/null
lsof -i :${1?} >/dev/null
}
timestamp() {
@ -62,7 +69,7 @@ timestamp() {
wait_for_server() {
timeout=$(( `timestamp` + $1 ))
while true; do
if server_started; then
if server_started "$2"; then
break
elif [ `timestamp` -gt "$timeout" ]; then
echo "timed out after $1 seconds" >&2
@ -109,23 +116,27 @@ fi
# If there are any adapter tests, spin up the HTTP server
if [ -n "$(filter_matching "adapters" "${test_files[@]}")" ]; then
if server_started; then
if server_started $port; then
echo "aborted: another instance of server running on $port" >&2
exit 1
fi
server_pid=$(start_server)
wait_for_server 15 || {
proxy_pid=$(start_proxy)
wait_for_server 15 $port || {
cat log/test.log
exit 1
}
wait_for_server 5 $proxy_port
cleanup() {
if [ $? -ne 0 ] && [ -n "$TRAVIS" ]; then
cat log/test.log
fi
kill "$server_pid"
kill "$proxy_pid"
}
trap cleanup INT EXIT
export LIVE="${scheme}://localhost:${port}"
export LIVE_PROXY="http://faraday%40test.local:there%20is%20cake@localhost:${proxy_port}"
fi
warnings="${TMPDIR:-/tmp}/faraday-warnings.$$"

View File

@ -8,6 +8,10 @@ module Adapters
Integration.apply(self, :NonParallel) do
# https://github.com/geemus/excon/issues/126 ?
undef :test_timeout if ssl_mode?
# Excon lets OpenSSL::SSL::SSLError be raised without any way to
# distinguish whether it happened because of a 407 proxy response
undef :test_proxy_auth_fail if ssl_mode?
end
end
end

View File

@ -172,6 +172,34 @@ module Adapters
end
end
def test_proxy
proxy_uri = URI(ENV['LIVE_PROXY'])
conn = create_connection(:proxy => proxy_uri)
res = conn.get '/echo'
assert_equal 'get', res.body
unless self.class.ssl_mode?
# proxy can't append "Via" header for HTTPS responses
assert_match(/:#{proxy_uri.port}$/, res['via'])
end
end
def test_proxy_auth_fail
proxy_uri = URI(ENV['LIVE_PROXY'])
proxy_uri.password = 'WRONG'
conn = create_connection(:proxy => proxy_uri)
err = assert_raises Faraday::Error::ConnectionFailed do
conn.get '/echo'
end
unless self.class.ssl_mode? && self.class.jruby?
# JRuby raises "End of file reached" which cannot be distinguished from a 407
assert_equal %{407 "Proxy Authentication Required "}, err.message
end
end
def test_empty_body_response_represented_as_blank_string
response = get('204')
assert_equal '', response.body

View File

@ -25,5 +25,7 @@ module Adapters
# test not applicable
undef test_connection_error
undef test_proxy
undef test_proxy_auth_fail
end
end

View File

@ -13,6 +13,9 @@ module Adapters
# which libcurl seems to generate for this particular request:
undef :test_POST_sends_files
# inconsistent outcomes ranging from successful response to connection error
undef :test_proxy_auth_fail if ssl_mode?
def test_binds_local_socket
host = '1.2.3.4'
conn = create_connection :request => { :bind => { :host => host } }