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   1416 use v5.8.5;
  3         16  
6              
7 3     3   13 use strict;
  3         5  
  3         45  
8 3     3   11 use warnings;
  3         4  
  3         61  
9              
10 3     3   11 use parent 'Plack::Middleware';
  3         5  
  3         16  
11              
12 3     3   200 use Plack::Util::Accessor qw/ data file /;
  3         5  
  3         16  
13              
14 3     3   169 use Cwd;
  3         4  
  3         173  
15 3     3   1642 use File::Temp qw/ tempfile /;
  3         21795  
  3         150  
16 3     3   1066 use HTTP::Date;
  3         8652  
  3         166  
17 3     3   20 use HTTP::Status qw/ :constants /;
  3         6  
  3         846  
18 3     3   16 use JSON::MaybeXS 1.004000;
  3         59  
  3         1200  
19              
20             our $VERSION = 'v0.2.3';
21              
22              
23             sub prepare_app {
24 3     3 1 227 my ($self) = @_;
25              
26 3 100       11 if (my $data = $self->data) {
    50          
27              
28 2 50       71 if ($self->file) {
29 0         0 die "Cannot specify both data and file";
30             }
31              
32 2         15 my ($fh, $filename) = tempfile('traffic-advice-XXXXXXXX', SUFFIX => '.json', UNLINK => 0, TMPDIR => 1);
33 2         969 $self->file( $filename );
34              
35 2 100       29 if (ref($data)) {
36 1         6 my $encoder = JSON::MaybeXS->new( { utf8 => 1 } );
37 1 50       15 print {$fh} $encoder->encode($data)
  1         24  
38             or die "Unable to write data";
39             }
40             else {
41 1 50       2 print {$fh} $data
  1         18  
42             or die "Unable to write data";
43             }
44              
45 2         107 close $fh;
46              
47              
48             }
49             elsif (my $file = $self->file) {
50              
51 1 50       52 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 61043 my ( $self, $env ) = @_;
64              
65 5 50       20 unless ( $env->{REQUEST_URI} eq '/.well-known/traffic-advice' ) {
66 0         0 return $self->app->($env);
67             }
68              
69 5 100       26 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       151 open my $fh, "<:raw", $file
78             or return $self->error( HTTP_INTERNAL_SERVER_ERROR, "Internal Error" );
79              
80 4         44 my @stat = stat $file;
81              
82 4         83 Plack::Util::set_io_path($fh, Cwd::realpath($file));
83              
84             [
85 4         110 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 2 my ($self, $code, $message) = @_;
99 1         8 return [ $code, [ 'Content-Type' => 'text/plain', 'Content-Length' => length($message) ], [ $message ] ];
100             }
101              
102             1;
103              
104             __END__