Apache2-CondProxy
view release on metacpan or search on metacpan
lib/Apache2/CondProxy.pm view on Meta::CPAN
}
else {
my $uri = $r->unparsed_uri;
$r->log->debug("Attempting lookup on $uri");
my $subr = _make_subreq($r, $uri);
# set the content-type and content-length in the subrequest
my $ct = $r->headers_in->get('Content-Type');
$subr->headers_in->set('Content-Type', $ct) if $ct;
my $cl = $r->headers_in->get('Content-Length');
$subr->headers_in->set('Content-Length', $cl) if $cl;
# remove Accept-Encoding headers for proxy
my $ae = $r->headers_in->get('Accept-Encoding');
$r->headers_in->unset('Accept-Encoding');
if ($subr->status == 404) {
$r->log->debug('Proxying before subrequest is run');
return _do_proxy($r);
}
$r->log->debug(
sprintf 'Results inconclusive: %d; running subrequest',
$subr->status);
$subr->add_input_filter(\&_input_filter_tee);
$subr->add_output_filter(\&_output_filter_hold);
my $rv = $subr->run;
# we only care about 404
my $st = $subr->status;
if (grep { $rv == $_ || $st == $_ } (403, 404)) {
$r->log->debug("Proxying $uri after subrequest is run");
return _do_proxy($r);
}
else {
# override the subrequest status
$subr->status($rv) if $subr->status != $rv && $rv != 0;
$r->status($subr->status);
# replace Accept-Encoding header
$r->headers_in->set('Accept-Encoding', $ae) if $ae;
$r->log->debug(
sprintf 'Subrequest returned %d; serving content for %s',
$subr->status, $uri);
# copy headers from subreq
$r->headers_out->overlap
($subr->headers_out, APR::Const::OVERLAP_TABLES_SET);
$r->err_headers_out->overlap
($subr->err_headers_out, APR::Const::OVERLAP_TABLES_SET);
# apparently content_type has to be done separately
#$r->log->debug($subr->content_type);
$r->content_type($subr->content_type) if $subr->content_type;
$r->content_encoding($subr->content_encoding)
if $subr->content_encoding;
$r->set_last_modified($subr->mtime) if $subr->mtime;
$r->SUPER::handler('modperl');
$r->set_handlers(PerlResponseHandler => \&_response_handler);
$r->push_handlers(PerlCleanupHandler => \&_cleanup_handler);
$r->add_output_filter(\&_output_filter_release);
return Apache2::Const::OK;
}
}
}
Apache2::Const::OK;
}
sub _make_subreq {
my ($r, $uri) = @_;
$uri = $r->unparsed_uri unless defined $uri;
my $subr = $r->lookup_method_uri($r->method, $uri);
# set the content-type and content-length in the subrequest
my $ct = $r->headers_in->get('Content-Type');
$subr->headers_in->set('Content-Type', $ct) if $ct;
my $cl = $r->headers_in->get('Content-Length');
$subr->headers_in->set('Content-Length', $cl) if $cl;
# remove this so no gzip filter etc happens
$subr->headers_in->unset('Accept-Encoding');
$subr;
}
sub _do_proxy {
my ($r, $first) = @_;
my $c = $r->connection;
my $base = URI->new($r->dir_config('ProxyTarget'))->canonical;
my $match = $r->dir_config('MatchScheme') || '';
$match = scalar($match =~ $TRUE);
if ($match) {
$c->is_https ? $base->scheme('https') : $base->scheme('http');
}
# just do this.
$base = URI->new_abs(substr($r->unparsed_uri, 1), $base);
# for some reason mod_proxy mysteriously started double-escaping
# URIs. AHA: MAGIC.
$r->notes->set('proxy-nocanon', 1);
$r->filename(sprintf 'proxy:%s', $base);
$r->proxyreq(Apache2::Const::PROXYREQ_REVERSE);
$r->SUPER::handler('proxy-server');
$r->add_output_filter(\&_output_filter_fix_location);
if ($first) {
$r->push_handlers(PerlCleanupHandler => \&_cleanup_handler);
$r->add_input_filter(\&_input_filter_tee);
$r->add_output_filter(\&_output_filter_local);
}
else {
$r->add_input_filter(\&_input_filter_replay);
}
return Apache2::Const::OK;
}
sub _do_local {
my ($r, $subr) = @_;
}
# XXX this is the only way I could think of to get at the Location
# header after mod_proxy took over. Could be problematic if another
# filter in the stack flushes output before this one gets run.
sub _output_filter_fix_location {
my ($f, $bb) = @_;
my $c = $f->c;
my $r = $f->r;
#my $mainr = $r->main || $r;
unless ($f->ctx) {
_fix_location($r, $c);
$f->ctx(1);
}
Apache2::Const::DECLINED;
}
sub _fix_location {
my $r = shift;
my $c = shift || $r->connection;
my $loc = $r->headers_out->get('Location');
if ($loc) {
my $match = $r->dir_config('MatchScheme') || '';
$match = scalar($match =~ $TRUE);
# get the hostname of the request, failing that, the server name
my $host = $r->headers_in->get('Host')
|| $r->server->server_hostname;
$host = ($c->is_https ? 'https://' : 'http://') . $host;
$host = URI->new($host)->canonical;
# get the proxy base
my $base = URI->new($r->dir_config('ProxyTarget'))->canonical;
if ($match) {
$c->is_https ? $base->scheme('https') : $base->scheme('http');
}
# fix for malformed (i.e. relative) Location header
$loc = URI->new_abs($loc, $base);
$loc = $loc->canonical;
( run in 0.390 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )