Better way to proxy an HTTP request using Perl HTTP::Response and LWP? -
i need perl cgi script fetches url , returns result of fetch - status, headers , content - unaltered cgi environment "proxied" url returned web server user's browser if they'd accessed url directly.
i'm running script cgi-bin in apache web server on ubuntu 14.04 host, question should independent of server platform - can run perl cgi scripts should able it.
i've tried using lwp::useragent::request() , i've got close. returns http::response object contains status code, headers , content, , has "as_string" method turns human-readable form. problem cgi perspective "as string" converts status code "http/1.1 200 ok" rather "status: 200 ok", apache server doesn't recognise output valid cgi response.
i can fix using other methods in http::response split out various parts, there seems no public way of getting @ encapsulated http::headers object in order call as_string method; instead have hack perl blessed object hash , yank out private "_headers" member directly. me seems evil, there better way?
here's code illustrate above. if put in cgi-bin directory can call as
http://localhost/cgi-bin/lwp-test?url=http://localhost/&http-response=1&show=1
you can use different url testing if want. if set http-response=0
(or drop param altogether) working piece-by-piece solution. if set show=0
(or drop it) proxied request returned script. apache return proxied page if have http-response=0 , choke 500 internal server error if it's 1.
#!/usr/bin/perl use strict; use warnings; use cgi::simple; use http::request; use http::response; use lwp::useragent; $q = cgi::simple->new(); $ua = lwp::useragent->new(); $req = http::request->new(get => $q->param('url')); $res = $ua->request($req); # print text/plain header if called "show=1" in query string # proxied url response shown in browser, otherwise output # proxied response if ours. if ($q->param('show')) { print $q->header("text/plain"); print "\n"; } if ($q->param('http-response')) { # prints status "http/1.1 200 ok", not "status: 200 ok". print $res->as_string; } else { # works correctly proxy, using {_headers} @ # private encapsulated http:response object seems bit evil. # there must better way! print "status: ", $res->status_line, "\n"; print $res->{_headers}->as_string; print "\n"; print $res->content; }
please bear in mind script written purely demonstrate how forward http::response
object cgi environment , bears no resemblance actual application.
you can go around internals of response object @ $res->{_headers}
using $res->headers
method, returns actual http::headers instance used. http::response inherits http::message.
it this:
print "status: ", $res->status_line, "\n"; print $res->headers->as_string;
that looks less evil, though it's still not pretty.
Comments
Post a Comment