File Coverage

blib/lib/Plack/Middleware/FixMissingBodyInRedirect.pm
Criterion Covered Total %
statement 52 52 100.0
branch 19 22 86.3
condition 12 15 80.0
subroutine 10 10 100.0
pod 1 1 100.0
total 94 100 94.0


line stmt bran cond sub pod time code
1             package Plack::Middleware::FixMissingBodyInRedirect;
2 1     1   480 use strict;
  1         2  
  1         29  
3 1     1   3 use warnings;
  1         2  
  1         28  
4 1     1   10 use parent qw( Plack::Middleware );
  1         1  
  1         6  
5              
6 1     1   51 use Plack::Util;
  1         1  
  1         19  
7 1     1   455 use HTML::Entities;
  1         6314  
  1         72  
8 1     1   5 use Scalar::Util qw(blessed);
  1         1  
  1         374  
9             # ABSTRACT: Plack::Middleware which sets body for redirect response, if it's not already set
10              
11             our $VERSION = '0.12';
12              
13             sub call {
14 14     14 1 50116 my $self = shift;
15              
16             return $self->response_cb($self->app->(@_), sub {
17 14     14   1635 my $res = shift;
18 14 50 33     80 return unless $res->[0] >= 300 && $res->[0] < 400;
19 14         31 my $headers = Plack::Util::headers($res->[1]); # first index contains HTTP header
20 14 50       258 if( $headers->exists('Location') ) {
21 14         400 my $location = $headers->get("Location");
22             # checking if body (which is at index 2) is set or not
23 14 100 100     319 if (@$res == 3 && !_is_body_set($res->[2])) {
    100 100        
24 5         10 my $body = $self->_default_html_body($location);
25 5         9 $res->[2] = [$body];
26 5         16 my $content_length = Plack::Util::content_length([$body]);
27 5         56 $headers->set('Content-Length' => $content_length);
28 5         139 $headers->set('Content-Type' => 'text/html; charset=utf-8');
29 5         163 return;
30             }
31             elsif (@$res == 2 || blessed($res->[2])) {
32 4 100       12 if(! $headers->exists('Content-Type')) {
33 2         43 $headers->set('Content-Type' => 'text/html; charset=utf-8')
34             }
35 4         83 my $done;
36             return sub {
37 8         466 my $chunk = shift;
38 8 100       17 return $chunk if $done;
39 4 100       9 if (!defined $chunk) {
    50          
40 2         3 $done = 1;
41 2         4 return $self->_default_html_body($location);
42             }
43             elsif (length $chunk) {
44 2         2 $done = 1;
45             }
46 2         6 return $chunk;
47 4         33 };
48             }
49             }
50 14         40 });
51             }
52              
53             sub _default_html_body {
54 7     7   6 my ($self_or_class, $location) = @_;
55 7         17 my $encoded_location = encode_entities($location);
56 7         73 return <<"EOF";
57            
58            
59            
60             Moved
61            
62            
63            

This item has moved here.

64            
65            
66             EOF
67             }
68              
69             sub _is_body_set {
70 12     12   13 my $body = shift;
71 12 100 66     27 if (ref $body eq 'ARRAY') {
    100 100        
72 8 100       13 return grep { defined && length } @$body;
  11         92  
73             }
74             elsif (Plack::Util::is_real_fh($body) && -f $body && -z _) {
75 1         59 return 0;
76             }
77 3         145 return 1;
78             }
79              
80             1;
81              
82             __END__