File Coverage

blib/lib/Plack/Middleware/TrafficAdvice.pm
Criterion Covered Total %
statement 50 54 92.5
branch 13 20 65.0
condition n/a
subroutine 12 12 100.0
pod 2 3 66.6
total 77 89 86.5


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   1570947 use v5.12;
  3         16  
6 3     3   67 use warnings;
  3         12  
  3         237  
7              
8 3     3   19 use parent 'Plack::Middleware';
  3         6  
  3         28  
9              
10 3     3   242 use Plack::Util::Accessor qw/ data file /;
  3         9  
  3         29  
11              
12 3     3   171 use Cwd;
  3         6  
  3         325  
13 3     3   4194 use File::Temp qw/ tempfile /;
  3         42807  
  3         271  
14 3     3   1484 use HTTP::Date;
  3         19528  
  3         255  
15 3     3   25 use HTTP::Status qw/ :constants /;
  3         10  
  3         1553  
16 3     3   29 use JSON::MaybeXS 1.004000;
  3         112  
  3         2189  
17              
18             our $VERSION = 'v0.3.1';
19              
20              
21             sub prepare_app {
22 3     3 1 377 my ($self) = @_;
23              
24 3 100       16 if (my $data = $self->data) {
    50          
25              
26 2 50       107 if ($self->file) {
27 0         0 die "Cannot specify both data and file";
28             }
29              
30 2         18 my ($fh, $filename) = tempfile('traffic-advice-XXXXXXXX', SUFFIX => '.json', UNLINK => 0, TMPDIR => 1);
31 2         1913 $self->file( $filename );
32              
33 2 100       22 if (ref($data)) {
34 1         10 my $encoder = JSON::MaybeXS->new( { utf8 => 1 } );
35 1 50       28 print {$fh} $encoder->encode($data)
  1         20  
36             or die "Unable to write data";
37             }
38             else {
39 1 50       31 print {$fh} $data
  1         10  
40             or die "Unable to write data";
41             }
42              
43 2         122 close $fh;
44              
45              
46             }
47             elsif (my $file = $self->file) {
48              
49 1 50       100 unless (-r $file) {
50 0         0 die "Cannot read file: '$file'";
51             }
52              
53             }
54             else {
55 0         0 die "Either data or file must be configured";
56             }
57              
58             }
59              
60             sub call {
61 5     5 1 99709 my ( $self, $env ) = @_;
62              
63 5 50       304 unless ( $env->{REQUEST_URI} eq '/.well-known/traffic-advice' ) {
64 0         0 return $self->app->($env);
65             }
66              
67 5 100       40 unless ( $env->{REQUEST_METHOD} =~ /^(GET|HEAD)$/ ) {
68 1         6 return $self->error( HTTP_METHOD_NOT_ALLOWED, "Not Allowed" );
69             }
70              
71 4         30 my $file = $self->file;
72              
73             # Some of this is based on Plack::App::File.
74              
75 4 50       280 open my $fh, "<:raw", $file
76             or return $self->error( HTTP_INTERNAL_SERVER_ERROR, "Internal Error" );
77              
78 4         86 my @stat = stat $file;
79              
80 4         147 Plack::Util::set_io_path($fh, Cwd::realpath($file));
81              
82             [
83 4         167 HTTP_OK,
84             [
85             'Content-Type' => 'application/trafficadvice+json',
86             'Content-Length' => $stat[7],
87             'Last-Modified' => HTTP::Date::time2str( $stat[9] )
88             ],
89             $fh,
90             ];
91              
92             }
93              
94              
95             sub error {
96 1     1 0 4 my ($self, $code, $message) = @_;
97 1         13 return [ $code, [ 'Content-Type' => 'text/plain', 'Content-Length' => length($message) ], [ $message ] ];
98             }
99              
100             1;
101              
102             __END__