File Coverage

blib/lib/Pinto/Server/Responder/File.pm
Criterion Covered Total %
statement 37 38 97.3
branch 12 16 75.0
condition 1 3 33.3
subroutine 7 7 100.0
pod 2 3 66.6
total 59 67 88.0


line stmt bran cond sub pod time code
1             # ABSTRACT: Responder for static files
2              
3             package Pinto::Server::Responder::File;
4              
5 12     12   7388 use Moose;
  12         47  
  12         133  
6              
7 12     12   90235 use Plack::Response;
  12         12061  
  12         133  
8 12     12   3460 use Plack::MIME;
  12         8420  
  12         131  
9              
10 12     12   379 use HTTP::Date ();
  12         35  
  12         4089  
11              
12             #-------------------------------------------------------------------------------
13              
14             our $VERSION = '0.14'; # VERSION
15              
16             #-------------------------------------------------------------------------------
17              
18             extends qw(Pinto::Server::Responder);
19              
20             #-------------------------------------------------------------------------------
21              
22             sub respond {
23 81     81 1 222 my ($self) = @_;
24              
25             # e.g. /stack_name/modules/02packages.details.txt.gz
26 81         2523 my ( undef, @path_parts ) = split '/', $self->request->path_info;
27 81         3076 my $file = $self->root->file(@path_parts);
28              
29 81 100       11371 return not_found($file) if not -f $file;
30 58 100       4315 return not_found($file) if index($file, '/../') > 0;
31              
32 57         1894 my @stat = stat($file);
33 57         3772 my $modified_since = HTTP::Date::str2time( $self->request->env->{HTTP_IF_MODIFIED_SINCE} );
34 57 50 33     919 return [ 304, [], [] ] if $modified_since && $stat[9] <= $modified_since;
35              
36 57         526 my $response = Plack::Response->new;
37 57         1227 $response->content_type( Plack::MIME->mime_type($file) );
38 57         5332 $response->content_length( $stat[7] );
39 57         2716 $response->header( 'Last-Modified' => HTTP::Date::time2str( $stat[9] ) );
40              
41 57 50       3654 $response->header( 'Cache-Control' => 'no-cache' ) if $self->should_not_cache($file);
42              
43 57 50       3504 $response->body( $file->openr ) unless $self->request->method eq "HEAD";
44 57         11406 $response->status(200);
45              
46 57         2282 return $response;
47             }
48              
49             #-------------------------------------------------------------------------------
50              
51              
52             #-------------------------------------------------------------------------------
53              
54             sub should_not_cache {
55 57     57 1 207 my ( $self, $file ) = @_;
56              
57             # force caches to always revalidate the indices, i.e.
58             # 01mailrc.txt.gz, 02packages.details.txt.gz, 03modlist.data.gz
59              
60 57         284 my $basename = $file->basename;
61              
62 57 100       479 return 1 if $basename eq '01mailrc.txt.gz';
63 37 100       249 return 1 if $basename eq '02packages.details.txt.gz';
64 20 50       110 return 1 if $basename eq '03modlist.data.gz';
65 0         0 return 0;
66             }
67              
68             #-------------------------------------------------------------------------------
69              
70             sub not_found {
71 24     24 0 1348 my $file = shift;
72 24         103 my $body = "File $file not found";
73 24         739 my $headers = [ 'Content-Type' => 'text/plain', 'Content-Length' => length($body) ];
74 24         1019 return [ 404, $headers, [$body] ];
75             }
76              
77             #-------------------------------------------------------------------------------
78              
79             __PACKAGE__->meta->make_immutable;
80              
81             #-------------------------------------------------------------------------------
82              
83             1;
84              
85             __END__
86              
87             =pod
88              
89             =encoding UTF-8
90              
91             =for :stopwords Jeffrey Ryan Thalhammer
92              
93             =head1 NAME
94              
95             Pinto::Server::Responder::File - Responder for static files
96              
97             =head1 VERSION
98              
99             version 0.14
100              
101             =head1 METHODS
102              
103             =head2 should_not_cache($file)
104              
105             Returns true if the file should not be cached, and therefore the Cache-Control
106             header should be set to 'no-cache' in the response. Currently, only the index
107             files should not be cached.
108              
109             =head1 AUTHOR
110              
111             Jeffrey Ryan Thalhammer <jeff@stratopan.com>
112              
113             =head1 COPYRIGHT AND LICENSE
114              
115             This software is copyright (c) 2015 by Jeffrey Ryan Thalhammer.
116              
117             This is free software; you can redistribute it and/or modify it under
118             the same terms as the Perl 5 programming language system itself.
119              
120             =cut