File Coverage

blib/lib/Dancer/Middleware/Rebase.pm
Criterion Covered Total %
statement 20 20 100.0
branch 5 6 83.3
condition 3 3 100.0
subroutine 5 5 100.0
pod 1 1 100.0
total 34 35 97.1


line stmt bran cond sub pod time code
1             package Dancer::Middleware::Rebase;
2             BEGIN {
3 3     3   72598 $Dancer::Middleware::Rebase::VERSION = '0.8.0';
4             }
5              
6             # ABSTRACT: a Plack middleware to be used for Dancer
7              
8 3     3   26 use strict;
  3         6  
  3         104  
9 3     3   2451 use parent qw( Plack::Middleware );
  3         952  
  3         18  
10 3     3   79317 use URI ();
  3         17985  
  3         693  
11              
12             sub call {
13 5     5 1 4093 my ($self, $env) = @_;
14              
15             # prepare cached data if it's the first call
16 5 50       175 if (!$self->{replacement}) {
17 5         41 my $uri = URI->new($self->{base});
18 5         16609 $self->{replacement} = {
19             'psgi.url_scheme' => $uri->scheme(),
20             'HTTP_HOST' => $uri->authority(),
21             'SCRIPT_NAME' => $uri->path(),
22             };
23              
24 5 100 100     611 $self->{strip} = $uri->path()
25             if $self->{strip} && substr($self->{strip}, 0, 1) ne '/';
26             } ## end if (!$self->{replacement...
27              
28             # override due variables in $env
29 5         34 while (my ($k, $v) = each %{$self->{replacement}}) {
  20         79  
30 15         37 $env->{$k} = $v;
31             }
32              
33             # strip prefix from PATH_INFO if applicable
34 5 100       47 $env->{PATH_INFO} =~ s/\A $self->{strip}//mxs if $self->{strip};
35              
36 5         34 return $self->app()->($env);
37             } ## end sub call
38              
39             1;
40              
41              
42             =pod
43              
44             =head1 NAME
45              
46             Dancer::Middleware::Rebase - a Plack middleware to be used for Dancer
47              
48             =head1 VERSION
49              
50             version 0.8.0
51              
52             =head1 DESCRIPTION
53              
54             This is a L specifically geared to the L
55             framework. The goal is to let you rebase your application easily, i.e.
56             let you move your application that usually lives in
57             C into C or
58             even C.
59              
60             This can be particularly useful in a reverse-proxy deployment, where
61             the application is called by the proxy HTTP server and thus lives
62             in a different namespace with respect to the one available to the
63             end user.
64              
65             Suppose for example that you have a reverse-proxy deployment, where
66             the end user calls route C in your application using the
67             URI C. If you are using Apache with
68             the following configuration:
69              
70             ProxyPass /app/ http://internal:3000/
71             ProxyPassReverse /app/ http://internal:3000/
72              
73             then the route in your application will be called as
74             C. This leads to two problems:
75              
76             =over
77              
78             =item *
79              
80             both C and C refer to C.
81             This means that it's very likely that your links will be wrong, e.g.
82             consider the link to the CSS file in a standard Dancer application:
83              
84            
85              
86             This will be expanded to C which
87             will not be accessible by the end user. This particular problem
88             can be addressed using L, which
89             massages C<$env> in order to restore the originally requested
90             scheme, host and port;
91              
92             =item *
93              
94             the additional path prefix C has been stripped by Apache and
95             there is no reference to it. While the problem above can be addressed
96             with L, there is no standard solution
97             for addressing this issue and you have to work out your own.
98              
99             =back
100              
101             You might think that you can address the latter problem with a proper
102             Apache configuration:
103              
104             ProxyPass /app/ http://internal:3000/app/
105             ProxyPassReverse /app/ http://internal:3000/app/
106              
107             but with this configuration you receive a request towards
108             C, which is not going to work
109             smoothly for different reasons:
110              
111             =over
112              
113             =item *
114              
115             you have to set a proper prefix for rebasing all the routes;
116              
117             =item *
118              
119             even so, you are not able to rebase the static part of the site,
120             i.e. your CSS files are still ruled out unless you address them
121             specifically in the Apache configuration.
122              
123             =back
124              
125             Dancer::Middleware::Rebase addresses all these problems at the same time.
126             You can set a base URI that will be propagated in the C<$env> passed to your
127             application. In particular, it will set all
128             the proper variables that are then used by L methods
129             C and C in order to establish the URI where all
130             stuff can be referred.
131              
132             In case you like keeping the prefix part in the Apache configuration,
133             anyway, you still have the problem of stripping it before giving it
134             to the application. In this case, you can set a C parameter
135             to eliminate the prefix from the C component of C<$env>.
136              
137             =head1 CONFIGURATION
138              
139             This module is a C, so you have to configure it
140             inside C like this:
141              
142             plack_middlewares:
143             -
144             - "+Dancer::Middleware::Rebase"
145             - base
146             - "http://example.com/app"
147             - strip
148             - 1
149              
150             Please note that you have to put a plus sign before the module name,
151             otherwise L will think that it is a name to be referred to the
152             L namespace.
153              
154             You can set the following options:
155              
156             =over
157              
158             =item B<< base >>
159              
160             the URI that has to be set as the base one. This will be what you
161             eventually get when you call C in your code and in
162             your templates, and it is also used by C.
163              
164             =item B<< strip >>
165              
166             either a true value or a string that starts with C. In the
167             first case, the C portion of the C URI will be used
168             as a prefix to be stripped from C, otherwise the
169             specified string is used. You should only need the first
170             approach, anyway.
171              
172             =back
173              
174             =begin whatever
175              
176             =head2 call
177              
178             What L wants us to override. It sets the proper stuff
179             in C<$env> and passes the control to the wrapped application.
180              
181              
182             =end whatever
183              
184             =head1 AUTHOR
185              
186             Flavio Poletti
187              
188             =head1 COPYRIGHT AND LICENSE
189              
190             Copyright (C) 2011 by Flavio Poletti .
191              
192             This module is free software. You can redistribute it and/or
193             modify it under the terms of the Artistic License 2.0.
194              
195             This program is distributed in the hope that it will be useful,
196             but without any warranty; without even the implied warranty of
197             merchantability or fitness for a particular purpose.
198              
199             =cut
200              
201              
202             __END__