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   1166 use Mojo::Base 'Mojolicious::Plugin';
  1         4  
  1         6  
4 1     1   213 use Mojo::Util 'trim';
  1         2  
  1         123  
5              
6             our $VERSION = '0.002';
7              
8             sub register {
9 6     6 1 11954 my ($self, $app, $options) = @_;
10              
11 6         16 my ($levels, $err);
12             {
13 6         14 local $@;
  6         11  
14 1     1   8 use warnings FATAL => 'numeric';
  1         2  
  1         325  
15 6 100 66     15 unless (eval { $levels = int($options->{levels} // $ENV{MOJO_REVERSE_PROXY} // 1); 1 }) {
  6   50     61  
  3         12  
16 3         10 $err = $@;
17             }
18             }
19              
20 6 100       42 die "Invalid reverse proxy 'levels' for ForwardedFor: $err" if defined $err;
21              
22             $app->helper(forwarded_for => sub {
23 12     12   102488 my $c = shift;
24 12 100       45 return $c->tx->original_remote_address unless $levels > 0;
25 8   100     23 my @addresses = split /\s*,\s*/, trim($c->tx->req->headers->header('X-Forwarded-For') // '');
26 8   100     374 return $addresses[-$levels] // $addresses[0] // $c->tx->original_remote_address;
      66        
27 3         31 });
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             Since Mojolicious 8.72, you can configure
65             L as a more reliable alternative to
66             the baseline reverse proxy configuration, affecting
67             L directly without need of this plugin.
68              
69             =head1 HELPERS
70              
71             L implements the following helpers.
72              
73             =head2 forwarded_for
74              
75             my $remote_addr = $c->forwarded_for;
76              
77             Returns the least recently appended remote address from the C
78             header, while skipping no more than the configured number of reverse proxy
79             L. Returns the originating address of the current request if
80             configured for 0 reverse proxy levels, or if no addresses have been appended to
81             the header.
82              
83             =head1 METHODS
84              
85             L inherits all methods from
86             L and implements the following new ones.
87              
88             =head2 register
89              
90             $plugin->register(Mojolicious->new);
91             $plugin->register(Mojolicious->new, {levels => 1});
92              
93             Register helper in L application. Takes the following options:
94              
95             =over 4
96              
97             =item levels
98              
99             Number of remote proxy levels to allow for when parsing C.
100             Defaults to the value of the C environment variable, or 1.
101              
102             =back
103              
104             =head1 BUGS
105              
106             Report any issues on the public bugtracker.
107              
108             =head1 AUTHOR
109              
110             Dan Book
111              
112             =head1 COPYRIGHT AND LICENSE
113              
114             This software is Copyright (c) 2018 by Dan Book.
115              
116             This is free software, licensed under:
117              
118             The Artistic License 2.0 (GPL Compatible)
119              
120             =head1 SEE ALSO
121              
122             L, L