File Coverage

blib/lib/HTTP/Proxy/HeaderFilter/standard.pm
Criterion Covered Total %
statement 40 49 81.6
branch 11 20 55.0
condition 12 14 85.7
subroutine 7 7 100.0
pod 1 1 100.0
total 71 91 78.0


line stmt bran cond sub pod time code
1             package HTTP::Proxy::HeaderFilter::standard;
2             $HTTP::Proxy::HeaderFilter::standard::VERSION = '0.303';
3 69     69   207 use strict;
  69         84  
  69         1675  
4 69     69   214 use HTTP::Proxy;
  69         50  
  69         1203  
5 69     69   24539 use HTTP::Headers::Util qw( split_header_words );
  69         36284  
  69         3156  
6 69     69   18948 use HTTP::Proxy::HeaderFilter;
  69         116  
  69         1417  
7 69     69   243 use vars qw( @ISA );
  69         77  
  69         27231  
8             @ISA = qw( HTTP::Proxy::HeaderFilter );
9              
10             # known hop-by-hop headers
11             my @hopbyhop =
12             qw( Connection Keep-Alive Proxy-Authenticate Proxy-Authorization
13             TE Trailers Transfer-Encoding Upgrade Proxy-Connection Public );
14              
15             # standard proxy header filter (RFC 2616)
16             sub filter {
17 152     152 1 10887 my ( $self, $headers, $message ) = @_;
18              
19             # the Via: header
20 152   100     557 my $via = $message->protocol() || '';
21 152 100 100     1847 if ( $self->proxy->via and $via =~ s!HTTP/!! ) {
22 143         387 $via .= " " . $self->proxy->via;
23 143   66     479 $headers->header(
24             Via => join ', ',
25             $message->headers->header('Via') || (), $via
26             );
27             }
28              
29             # the X-Forwarded-For header
30             $headers->push_header(
31 152 100 100     10183 X_Forwarded_For => $self->proxy->client_socket->peerhost )
32             if $message->isa( 'HTTP::Request' ) && $self->proxy->x_forwarded_for;
33              
34             # make a list of hop-by-hop headers
35 152         5235 my %h2h = map { (lc) => 1 } @hopbyhop;
  1520         3336  
36 152         672 my $hop = HTTP::Headers->new();
37 152         1141 my $client = HTTP::Headers->new();
38 80         2140 $h2h{ lc $_->[0] } = 1
39 152         885 for map { split_header_words($_) } $headers->header('Connection');
40              
41             # hop-by-hop headers are set aside
42             # as well as LWP::UserAgent Client-* headers
43             $headers->scan(
44             sub {
45 1251     1251   14468 my ( $k, $v ) = @_;
46 1251 100       2178 if ( $h2h{lc $k} ) {
47 166         363 $hop->push_header( $k => $v );
48 166         2527 $headers->remove_header($k);
49             }
50 1251 100       4732 if( $k =~ /^Client-/ ) {
51 143         394 $client->push_header( $k => $v );
52 143         3244 $headers->remove_header($k);
53             }
54             }
55 152         6268 );
56              
57             # set the hop-by-hop and client headers in the proxy
58             # only the end-to-end headers are left in the message
59 152         1580 $self->proxy->hop_headers($hop);
60 152         375 $self->proxy->client_headers($client);
61              
62             # handle Max-Forwards
63 152 50 66     1102 if ( $message->isa('HTTP::Request')
64             and defined $headers->header('Max-Forwards') ) {
65 0         0 my ( $max, $method ) =
66             ( $headers->header('Max-Forwards'), $message->method );
67 0 0       0 if ( $max == 0 ) {
    0          
68             # answer directly TRACE ou OPTIONS
69 0 0       0 if ( $method eq 'TRACE' ) {
    0          
70 0         0 my $response =
71             HTTP::Response->new( 200, 'OK',
72             HTTP::Headers->new( Content_Type => 'message/http'
73             , Content_Length => 0),
74             $message->as_string );
75 0         0 $self->proxy->response($response);
76             }
77             elsif ( $method eq 'OPTIONS' ) {
78 0         0 my $response = HTTP::Response->new(200);
79 0         0 $response->header( Allow => join ', ', @HTTP::Proxy::METHODS );
80 0         0 $self->proxy->response($response);
81             }
82             }
83             # The Max-Forwards header field MAY be ignored for all
84             # other methods defined by this specification (RFC 2616)
85             elsif ( $method =~ /^(?:TRACE|OPTIONS)/ ) {
86 0         0 $headers->header( 'Max-Forwards' => --$max );
87             }
88             }
89              
90             # no encoding accepted (gzip, compress, deflate)
91             # if we plan to do anything with the response body
92 152         344 $headers->remove_header( 'Accept-Encoding' )
93 152 100       1898 if @{ $self->proxy->{body}{response}{filters} };
94             }
95              
96             1;
97              
98             __END__