Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

HTTP::Proxy : changing the URI

by insaniac (Friar)
on Dec 15, 2004 at 14:11 UTC ( #415021=perlquestion: print w/replies, xml ) Need Help??

insaniac has asked for the wisdom of the Perl Monks concerning the following question:

hi bwothers and sisters,

I have to write (read: have written) a proxy server which searches for a variable in the request, and based on that variable, add 2 different variable. It's a cheap Single-SignOn solution, which probably stinks security-wise. But at the moment, security is not a requirement (the proxy will be on a separate network blabla).

now, everything works fine when I use it as a proxy (i mean: if I add the proxy IP in firefox, it proxies like it should). the thing we want to achieve is, when a request is made to http://proxy_host/ it should be redirected to another host, something like http://forwarded_host/ (but it should also do the HTTP::Proxy::HeaderFilter i created).
The problem is: when a request is being made to http://proxy_host/, the request is "GET /", and then HTTP::Proxy doesn't use the HTTP::Proxy::HeaderFilter i created. code is the readmore..

here's the code:
#!/usr/bin/perl -w use strict; use HTTP::Proxy qw/:log/; use HTTP::Headers ; use HTTP::Proxy::HeaderFilter; # Variable init my $host = undef; my $port = 80; my $log_file = "/tmp/proxy.log"; my $localhost = "proxy_host"; # the host where proxy is running my $remotehost = "forwarded_host"; my $agent_timeout = 10; sub search_credentials { my($iv_user,$iv_group) = @_; my($ht_user,$ht_passwd); # do some userid mapping funk # test example $ht_user = 'username'; $ht_passwd = 'password'; return ($ht_user,$ht_passwd); } open(LOG,">>", $log_file); my $proxy = HTTP::Proxy->new; $proxy->port($port); $proxy->host($host); $proxy->logfh(*LOG); #$proxy->logmask(STATUS | PROCESS ); # Normal logging $proxy->logmask(STATUS | PROCESS | HEADERS | FILTER); # Debug logging my $filter = HTTP::Proxy::HeaderFilter->new( sub { my ( $self, $headers, $message ) = @_; my $get_uri = $message->$headers->uri(); print "Unaltered URI: $get_uri\n"; my $iv_user = $message->$headers->header('iv-user'); my $iv_group = $message->$headers->header('iv-group'); my($ht_user,$ht_passwd) = search_credentials($iv_user, +$iv_group); $message->$headers->authorization_basic($ht_user,$ht_p +asswd); $get_uri =~ s/$localhost/$remotehost/ if $get_uri =~ m +/$localhost/ ; $get_uri =~ s?^/?http://$remotehost/? if $get_uri =~ m +%^/% ; print "Altered URI: $get_uri\n"; $message->$headers->uri($get_uri); } ); $proxy->push_filter(request => $filter); # this is the mainloop $proxy->start;

UPDATE:
some of the logging... the next part is logged when we use it as a proxy within our webbrowser:

[Wed Dec 15 13:51:39 2004] (10600) Request: GET http://192.168.252.209 +/index.html [Wed Dec 15 13:51:39 2004] (10600) Request: Via: 0.9 amano (HTTP::Prox +y/0.13) [Wed Dec 15 13:51:39 2004] (10600) Request: Authorization: Basic YWRta +W46bmFsaWIxNTk=
The Authorization was added by the filter.

the following logging was when we disabled the proxy setting in firefox, and went directly to http://proxy_host/ (this is what we want to achieve):

[Wed Dec 15 15:39:56 2004] (11209) Request: GET / [Wed Dec 15 15:39:57 2004] (11209) Response: 501 Not Implemented
TIA a lot ;-)
--
to ask a question is a moment of shame
to remain ignorant is a lifelong shame

Replies are listed 'Best First'.
Re: HTTP::Proxy : changing the URI
by !1 (Hermit) on Dec 15, 2004 at 19:28 UTC

    Ah, where to begin?

    1. $headers are the headers that are going to be sent back to the connection that made the request to the proxy. $message is either going to be an HTTP::Request or an HTTP::Response object. You specifically want to filter HTTP::Requests.
    2. What is $message->$headers->header supposed to do?
    3. You should be using HTTP::Proxy::HeaderFilter::simple. You may have been getting a message along the lines of "HTTP::Proxy::HeaderFilter cannot be used as a filter".
    4. You're going to need to patch HTTP::Proxy to rewrite the requested uri for you somewhere in HTTP::Proxy::serve_connections. Right now it's getting undef when it checks $req->uri->scheme. To change this up, you can have something along the lines of:
      $req->uri( $self->url . substr($req->uri,1) ) if $req->uri =~ m!^/!;
      Please note that if you do not filter this request, your proxy will redirect to itself time and time again. Also, set your host to something.

    Hopefully something in here will help you.

      dude, you're patch tip works like a charm!!!! thanx a whole heap :-D
      pretty cool how it works now... pretty cool.. (i'm just a perl beginner, i'm constantly amazed about the power of perl :) )
      --
      to ask a question is a moment of shame
      to remain ignorant is a lifelong shame
      sorry i reply just now... i was pretty tired yesterday evening, so i didn't touch a pc after work ;-)

      i showed you a bad example of my code, the working code does use the HTTP::Proxy::HeaderFilter::simple. (otherwise the filter doesn't work; like you also mentioned). i've added the working code to end of this reply.
      the $message->$headers->header should have been $message->header (when using HTTP::Proxy::HeaderFilter::simple), and that methods sets or gets a header variable. about the patch: yeah, I thought it was something like that, but is the error really coming from HTTP::Proxy?

      anyhow, thanx a bunch for the tips, the patch-tip is probably going to be the most successful one... but i'll keep you posted (btw: we already arranged that the product that's supposed to use this proxy, will use it as a proxy (so it will make "correct" requests). so actually my problem is solved, but I still want to see if this idea would work.. it would be cool, no?)

      #!/usr/local/bin/perl -w use strict; use HTTP::Proxy qw/:log/; use HTTP::Headers ; use HTTP::Proxy::HeaderFilter::simple; # Variable init my $host = undef; my $port = 80; my $log_file = "/tmp/proxy.log"; my $localhost = "proxy_host"; my $remotehost = "forwarded_host"; my $agent_timeout = 10; sub search_credentials { my($iv_user,$iv_group) = @_; my($ht_user,$ht_passwd); # test example $ht_user = 'some_web_user'; $ht_passwd = 'passwd'; return ($ht_user,$ht_passwd); } open(LOG,">>", $log_file); my $proxy = HTTP::Proxy->new; $proxy->port($port); $proxy->host($host); $proxy->logfh(*LOG); $proxy->logmask(STATUS | PROCESS | HEADERS | FILTER); # Debug logging my $filter = HTTP::Proxy::HeaderFilter::simple->new( sub { my ( $self, $headers, $message ) = @_; my $get_uri = $message->uri() ? $message->uri() : "http://$rem +otehost/"; if( $get_uri =~ m%^/%) { print "Unaltered URI: $get_uri\n"; $get_uri =~ s?^/?http://$remotehost/? ; print "Altered URI: $get_uri\n"; } my $iv_user = $message->header('iv-user'); my $iv_group = $message->header('iv-group'); my($ht_user,$ht_passwd) = search_credentials($iv_user,$iv_grou +p); $message->authorization_basic($ht_user,$ht_passwd); } ); $proxy->push_filter(request => $filter ); # this is the mainloop $proxy->start;
      --
      to ask a question is a moment of shame
      to remain ignorant is a lifelong shame

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://415021]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (3)
As of 2021-09-25 05:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?