File Coverage

blib/lib/Plack/Middleware/Proxy/RewriteLocation.pm
Criterion Covered Total %
statement 21 52 40.3
branch 2 14 14.2
condition 0 6 0.0
subroutine 7 10 70.0
pod 2 2 100.0
total 32 84 38.1


line stmt bran cond sub pod time code
1             package Plack::Middleware::Proxy::RewriteLocation;
2 3     3   9284 use strict;
  3         7  
  3         187  
3 3     3   33 use parent 'Plack::Middleware';
  3         6  
  3         119  
4              
5 3     3   262 use Plack::Util;
  3         10  
  3         108  
6 3     3   21 use Plack::Util::Accessor 'url_map';
  3         5  
  3         62  
7 3     3   389 use URI;
  3         9  
  3         2566  
8              
9             sub _different_part($$) {
10 0     0   0 my ($from, $to) = @_;
11              
12 0         0 while ($from =~ m{[^/]+(?:\://$|/$|$)}g) {
13 0         0 my $last_part = $&;
14 0 0       0 last unless $to =~ /\Q$last_part\E$/;
15              
16 0         0 $from =~ s!\Q$last_part\E$!!;
17 0         0 $to =~ s!\Q$last_part\E$!!;
18             }
19              
20 0         0 $from => $to;
21             }
22              
23             sub new {
24 26     26 1 27269 my $self = shift->SUPER::new( @_ );
25              
26             # regularize the remote URLs in the URL map
27 26 100       1106 if( my $m = $self->url_map ) {
28 6         252 for( my $i = 1; $i < @$m; $i += 2 ) {
29 8         1964 $m->[$i] = $self->_regularize_url( $m->[$i] );
30             }
31             }
32              
33 26         12119 return $self;
34             }
35              
36             sub call {
37 0     0 1 0 my($self, $env) = @_;
38              
39             return sub {
40 0     0   0 my $respond = shift;
41              
42 0         0 my $cb = $self->app->($env);
43 0 0       0 return $respond->( $cb ) unless ref $cb eq 'CODE';
44              
45             $cb->(sub {
46 0         0 my $res = shift;
47              
48 0 0 0     0 if ( $env->{HTTP_HOST} and my $location = Plack::Util::header_get($res->[1], 'Location') ) {
49              
50 0         0 my @map;
51 0 0       0 if ($self->url_map) {
52             # regularize the format of the location so we can
53             # compare it correctly (some apps print this
54             # non-canonically)
55 0         0 $location = $self->_regularize_url( $location );
56              
57 0         0 my $proxy = "$env->{'psgi.url_scheme'}://$env->{HTTP_HOST}";
58 0         0 my @url_map = @{$self->url_map};
  0         0  
59              
60 0         0 while(my ($proxy_path, $remote) = splice @url_map, 0, 2) {
61 0         0 push @map, "$proxy$proxy_path" => $remote;
62             }
63             } else {
64             # Auto-guessing url_map
65 0         0 my $original_url = "$env->{'psgi.url_scheme'}://" .
66             $env->{HTTP_HOST} .
67             $env->{SCRIPT_NAME} .
68             $env->{PATH_INFO};
69 0 0 0     0 $original_url .= '?' . $env->{QUERY_STRING}
70             if defined $env->{QUERY_STRING} && $env->{QUERY_STRING};
71 0         0 @map = _different_part(
72             $original_url => $env->{'plack.proxy.last_url'}
73             );
74             }
75              
76 0         0 while(my ($proxy_url, $remote) = splice @map, 0, 2) {
77 0 0       0 last if $location =~ s!^$remote!$proxy_url!;
78             }
79              
80 0         0 $location =~ s!//$!/!; #< avoid double slashes
81              
82 0         0 Plack::Util::header_set( $res->[1], 'Location' => $location );
83             }
84              
85 0         0 return $respond->( $res );
86 0         0 });
87 0         0 };
88             }
89              
90             sub _regularize_url {
91 8     8   424 '' . URI->new( $_[1] )->canonical
92             }
93              
94             1;
95              
96             __END__