File Coverage

blib/lib/Mojolicious/Plugin/ForwardedFor.pm
Criterion Covered Total %
statement 23 23 100.0
branch 6 6 100.0
condition 10 13 76.9
subroutine 5 5 100.0
pod 1 1 100.0
total 45 48 93.7


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::ForwardedFor;
2              
3 1     1   1059 use Mojo::Base 'Mojolicious::Plugin';
  1         2  
  1         8  
4 1     1   214 use Mojo::Util 'trim';
  1         2  
  1         106  
5              
6             our $VERSION = '0.001';
7              
8             sub register {
9 6     6 1 12428 my ($self, $app, $options) = @_;
10              
11 6         15 my ($levels, $err);
12             {
13 6         13 local $@;
  6         13  
14 1     1   6 use warnings FATAL => 'numeric';
  1         3  
  1         305  
15 6 100 66     16 unless (eval { $levels = int($options->{levels} // $ENV{MOJO_REVERSE_PROXY} // 1); 1 }) {
  6   50     60  
  3         12  
16 3         9 $err = $@;
17             }
18             }
19              
20 6 100       43 die "Invalid reverse proxy 'levels' for ForwardedFor: $err" if defined $err;
21              
22             $app->helper(forwarded_for => sub {
23 12     12   105627 my $c = shift;
24 12 100       74 return $c->tx->original_remote_address unless $levels > 0;
25 8   100     31 my @addresses = split /\s*,\s*/, trim($c->tx->req->headers->header('X-Forwarded-For') // '');
26 8   100     476 return $addresses[-$levels] // $addresses[0] // $c->tx->original_remote_address;
      66        
27 3         28 });
28             }
29              
30             1;
31              
32             =head1 NAME
33              
34             Mojolicious::Plugin::ForwardedFor - Retrieve the remote address from X-Forwarded-For
35              
36             =head1 SYNOPSIS
37              
38             use Mojolicious::Lite;
39             plugin ForwardedFor => {levels => 2}; # number of reverse proxies you control
40             any '/' => sub {
41             my $c = shift;
42             $c->render(json => {remote_addr => $c->forwarded_for});
43             };
44             app->start;
45              
46             =head1 DESCRIPTION
47              
48             L supports deployment via a
49             L setup by
50             specifying the L configuration option
51             for Hypnotoad, or the C environment variable. However,
52             L will in this case only return the most
53             recent address from the C header, as it cannot automatically
54             determine how many remote addresses correspond to proxies.
55              
56             L can be configured with the number of
57             reverse proxy L that you control, and provides a L
58             helper method that will return the remote address at that level. It is
59             important to set L no higher than the number of proxies that will
60             have appended addresses to the C header, as the original
61             requests can pass anything as the initial value of the header, and thus spoof
62             additional proxy levels.
63              
64             =head1 HELPERS
65              
66             L implements the following helpers.
67              
68             =head2 forwarded_for
69              
70             my $remote_addr = $c->forwarded_for;
71              
72             Returns the least recently appended remote address from the C
73             header, while skipping no more than the configured number of reverse proxy
74             L. Returns the originating address of the current request if
75             configured for 0 reverse proxy levels, or if no addresses have been appended to
76             the header.
77              
78             =head1 METHODS
79              
80             L inherits all methods from
81             L and implements the following new ones.
82              
83             =head2 register
84              
85             $plugin->register(Mojolicious->new);
86             $plugin->register(Mojolicious->new, {levels => 1});
87              
88             Register helper in L application. Takes the following options:
89              
90             =over 4
91              
92             =item levels
93              
94             Number of remote proxy levels to allow for when parsing C.
95             Defaults to the value of the C environment variable, or 1.
96              
97             =back
98              
99             =head1 BUGS
100              
101             Report any issues on the public bugtracker.
102              
103             =head1 AUTHOR
104              
105             Dan Book
106              
107             =head1 COPYRIGHT AND LICENSE
108              
109             This software is Copyright (c) 2018 by Dan Book.
110              
111             This is free software, licensed under:
112              
113             The Artistic License 2.0 (GPL Compatible)
114              
115             =head1 SEE ALSO
116              
117             L, L