Apache2-Proxy
view release on metacpan or search on metacpan
lib/Apache2/Proxy.pm view on Meta::CPAN
# some headers have an unecessary newline appended so chomp the value
chomp( $headers->{$key} );
if ( $headers->{$key} =~ m/\n/ ) {
$headers->{$key} =~ s/\n/ /g;
}
$r->log->debug(
"$$ Setting header key $key, value " . $headers->{$key} )
if VERBOSE_DEBUG;
$r->headers_out->set( $key => $headers->{$key} );
}
return 1;
}
sub translate_cookie_and_auth_headers {
my ( $class, $r, $res ) = @_;
################################################
# process the www-auth and set-cookie headers
no strict 'refs';
foreach my $header_type qw( set-cookie www-authenticate ) {
next unless defined $res->header($header_type);
my @headers = $res->header($header_type);
foreach my $header (@headers) {
$r->log->debug("$$ setting header $header_type value $header")
if VERBOSE_DEBUG;
$r->err_headers_out->add( $header_type => $header );
}
# and remove it from the response headers
my $removed = $res->headers->remove_header($header_type);
$r->log->debug("$$ translated $removed $header_type headers")
if VERBOSE_DEBUG;
}
return 1;
}
sub set_twohundred_response_headers {
my ( $class, $r, $res, $response_content_ref ) = @_;
$r->log->debug("setting response headers " . Dumper($res->headers)) if DEBUG;
# This loops over the response headers and adds them to headers_out.
# Override any headers with our own here
my %headers;
$r->headers_out->clear();
$class->translate_cookie_and_auth_headers( $r, $res );
# Create a hash with the HTTP::Response HTTP::Headers attributes
$res->scan( sub { $headers{ $_[0] } = $_[1]; } );
$r->log->debug(
sprintf( "$$ not cookie/auth headers: %s", Dumper( \%headers ) ) )
if VERBOSE_DEBUG;
## Set the response content type from the request, preserving charset
$r->content_type( $headers{'Content-Type'} );
delete $headers{'Content-Type'};
# need to encode content if utf-8
my $charset = $class->response_charset($r, $res);
$r->log->debug("$$ charset is $charset") if DEBUG;
if (($charset ne 'ISO-8859-1') && ($r->content_type !~ m/image|video/)) {
$$response_content_ref = Encode::encode($charset,
$$response_content_ref);
}
#############################
## Content languages
if ( defined $headers{'content-language'} ) {
$r->content_languages( [ $res->header('content-language') ] );
$r->log->debug(
"$$ content languages set to " . $res->header('content_language') )
if DEBUG;
delete $headers{'Content-Language'};
}
##################
# content_encoding
# do not mess with this next section unless you like pain
my $encoding;
if (($r->content_type !~ m/image|video/) &&
((length($$response_content_ref) != 0) or
($headers{'Content-Length'} != 0)) &&
( $r->pnotes('client_supports_compression') )) {
$r->log->debug( "$$ client supports compression: "
. $r->pnotes('client_supports_compression') )
if DEBUG;
my @h =
map { $_->[0] }
HTTP::Headers::Util::split_header_words(
$r->pnotes('client_supports_compression') );
$r->log->debug( "$$ header words are " . join( ',', @h ) )
if VERBOSE_DEBUG;
# use the first acceptable compression, ordered by
if ( grep { $_ eq 'x-bzip2' } @h ) {
$response_content_ref =
Compress::Bzip2::compress($$response_content_ref);
$encoding = 'x-bzip2';
}
elsif (( grep { $_ eq 'gzip' } @h )
|| ( grep { $_ eq 'x-gzip' } @h ) )
{ # some parts lifted from HTTP::Message
# need a copy for memgzip, see HTTP::Message notes
my $gzipped =
eval { Compress::Zlib::memGzip($response_content_ref); };
my $err = $@;
if ($err) {
$r->log->error("compression error: $err");
} else {
$r->log->debug("$$ compressed response from " . length($$response_content_ref) . " to " . length($gzipped)) if DEBUG;
$$response_content_ref = $gzipped;
$encoding = 'gzip';
}
}
elsif ( grep { $_ eq 'deflate' } @h ) {
my $copy = $$response_content_ref;
$$response_content_ref = Compress::Zlib::compress($copy);
$encoding = 'deflate';
}
else {
$r->log->error( "$$ unknown content-encoding encountered: "
. join( ',', @h ) );
}
}
if ($encoding) {
$r->log->debug("$$ setting content encoding to $encoding") if DEBUG;
$r->content_encoding($encoding);
delete $headers{'Transfer-Encoding'}; # don't want to be chunked here
}
delete $headers{'Content-Encoding'};
###########################
# set the content length to the uncompressed content length
$r->set_content_length( length($$response_content_ref) );
delete $headers{'Content-Length'};
##########################################
# this is for any additional headers, usually site specific
$class->translate_remaining_headers( $r, \%headers );
###############################
# possible through a nasty hack, set the server version
$r->server->add_version_component( $headers{Server} || 'sl' );
###############################
# maybe someday but not today, do not cache this response
$r->no_cache(1);
return 1;
}
# figure out what charset a response was made in, code adapted from
# HTTP::Message::decoded_content
sub response_charset {
my ( $class, $r, $response ) = @_;
# pull apart Content-Type header and extract charset
my $charset;
my @ct = HTTP::Headers::Util::split_header_words(
$response->header("Content-Type") );
if (@ct) {
my ( undef, undef, %ct_param ) = @{ $ct[-1] };
$charset = $ct_param{charset};
}
# if the charset wasn't in the http header look for meta-equiv
unless ($charset) {
# default charset for HTTP::Message - if it couldn't guess it will
# have decoded as 8859-1, so we need to match that when
# re-encoding
return $charset || "ISO-8859-1";
}
}
sub resolve {
my ( $class, $hostname ) = @_;
# run the dns query
my $query = $Resolver->query($hostname);
unless ($query) {
die "dns resolution failed: " . $Resolver->errorstring;
}
else {
foreach my $rr ( $query->answer ) {
next unless $rr->type eq "A";
# return the A record
return $rr->address;
}
}
die "could not resolve A record for $hostname";
}
sub handler {
my ( $class, $r ) = @_;
unless ($r->hostname) {
$r->log->error("$$ no hostname for req " . $r->as_string);
return Apache2::Const::HTTP_BAD_REQUEST;
}
# Build the request headers
my $headers = $class->get_request_headers($r);
my $url = $r->construct_url($r->unparsed_uri);
$r->pnotes('url' => $url);
my %get = (
headers => $headers,
url => $url,
);
my $ip;
if ($r->hostname !~ m/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
$r->log->debug( "$$ resolving host " . $r->hostname ) if DEBUG;
$ip = eval { $class->resolve( $r->hostname ) };
if ($@) {
# dns error
$r->log->error( "$$ unable to resolve host " . $r->hostname );
return &crazypage($r); # haha this page is kwazy!
}
} else {
$ip = $r->hostname
( run in 1.942 second using v1.01-cache-2.11-cpan-39bf76dae61 )