File Coverage

blib/lib/Plack/Middleware/RealIP.pm
Criterion Covered Total %
statement 45 45 100.0
branch 16 20 80.0
condition 2 3 66.6
subroutine 8 8 100.0
pod 2 2 100.0
total 73 78 93.5


line stmt bran cond sub pod time code
1             package Plack::Middleware::RealIP;
2 2     2   84874 use strict;
  2         4  
  2         77  
3 2     2   10 use warnings;
  2         3  
  2         42  
4 2     2   61 use 5.008;
  2         8  
5             our $VERSION = 0.04;
6 2     2   472 use parent qw/Plack::Middleware/;
  2         256  
  2         13  
7 2     2   13638 use Net::Netmask;
  2         338404  
  2         354  
8              
9 2     2   22 use Plack::Util::Accessor qw( header trusted_proxy );
  2         5  
  2         23  
10              
11             sub prepare_app {
12 10     10 1 13050 my $self = shift;
13 10         30 local $Net::Netmask::SHORTNET_DEFAULT = 1;
14              
15 10 50       28 if (my $trusted_proxy = $self->trusted_proxy) {
16 10 100       121 my @trusted_proxy = map { Net::Netmask->new($_) } ref($trusted_proxy) ? @{ $trusted_proxy } : ($trusted_proxy);
  17         556  
  4         10  
17 10         754 $self->trusted_proxy(\@trusted_proxy);
18             }
19             }
20              
21             sub call {
22 10     10 1 34383 my $self = shift;
23 10         19 my $env = shift;
24              
25 10         19 my $header;
26 10 50       43 if ($header = $self->header) {
27 10         97 ($header = uc $header) =~ tr/-/_/;
28 10 50       53 $header = "HTTP_$header" unless $header =~ /^(?:HTTP|CONTENT|COOKIE)/;
29             }
30              
31 10         28 my (@remote, @trusted_proxy);
32 10 100       71 @remote = $env->{$header} =~ /([^,\s]+)/g if exists $env->{$header};
33 10 50       33 @trusted_proxy = @{ $self->trusted_proxy } if $self->trusted_proxy;
  10         49  
34              
35 10 100 66     79 if (@remote and @trusted_proxy) {
36 8         32 my @unconfirmed = (@remote, $env->{REMOTE_ADDR});
37              
38 8         24 while (my $addr = pop @unconfirmed) {
39 15         30 my $has_matched = 0;
40 15         31 foreach my $netmask (@trusted_proxy) {
41 26 100       432 $has_matched++, last if $netmask->match($addr);
42             }
43 15 100       654 $env->{REMOTE_ADDR} = $addr, last unless $has_matched;
44             }
45              
46 8 100       20 if (@unconfirmed) {
47 4         15 $env->{$header} = join(', ', @unconfirmed);
48             } else {
49 4         11 delete $env->{$header};
50             }
51             }
52              
53 10         40 return $self->app->($env);
54             }
55              
56             1;
57              
58             =head1 NAME
59              
60             Plack::Middleware::RealIP - Override client IP with header value provided by proxy/load balancer
61              
62             =head1 SYNOPSIS
63              
64             enable 'Plack::Middleware::RealIP',
65             header => 'X-Forwarded-For',
66             trusted_proxy => [qw(192.168.1.0/24 192.168.2.1)];
67              
68             =head1 DESCRIPTION
69              
70             Plack::Middleware::RealIP is loose port of the Apache module
71             mod_remoteip. It overrides C with the IP address advertised
72             in the request header configured with C
.
73              
74             When multiple, comma delimited IP addresses are listed in the header
75             value, they are processed from right to left. The first untrusted IP
76             address found, based on C, stops the processing and is
77             set to be C. The header field is updated to this remaining
78             list of unconfirmed IP addresses, or if all IP addresses were trusted,
79             this header is removed from the request altogether.
80              
81             =head1 CONFIGURATION
82              
83             =head2 header
84              
85             Sets a request header to trust as the client IP, e.g. X-Client-IP
86              
87             =head2 trusted_proxy
88              
89             A list of IP addresses or subnet blocks which are trusted to provide IP header.
90              
91             =head1 AUTHOR
92              
93             Sherwin Daganato Esherwin@daganato.comE
94              
95             Most of the logic is based on L by Graham Barr
96              
97             =head1 CONTRIBUTORS
98              
99             jmaslak: Joelle Maslak
100              
101             =head1 LICENSE
102              
103             This library is free software; you can redistribute it and/or modify
104             it under the same terms as Perl itself.
105              
106             =head1 SEE ALSO
107              
108             L
109              
110             L
111              
112             L
113              
114             L
115              
116             =cut