Apache-ReverseProxy
view release on metacpan or search on metacpan
lib/Apache/ReverseProxy.pm view on Meta::CPAN
}
elsif ( defined $exact{$uri_with_qs} ) { # try exact uri with qs
$uri = $exact{$uri_with_qs};
$changed=1;
}
else {
# otherwise, try regular expression matching
foreach my $key (keys(%regex)) {
if ($uri =~ /^$key/) {
$changed=1;
# replace URI's first, then append query string
my $replace_uri = $regex{$key};
my $replace_query='';
if ($replace_uri =~ s/\?(.*)$//) { $replace_query = $1 }
$uri =~ s/$key/${replace_uri}/;
if (length $replace_query) { $uri .= '?' . $replace_query }
last;
}
} # for each regex match...
} # regex matching
if ($changed) {
# strip out possible query string from re-written uri, store it
my $munged_uri = $uri;
my $munged_uri_query = '';
if ($munged_uri =~ s/\?(.*)$//) { $munged_uri_query = $1 }
# query string processing
my $query = $r->args() || ''; # from the user's request
# user has query, but munged url doesn't
if ( defined $query && length($query) && length($munged_uri_query)==0) {
$munged_uri_query = $query;
}
elsif (defined $query && length($query)) {
# if the user had a query string, add it in to the munged uri's qs
my $internal = new CGI($munged_uri_query);
my $user_query = new CGI($query);
foreach my $user_key ( $user_query->param() ) {
# if we can't replace and the variable exists in both places, skip it
# unless ($internal->param($user_key) && $user_query->param($user_key)
# && defined $no_query_replace{$orig_uri} ) {
$internal->param($user_key, $user_query->param($user_key) );
# }
} # for each variable in the user's query string
$munged_uri_query = $internal->query_string(); # stringify
}
if (length $munged_uri_query) { $uri = $munged_uri .'?'. $munged_uri_query }
my $request = new HTTP::Request($r->method, $uri);
# copy in client headers
my(%headers) = $r->headers_in();
for (keys(%headers)) {
$request->header($_, $headers{$_});
}
my $host = $uri;
$host =~ s/([a-zA-z]*:\/\/)([a-zA-Z0-9.-]*)([:0-9]*)\/.*/$2/;
$request->header('Host', $host);
my $ua = new LWP::UserAgent('max_redirect' => 0);
if (defined $chain) {
$ua->proxy(['http', 'https', 'ftp', 'gopher'], $chain);
if (defined $noproxy) { $ua->noproxy($noproxy) }
}
# copy over the client's user-agent, since some servers look at
# this and customize their response based on it.
my $origin_ua = $r->header_in('user-agent');
if (defined $origin_ua && length $origin_ua) {
$ua->agent($origin_ua)
}
# copy over the content type
my $content_type = $r->header_in('content-type');
if (defined $content_type && length $content_type) {
$request->header('content-type', $content_type);
}
# copy over the entity body as well
my $entity_body = $r->content();
if (defined $entity_body && length $entity_body) {
$request->content($entity_body);
} else {
my $buff = '';
$r->read($buff, $r->header_in('Content-length'));
if ($buff ne '') {
$request->content($buff);
}
}
# Okay now for the fireworks. We use a custom subroutine to send an
# http header and then display the content in chunks of 4096 bytes.
# In this way we avoid reading the entire request into core and forcing
# the web browser to wait for the entire file to be downloaded before
# receiving any data.
my $first_time=1;
my $response = $ua->request($request, sub {
my($data, $response, $protocol) = @_;
if ($first_time == 1) {
$r->content_type($response->header('Content-type'));
$r->status($response->code());
$r->status_line($response->code() . ' ' . $response->message());
$response->scan(sub { $r->headers_out->add(@_); });
$r->send_http_header();
$first_time=0;
( run in 0.548 second using v1.01-cache-2.11-cpan-2398b32b56e )