Greetings,
When a HTTP::Request is made through an LWP::UserAgent with a proxy
configured
the HTTP::Request is changed by LWP::UserAgent::__need_proxy:
sub _need_proxy {
...
$req->{proxy} = $HTTP::URI_CLASS->new($proxy);
}
"proxy" is not a documented attribute of the HTTP::Request class, but
when it
is set _need_proxy ignores the current LWP::UserAgent proxy settings:
sub _need_proxy {
my($req, $ua) = @_;
return if exists $req->{proxy};
...
}
This becomes a problem when trying to use a single HTTP::Request instance
across multiple proxies - for example:
my $request = HTTP::Request->new(GET => 'http://www.example.com/');
my $ua = LWP::UserAgent->new();
$ua->proxy('http', 'http://proxy_one.example.org:12345/');
# This first request goes through proxy_one
$ua->request($request);
# Now change the proxy on the LWP::UserAgent
$ua->proxy('http', 'http://proxy_two.example.org:12345/');
# This second request goes through proxy_one still because
# $request->{proxy} == "http://proxy_one.example.org:12345/"
$ua->request($request);
This can be worked around in the calling software by deleting
$request->{proxy}
between requests but it's a hack (and one which could fail at any time given
that this is a non-documented attribute).
I've thought of three possible patches:
PATCH 1:
Remove the "return if exists $req->{proxy};" line from _need_proxy I
think this
is the cleanest approach.
I think the only reason not to do this is that it incurs some extra
processing
cost per request (but only in the case that a single request is used
over and
over again). It might break existing code that relies on the undocumented
"proxy" attribute (where people are building requests with proxies
rather than
configuring via LWP::UserAgent). If this is a concern see 2.
PATCH 1 GIT:
diff --git a/lib/LWP/UserAgent.pm b/lib/LWP/UserAgent.pm
index 1ee9ffb..945cd8a 100644
--- a/lib/LWP/UserAgent.pm
+++ b/lib/LWP/UserAgent.pm
@@ -934,7 +934,6 @@ sub mirror
sub _need_proxy {
my($req, $ua) = @_;
- return if exists $req->{proxy};
my $proxy = $ua->{proxy}{$req->uri->scheme} || return;
if ($ua->{no_proxy}) {
if (my $host = eval { $req->uri->host }) {
PATCH 2:
A more expensive option would be to check if the LWP::UserAgent has a proxy
configured and if it is different from the proxy attribute on the
HTTP::Request.
If it is different I would argue that LWP::UserAgent value should
override the
requestm, so if the values were different the LWP::UserAgent could
change the
value of the proxy atttribute.
I've not included a git patch for this option but could supply one if it
was of
interest.
PATCH 3:
At the moment $request->{proxy} has to be set because the request is
passed out
of the LWP::UserAgent to a protocol handler. As I recall at this stage the
LWP::UserAgent is not visible to the protocol handler, so $request is
used to
pass on the proxy configuration.
A much bigger change to the code would have the protocol handler given
access
to the LWP::UserAgent so that the proxy did not have to be attached to the
HTTP::Request. The same decision still needs to be made as in PATCH 2
(ie what
happens if someone has set the proxy attribute).
As with patch 2, I've not included a git patch for this option but could
supply
one if it was of interest.
Cheerio,
Brad
--
Bradley Dean
Email: [email protected] Skype: [email protected]
Mobile(Aus): +61-413014395 WWW: http://bjdean.id.au/
S/MIME: http://bjdean.id.au/certs/email-public-rsa.txt