File Coverage

blib/lib/Plack/Middleware/TrafficAdvice.pm
Criterion Covered Total %
statement 53 57 92.9
branch 13 20 65.0
condition n/a
subroutine 13 13 100.0
pod 2 3 66.6
total 81 93 87.1


line stmt bran cond sub pod time code
1             package Plack::Middleware::TrafficAdvice;
2              
3             # ABSTRACT: handle requests for /.well-known/traffic-advice
4              
5 3     3   1591 use v5.8.5;
  3         17  
6              
7 3     3   13 use strict;
  3         5  
  3         47  
8 3     3   11 use warnings;
  3         6  
  3         101  
9              
10 3     3   16 use parent 'Plack::Middleware';
  3         3  
  3         14  
11              
12 3     3   231 use Plack::Util::Accessor qw/ data file /;
  3         6  
  3         20  
13              
14 3     3   192 use Cwd;
  3         6  
  3         205  
15 3     3   1791 use File::Temp qw/ tempfile /;
  3         24359  
  3         151  
16 3     3   1128 use HTTP::Date;
  3         9679  
  3         180  
17 3     3   19 use HTTP::Status qw/ :constants /;
  3         5  
  3         1077  
18 3     3   19 use JSON::MaybeXS 1.004000;
  3         53  
  3         1258  
19              
20             our $VERSION = 'v0.2.2';
21              
22              
23             sub prepare_app {
24 3     3 1 262 my ($self) = @_;
25              
26 3 100       10 if (my $data = $self->data) {
    50          
27              
28 2 50       79 if ($self->file) {
29 0         0 die "Cannot specify both data and file";
30             }
31              
32 2         14 my ($fh, $filename) = tempfile('traffic-advice-XXXXXXXX', SUFFIX => '.json', UNLINK => 0, TMPDIR => 1);
33 2         1036 $self->file( $filename );
34              
35 2 100       42 if (ref($data)) {
36 1         7 my $encoder = JSON::MaybeXS->new( { utf8 => 1 } );
37 1 50       18 print {$fh} $encoder->encode($data)
  1         35  
38             or die "Unable to write data";
39             }
40             else {
41 1 50       2 print {$fh} $data
  1         35  
42             or die "Unable to write data";
43             }
44              
45 2         126 close $fh;
46              
47              
48             }
49             elsif (my $file = $self->file) {
50              
51 1 50       62 unless (-r $file) {
52 0         0 die "Cannot read file: '$file'";
53             }
54              
55             }
56             else {
57 0         0 die "Either data or file must be configured";
58             }
59              
60             }
61              
62             sub call {
63 5     5 1 68523 my ( $self, $env ) = @_;
64              
65 5 50       18 unless ( $env->{REQUEST_URI} eq '/.well-known/traffic-advice' ) {
66 0         0 return $self->app->($env);
67             }
68              
69 5 100       29 unless ( $env->{REQUEST_METHOD} =~ /^(GET|HEAD)$/ ) {
70 1         4 return $self->error( HTTP_METHOD_NOT_ALLOWED, "Not Allowed" );
71             }
72              
73 4         16 my $file = $self->file;
74              
75             # Some of this is based on Plack::App::File.
76              
77 4 50       160 open my $fh, "<:raw", $file
78             or return $self->error( HTTP_INTERNAL_SERVER_ERROR, "Internal Error" );
79              
80 4         48 my @stat = stat $file;
81              
82 4         91 Plack::Util::set_io_path($fh, Cwd::realpath($file));
83              
84             [
85 4         137 HTTP_OK,
86             [
87             'Content-Type' => 'application/trafficadvice+json',
88             'Content-Length' => $stat[7],
89             'Last-Modified' => HTTP::Date::time2str( $stat[9] )
90             ],
91             $fh,
92             ];
93              
94             }
95              
96              
97             sub error {
98 1     1 0 3 my ($self, $code, $message) = @_;
99 1         7 return [ $code, [ 'Content-Type' => 'text/plain', 'Content-Length' => length($message) ], [ $message ] ];
100             }
101              
102             1;
103              
104             __END__