File Coverage

blib/lib/Web/MREST/InitRouter.pm
Criterion Covered Total %
statement 66 71 92.9
branch 21 26 80.7
condition 3 4 75.0
subroutine 13 14 92.8
pod 0 1 0.0
total 103 116 88.7


line stmt bran cond sub pod time code
1             # *************************************************************************
2             # Copyright (c) 2014-2022, SUSE LLC
3             #
4             # All rights reserved.
5             #
6             # Redistribution and use in source and binary forms, with or without
7             # modification, are permitted provided that the following conditions are met:
8             #
9             # 1. Redistributions of source code must retain the above copyright notice,
10             # this list of conditions and the following disclaimer.
11             #
12             # 2. Redistributions in binary form must reproduce the above copyright
13             # notice, this list of conditions and the following disclaimer in the
14             # documentation and/or other materials provided with the distribution.
15             #
16             # 3. Neither the name of SUSE LLC nor the names of its contributors may be
17             # used to endorse or promote products derived from this software without
18             # specific prior written permission.
19             #
20             # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21             # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22             # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23             # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24             # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25             # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26             # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27             # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28             # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29             # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30             # POSSIBILITY OF SUCH DAMAGE.
31             # *************************************************************************
32              
33              
34             use 5.012;
35 22     22   488 use strict;
  22         64  
36 22     22   104 use warnings;
  22         37  
  22         379  
37 22     22   94  
  22         43  
  22         894  
38             use App::CELL qw( $log $meta $site );
39 22     22   132 use Data::Dumper;
  22         42  
  22         1732  
40 22     22   129 use Path::Router;
  22         52  
  22         829  
41 22     22   9252 use Try::Tiny;
  22         3383145  
  22         771  
42 22     22   162  
  22         53  
  22         2610  
43              
44             =head1 NAME
45              
46             Web::MREST::InitRouter - Routines for initializing our Path::Router instance
47              
48              
49              
50             =head1 SYNOPSIS
51              
52             L<Web::MREST> uses L<Path::Router> to match URIs to resources. All resources
53             are packed into a single object. The singleton is exported as C<$router> from
54             this module and can be initialized by calling C<init_router>, which is also
55             exported, with no arguments.
56              
57             use Web::MREST::InitRouter qw( $router );
58              
59             ...
60              
61             Web::MREST::InitRouter::init_router() unless defined $router and $router->can( 'match' );
62              
63              
64              
65              
66             =head1 PACKAGE VARIABLES
67              
68             =cut
69              
70             our $router;
71             our $resources = {};
72             our @non_expandable_properties = qw( parent validations documentation resource_name children );
73             our %no_expand_map = map { ( $_ => '' ) } @non_expandable_properties;
74              
75              
76             =head1 EXPORTS
77              
78             This module provides the following exports:
79              
80             =over
81              
82             =item C<$router> (Path::Router singleton)
83              
84             =item C<$resources> (expanded resource definitions)
85              
86             =back
87              
88             =cut
89              
90             use Exporter qw( import );
91 22     22   151 our @EXPORT_OK = qw( $router $resources );
  22         45  
  22         14921  
92              
93              
94             =head1 FUNCTIONS
95              
96             =cut
97              
98              
99             #
100             # read in multiple resource definitions from a hash
101             #
102             my $defs = shift;
103             #$log->debug("Entering " . __PACKAGE__. "::_load_resource_defs with argument " . Dumper( $defs ));
104 20     20 0 60  
105             # first pass -> expand resource defs and add them to $resources
106             foreach my $resource ( keys( %$defs ) ) {
107             # each resource definition is a hash.
108 20         137 if ( ref( $defs->{$resource} ) eq 'HASH' ) {
109             _process_resource_def( $resource, $defs->{$resource} );
110 240 50       208935 } else {
111 240         536 die "AAAAAAAHHHHHHH! Definition of resource $resource is not a hashref!";
112             }
113 0         0 _add_route( $resource );
114             }
115 240         398 }
116              
117              
118             # processes an individual resource definition hash and adds Path::Router route
119             # for it
120             my ( $resource, $resource_def ) = @_;
121             #$log->debug("Entering " . __PACKAGE__. "::_process_resource_def with:" );
122             $log->info("Initializing \$resource ->$resource<-");
123 240     240   424 #$log->debug("\$resource_def " . Dumper( $resource_def ) );
124              
125 240         1611 # expand all properties except those in %no_expand_map
126             foreach my $prop ( keys %$resource_def ) {
127             next if exists $no_expand_map{ $prop };
128             _expand_property( $resource, $resource_def, $prop );
129 240         41751 }
130 1160 100       2180  
131 700         1206 # handle non-expandable properties
132             #
133             # - validations
134             my $validations = $resource_def->{'validations'};
135             $resources->{$resource}->{'validations'} = $validations if $resource_def->{'validations'};
136             #
137 240         417 # - documentation
138 240 100       476 my $documentation = $resource_def->{'documentation'};
139             $resources->{$resource}->{'documentation'} = $documentation if $resource_def->{'documentation'};
140             #
141 240         345 # - parent
142 240 100       554 if ( $resource ne '/' ) {
143             my $parent = $resource_def->{'parent'} || '/';
144             push( @{ $resources->{$parent}->{'children'} }, $resource );
145 240 100       448 $resources->{$resource}->{'parent'} = $parent;
146 220   50     429 }
147 220         264  
  220         566  
148 220         402 return;
149             }
150              
151 240         398  
152             my $resource = shift;
153             my %validations;
154             if ( ref( $resources->{$resource}->{'validations'} ) eq 'HASH' ) {
155             %validations = %{ $resources->{$resource}->{'validations'} };
156 240     240   342 delete $resources->{$resource}->{'validations'};
157 240         279 }
158 240 100       493 my $ARGS = {
159 20         59 target => $resources->{$resource},
  20         102  
160 20         65 };
161             $ARGS->{'validations'} = \%validations if %validations;
162            
163 240         516 try {
164             $router->add_route( $resource, %$ARGS );
165 240 100       431 } catch {
166             $log->crit( $_ );
167             };
168 240     240   9111 }
169              
170 0     0   0  
171 240         1416 # takes an individual resource definition property, expands it and puts it in
172             # $resources package variable
173             my ( $resource, $resource_def, $prop ) = @_;
174             #$log->debug("Entering " . __PACKAGE__. "::_expand_property with " .
175             # "resource \"$resource\" and property \"$prop\"" );
176              
177             # set the resource_name property
178 700     700   1033 $resources->{$resource}->{'resource_name'} = $resource;
179              
180             my @supported_methods = ( ref( $resource_def->{'handler'} ) eq 'HASH' )
181             ? keys( %{ $resource_def->{'handler'} } )
182             : @{ $site->MREST_SUPPORTED_HTTP_METHODS || [ qw( GET POST PUT DELETE ) ] };
183 700         1224 foreach my $method ( @supported_methods ) {
184             #$log->debug( "Considering the \"$method\" method" );
185             if ( exists $resource_def->{$prop} ) {
186 480         989 my $prop_def = $resource_def->{$prop};
187 700 50       1357 my $refv = ref( $prop_def ) || 'SCALAR';
  220 100       1466  
188 700         9198 #$log->debug( "The definition of this property is a $refv" );
189             if ( $refv eq 'HASH' ) {
190 2140 50       2862 if ( $prop_def->{$method} ) {
191 2140         2479 $resources->{$resource}->{$method}->{$prop} = $prop_def->{$method};
192 2140   100     4073 } else {
193             $log->crit( "No $prop defined for $method method in $resource!" );
194 2140 100       3102 }
    50          
195 320 50       511 } elsif ( $refv eq 'SCALAR' ) {
196 320         823 $resources->{$resource}->{$method}->{$prop} = $prop_def;
197             } else {
198 0         0 die "AAAAAGAAAGAAAAAA! in " . __FILE__ . ", _populate_resources";
199             }
200             } else {
201 1820         3763 # resource with no def_part: suspicious
202             $log->notice( "While walking resource definition tree, " .
203 0           "encountered resource $resource with missing $prop in its definition" );
204             }
205             }
206             }
207 0            
208             1;