Hi Gisle,

On 10/04/11 00:06, Gisle Aas wrote:
I'm thinking that we should instead document the {proxy} attribute.  It can be 
useful to have it available in $response->request to be able to tell where the 
request was sent.

The reason why _need_proxy() does not override {proxy} if set is that it allows 
other handlers to set it up.  You might for instance want to set up a handler 
that proxies everything not going to your intranett, or just set it explicitly 
for some requests.

I agree that documenting the {proxy} attribute is a good idea.

If the behaviour of _need_proxy() is going to stay the same perhaps the documentation for LWP::UserAgent::proxy() could be updated to include a warning, something like:

Note that if a HTTP::Request object already has a proxy attribute set, the LWP::UserAgent proxy setting will not be used.

If the proxy attribute is going to be documented in HTTP::Request it would be nice if there was an accessor method added so that the proxy could be set on a request in the same way that is it added to a user agent.

One more thought - though I think this might complicate the LWP::UserAgent interface in a non-userfriendly way - what do you think of adding a switch to LWP::UserAgent so that the proxy setting could be set to override the request proxy setting (but not by default)?

I'm happy to write the patches for these changes (once we've established what they should be).

Cheerio,

 Brad



--Gisle


On Apr 9, 2011, at 0:44 , Bradley Dean wrote:

Greetings,

I've been looking at what feels to me like a bug with the handling of proxy 
configuration. 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 a few possible patches:

PATCH 1:

Remove the "return if exists $req->{proxy};" line from _need_proxy. I think 
this is the cleanest approach.

Thinking of reasons not to do this: 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: bjd...@bjdean.id.au Skype: sk...@bjdean.id.au
Mobile(Aus): +61-413014395 WWW: http://bjdean.id.au/
S/MIME: http://bjdean.id.au/certs/email-public-rsa.txt

Reply via email to