File Coverage

blib/lib/Plack/Middleware/XForwardedFor.pm
Criterion Covered Total %
statement 38 38 100.0
branch 12 14 85.7
condition 1 2 50.0
subroutine 7 7 100.0
pod 2 2 100.0
total 60 63 95.2


line stmt bran cond sub pod time code
1             package Plack::Middleware::XForwardedFor;
2             # ABSTRACT: Plack middleware to handle X-Forwarded-For headers
3             $Plack::Middleware::XForwardedFor::VERSION = '0.172050';
4 1     1   836 use strict;
  1         3  
  1         38  
5 1     1   9 use warnings;
  1         3  
  1         46  
6 1     1   8 use parent qw(Plack::Middleware);
  1         2  
  1         9  
7 1     1   95 use Plack::Util::Accessor qw(trust);
  1         11  
  1         11  
8 1     1   914 use Net::IP qw();
  1         75284  
  1         458  
9              
10             sub prepare_app {
11 10     10 1 9744 my $self = shift;
12              
13 10 100       40 if (my $trust = $self->trust) {
14 8 100       76 my @trust = map { Net::IP->new($_) } ref($trust) ? @$trust : ($trust);
  11         2292  
15 8         11425 $self->trust(\@trust);
16             }
17             }
18              
19             sub call {
20 10     10 1 398 my ($self, $env) = @_;
21              
22             my @forward =
23 16         40 map { s/^::ffff://; $_ }
  16         74  
24 10   50     77 (split(/,\s*/, ($env->{HTTP_X_FORWARDED_FOR} || '')));
25              
26 10 50       37 if (@forward) {
27 10         24 my $addr = $env->{REMOTE_ADDR};
28 10         23 $addr =~ s/^::ffff://;
29              
30 10 100       35 if (my $trust = $self->trust) {
31             ADDR: {
32 8 100       54 if (my $next = pop @forward) {
  18         55  
33 13         596 foreach my $netmask (@$trust) {
34 17 50       282 my $ip = Net::IP->new($addr) or redo ADDR;
35 17 100       33779 if ($netmask->overlaps($ip)) {
36 10         3549 $addr = $next;
37 10         50 redo ADDR;
38             }
39             }
40             }
41             }
42             }
43             else { # trust everything, so use first in list
44 2         17 $addr = shift @forward;
45             }
46 10         340 $env->{REMOTE_ADDR} = $addr;
47             }
48              
49 10         45 $self->app->($env);
50             }
51              
52             1;
53              
54             =head1 NAME
55              
56             Plack::Middleware::XForwardedFor - Plack middleware to handle X-Forwarded-For headers
57              
58             =head1 VERSION
59              
60             version 0.172050
61              
62             =head1 SYNOPSIS
63              
64             builder {
65             enable "Plack::Middleware::XForwardedFor",
66             trust => [qw(127.0.0.1/8)];
67             };
68              
69             =head1 DESCRIPTION
70              
71             C will look for C
72             header in the incoming request and change C to the
73             real client IP
74              
75             =head1 PARAMETERS
76              
77             =over
78              
79             =item trust
80              
81             If not specified then all addressed are trusted and C will be set to the
82             first IP in the C header.
83              
84             If given, it should be a list of IPs or Netmasks that can be trusted. Starting with the IP
85             of the client in C then the IPs in the C header from right to left.
86             The first untrusted IP found is set to be C
87              
88             =back
89              
90             =head1 SEE ALSO
91              
92             L, L
93              
94             =head1 AUTHOR
95              
96             Graham Barr
97              
98             =head1 COPYRIGHT AND LICENSE
99              
100             This software is copyright (c) 2010 by Graham Barr.
101              
102             This is free software; you can redistribute it and/or modify it under
103             the same terms as the Perl 5 programming language system itself.
104              
105             =cut