From 6b1b51b8c3a73478998d3f4ea7332718d4e343d6 Mon Sep 17 00:00:00 2001
From: Gianni Ceccarelli <gianni.ceccarelli@net-a-porter.com>
Date: Tue, 24 Jun 2014 10:35:09 +0100
Subject: [PATCH] RT-96501 simple HTTP-via-proxy support
---
lib/Net/Async/HTTP.pm | 2 ++
lib/Net/Async/HTTP/Connection.pm | 14 ++++++++++----
t/01request.t | 34 +++++++++++++++++++++++++++++++---
3 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/lib/Net/Async/HTTP.pm b/lib/Net/Async/HTTP.pm
index 21e299e..f118d35 100644
--- a/lib/Net/Async/HTTP.pm
+++ b/lib/Net/Async/HTTP.pm
@@ -384,6 +384,7 @@ sub get_connection
ready_queue => $ready_queue,
( map { $_ => $self->{$_} }
qw( max_in_flight pipeline read_len write_len decode_content ) ),
+ is_proxy => $args{is_proxy},
on_closed => sub {
my $conn = shift;
@@ -614,6 +615,7 @@ sub _do_one_request
return $self->get_connection(
host => $args{proxy_host} || $self->{proxy_host} || $host,
port => $args{proxy_port} || $self->{proxy_port} || $port,
+ is_proxy => !!($args{proxy_host} || $self->{proxy_host}),
SSL => $args{SSL},
( map { m/^SSL_/ ? ( $_ => $args{$_} ) : () } keys %args ),
)->then( sub {
diff --git a/lib/Net/Async/HTTP/Connection.pm b/lib/Net/Async/HTTP/Connection.pm
index 174593f..f993a39 100644
--- a/lib/Net/Async/HTTP/Connection.pm
+++ b/lib/Net/Async/HTTP/Connection.pm
@@ -52,7 +52,7 @@ sub configure
my $self = shift;
my %params = @_;
- foreach (qw( pipeline max_in_flight ready_queue decode_content )) {
+ foreach (qw( pipeline max_in_flight ready_queue decode_content is_proxy )) {
$self->{$_} = delete $params{$_} if exists $params{$_};
}
@@ -540,7 +540,8 @@ sub request
}
};
- # Unless the request method is CONNECT, the URL is not allowed to contain
+ # Unless the request method is CONNECT, or we are connecting to a
+ # non-transparent proxy, the URL is not allowed to contain
# an authority; only path
# Take a copy of the headers since we'll be hacking them up
my $headers = $req->headers->clone;
@@ -550,8 +551,13 @@ sub request
}
else {
my $uri = $req->uri;
- $path = $uri->path_query;
- $path = "/$path" unless $path =~ m{^/};
+ if ( $self->{is_proxy} ) {
+ $path = $uri->as_string;
+ }
+ else {
+ $path = $uri->path_query;
+ $path = "/$path" unless $path =~ m{^/};
+ }
my $authority = $uri->authority;
if( defined $authority and
my ( $user, $pass, $host ) = $authority =~ m/^(.*?):(.*)@(.*)$/ ) {
diff --git a/t/01request.t b/t/01request.t
index 0181298..f4dd0b4 100644
--- a/t/01request.t
+++ b/t/01request.t
@@ -35,7 +35,8 @@ sub do_test_req
my $error;
my $request = $args{req};
- my $host = $args{no_host} ? $request->uri->host : "host$hostnum"; $hostnum++;
+ my $host = $args{no_host} ? $request->uri->host : $http->{proxy_host} || "host$hostnum"; $hostnum++;
+ my $service = $http->{proxy_port} || 80;
my $peersock;
no warnings 'redefine';
@@ -43,8 +44,8 @@ sub do_test_req
my $self = shift;
my %args = @_;
- $args{host} eq $host or die "Expected $args{host} eq $host";
- $args{service} eq "80" or die "Expected $args{service} eq 80";
+ $args{host} eq $host or die "Expected $args{host} eq $host";
+ $args{service} eq $service or die "Expected $args{service} eq $service";
( my $selfsock, $peersock ) = IO::Async::OS->socketpair() or die "Cannot create socket pair - $!";
$self->set_handle( $selfsock );
@@ -218,6 +219,33 @@ do_test_req( "GET to full URL",
expect_res_content => "Hello, world!",
);
+$http->configure(proxy_host => 'proxyhost',proxy_port=>3128);
+do_test_req( "GET over proxy",
+ req => $req,
+ host => "myhost",
+
+ expect_req_firstline => "GET
http://myhost/some/path HTTP/1.1",
+ expect_req_headers => {
+ Host => "myhost",
+ },
+
+ response => "HTTP/1.1 200 OK$CRLF" .
+ "Content-Length: 13$CRLF" .
+ "Content-Type: text/plain$CRLF" .
+ "Connection: Keep-Alive$CRLF" .
+ $CRLF .
+ "Hello, world!",
+
+ expect_res_code => 200,
+ expect_res_headers => {
+ 'Content-Length' => 13,
+ 'Content-Type' => "text/plain",
+ 'Connection' => "Keep-Alive",
+ },
+ expect_res_content => "Hello, world!",
+);
+$http->configure(proxy_host => undef,proxy_port=>undef);
+
$req = HTTP::Request->new( GET => "/empty", [ Host => "myhost" ] );
do_test_req( "GET with empty body",
--
1.8.5.5