File Coverage

blib/lib/Plack/App/DAIA.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1 8     8   121867 use strict;
  8         17  
  8         276  
2 8     8   44 use warnings;
  8         18  
  8         425  
3             package Plack::App::DAIA;
4             #ABSTRACT: DAIA Server as Plack application
5             our $VERSION = '0.55'; #VERSION
6 8     8   110 use v5.10.1;
  8         27  
  8         343  
7              
8 8     8   773 use parent 'Plack::Component';
  8         258  
  8         74  
9 8     8   130945 use LWP::Simple qw(get);
  8         516476  
  8         81  
10 8     8   1882 use Encode;
  8         18  
  8         646  
11 8     8   8067 use JSON;
  8         101503  
  8         49  
12 8     8   16063 use DAIA;
  0            
  0            
13             use Scalar::Util qw(blessed);
14             use Try::Tiny;
15             use Plack::Util::Accessor qw(xslt root warnings errors code idformat initialized safe);
16             use Plack::Middleware::Static;
17             use File::ShareDir qw(dist_dir);
18              
19             use Carp;
20             use Plack::Request;
21              
22             our %FORMATS = DAIA->formats;
23              
24             sub prepare_app {
25             my $self = shift;
26             return if $self->initialized;
27              
28             $self->init;
29             $self->errors(0) unless defined $self->errors;
30             $self->warnings(1) if $self->errors or not defined $self->warnings;
31             $self->idformat( qr{^.*$} ) unless defined $self->idformat;
32             $self->safe(1) unless defined $self->safe;
33             $self->xslt('daia.xsl') if ($self->xslt // 1) eq 1;
34              
35             $self->{client} = Plack::Middleware::Static->new(
36             path => qr{daia\.(xsl|css|xsd)$|xmlverbatim\.xsl$|icons/[a-z0-9_-]+\.png$},
37             root => ($self->root || dist_dir('Plack-App-DAIA'))
38             ) if $self->xslt;
39              
40             $self->initialized(1);
41             }
42              
43             sub init {
44             # initialization hook
45             }
46              
47             sub call_client {
48             my ($self, $req) = @_;
49              
50             if ( $self->{client} and $req->path ne '/' and !keys %{$req->parameters} ) {
51             return $self->{client}->_handle_static( $req->env );
52             } else {
53             return;
54             }
55             }
56              
57             sub call {
58             my ($self, $env) = @_;
59             my $req = Plack::Request->new($env);
60              
61             my $id = $req->param('id') // '';
62             my $format = lc($req->param('format') // '');
63              
64             # serve parts of the XSLT client
65             my $res = $self->call_client($req);
66             return $res if $res;
67              
68             # validate identifier
69             my ($invalid_id, $error, %parts) = ('',undef);
70             if ( $id ne '' and ref $self->idformat ) {
71             if ( ref $self->idformat eq 'Regexp' ) {
72             if ( $id =~ $self->idformat ) {
73             %parts = %+; # named capturing groups
74             } else {
75             $invalid_id = $id;
76             $id = "";
77             }
78             }
79             }
80              
81             if ( $self->warnings ) {
82             if ( $invalid_id ne '' ) {
83             $error = 'unknown identifier format';
84             } elsif ( $id eq '' ) {
85             $error = 'please provide a document identifier';
86             }
87             }
88              
89             # retrieve and construct response
90             my ($status, $daia) = (200, undef);
91             if ( $error and $self->errors ) {
92             $daia = DAIA::Response->new;
93             } else {
94             if ($self->safe) {
95             try {
96             $daia = $self->retrieve( $id, %parts );
97             } catch {
98             chomp($error = "request method died: $_");
99             $status = 500;
100             }
101             } else {
102             $daia = $self->retrieve( $id, %parts );
103             }
104             if (!$daia or !blessed $daia or !$daia->isa('DAIA::Response')) {
105             $daia = DAIA::Response->new;
106             $error = 'request method did not return a DAIA response'
107             unless $error;
108             $status = 500;
109             }
110             }
111              
112             if ( $error and $self->warnings ) {
113             $daia->addMessage( 'en' => $error, errno => 400 );
114             }
115              
116             $self->as_psgi( $status, $daia, $format, $req->param('callback') );
117             }
118              
119             sub retrieve {
120             my $self = shift;
121             return $self->code ? $self->code->(@_) : undef;
122             }
123              
124             sub as_psgi {
125             my ($self, $status, $daia, $format, $callback) = @_;
126             my ($content, $type);
127              
128             $type = $FORMATS{$format} unless $format eq 'xml';
129             $content = $daia->serialize($format) if $type;
130              
131             if (!$content) {
132             $type = "application/xml; charset=utf-8";
133             if ( $self->warnings ) {
134             if ( not $format ) {
135             $daia->addMessage( 'en' => 'please provide an explicit parameter format=xml', 300 );
136             } elsif ( $format ne 'xml' ) {
137             $daia->addMessage( 'en' => 'unknown or unsupported format', 300 );
138             }
139             }
140             $content = $daia->xml( header => 1, xmlns => 1, ( $self->xslt ? (xslt => $self->xslt) : () ) );
141             } elsif ( $type =~ qr{^application/javascript} and ($callback || '') =~ /^[\w\.\[\]]+$/ ) {
142             $content = "$callback($content)";
143             }
144              
145             return [ $status, [ "Content-Type" => $type ], [ encode('utf8',$content) ] ];
146             }
147              
148             1;
149              
150             __END__