| 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 |