File Coverage

blib/lib/Perlbal/Plugin/XFFExtras.pm
Criterion Covered Total %
statement 44 44 100.0
branch 4 8 50.0
condition 3 8 37.5
subroutine 11 11 100.0
pod 0 2 0.0
total 62 73 84.9


line stmt bran cond sub pod time code
1             package Perlbal::Plugin::XFFExtras;
2              
3 1     1   9 use strict;
  1         3  
  1         38  
4 1     1   6 use warnings;
  1         2  
  1         37  
5              
6 1     1   4 use Danga::Socket 1.53; # Need newer Danga::Socket than perlbal to have local_port
  1         60  
  1         27  
7 1     1   6 use Perlbal 1.74; # is_ssl support was added in 1.74
  1         16  
  1         20  
8 1     1   7 use Perlbal::BackendHTTP ();
  1         3  
  1         23  
9 1     1   5 use Perlbal::Service ();
  1         2  
  1         116  
10              
11             sub load {
12 1     1 0 10 Perlbal::Service::add_tunable(
13             send_backend_port => {
14             check_role => 'reverse_proxy',
15             des => "Send an X-Forwarded-Port header to backends to indicate the peer's remote address",
16             check_type => 'bool',
17             default => 0,
18             }
19             );
20 1         6 Perlbal::Service::add_tunable(
21             send_backend_proto => {
22             check_role => 'reverse_proxy',
23             des => "Send an X-Forwarded-Proto header to backends to indicate the peers connecting protocol",
24             check_type => 'bool',
25             default => 0,
26             }
27             );
28             }
29              
30             # magical Perlbal hook return value constants
31 1     1   5 use constant HANDLE_REQUEST => 0;
  1         2  
  1         73  
32 1     1   5 use constant IGNORE_REQUEST => 1;
  1         3  
  1         271  
33              
34             sub register {
35 1     1 0 2 my ($class, $svc) = @_;
36              
37 1   50     4 my $cfg = $svc->{extra_config} ||= {};
38              
39             $svc->register_hook(XFFExtras => backend_client_assigned => sub {
40 1     1   2 my Perlbal::BackendHTTP $be = shift;
41 1         3 my $hds = $be->{req_headers};
42 1         3 my $client = $be->{client};
43 1         5 my $client_ip = $client->peer_ip_string;
44              
45 1         16 my $trusted = $svc->trusted_ip($client_ip);
46 1         3 my $blind = $svc->{blind_proxy};
47 1 50 33     9 if (($trusted && !$blind) || !$trusted) {
      33        
48 1 50       5 if ($cfg->{send_backend_port}) {
49             # Danga::Socket has no accessor for the peer_port, so we break object
50             # boundaries for now to implement this. Force to integer because D::S
51             # also likes to store string error messages in this field too.
52 1         16 $client->local_ip_string;
53 1         37 my $local_port = $client->{local_port} + 0;
54 1         4 $hds->header("X-Forwarded-Port", $local_port);
55             }
56 1 50       5 if ($cfg->{send_backend_proto}) {
57 1 50       5 my $proto = $client->{is_ssl} ? 'https' : 'http';
58 1         5 $hds->header("X-Forwarded-Proto", $proto);
59             }
60             }
61              
62 1         4 return HANDLE_REQUEST;
63 1         9 });
64             }
65              
66             1;
67              
68             __END__