File Coverage

lib/Web/DataService/Request.pm
Criterion Covered Total %
statement 12 129 9.3
branch 0 64 0.0
condition 0 26 0.0
subroutine 4 29 13.7
pod 18 23 78.2
total 34 271 12.5


line stmt bran cond sub pod time code
1             #
2             # Web::DataService::Request
3             #
4             # A base class that implements a data service for the PaleoDB. This can be
5             # subclassed to produce any necessary data service. For examples, see
6             # TaxonQuery.pm and CollectionQuery.pm.
7             #
8             # Author: Michael McClennen
9              
10 2     2   16 use strict;
  2         18  
  2         81  
11              
12             package Web::DataService::Request;
13              
14 2     2   15 use Carp 'croak';
  2         5  
  2         88  
15              
16 2     2   1233 use Moo;
  2         5422  
  2         11  
17 2     2   3830 use namespace::clean;
  2         19448  
  2         12  
18              
19              
20             # The required attribute 'ds' is the data service with which this request is
21             # associated.
22              
23             has ds => ( is => 'ro', isa => \&is_dataservice_object, required => 1 );
24              
25             # The required attribute 'outer' is the request object generated by the
26             # foundation framework.
27              
28             has outer => ( is => 'ro', required => 1 );
29              
30             # The attribute 'path' selects the data service node which will be used to
31             # process the request. If not given explicitly, it will be retrieved from the
32             # 'outer' request object.
33              
34             has path => ( is => 'rw', trigger => \&_match_node );
35              
36             # The following argument can be specified separately, or you can let it be
37             # extracted from the value of 'path'. But note that if 'path' does not
38             # correspond to a defined node, then 'rest_path' will be modified
39             # accordingly.
40              
41             has rest_path => ( is => 'ro' );
42              
43             # The attribute 'http_method' selects the HTTP method which will be used to
44             # process the request. If not given explicitly, it will be retrieved from the
45             # 'outer' request object.
46              
47             has http_method => ( is => 'rw' );
48              
49             # The following attributes will be determined automatically by
50             # Web::DataService, unless explicitly defined at initialization time or
51             # explicitly overridden later.
52              
53             has is_invalid_request => ( is => 'rw' );
54              
55             has is_doc_request => ( is => 'rw' );
56              
57             has output_format => ( is => 'rw' );
58              
59             has output_vocab => ( is => 'rw' );
60              
61             has output_linebreak => ( is => 'rw' );
62              
63             has result_limit => ( is => 'rw' );
64              
65             has result_offset => ( is => 'rw' );
66              
67             has display_header => ( is => 'rw' ); #, lazy => 1, builder => sub { $_[0]->_init_value('header') } );
68              
69             has display_datainfo => ( is => 'rw' );
70              
71             has display_counts => ( is => 'rw' );
72              
73             has save_output => ( is => 'rw' );
74              
75             has save_filename => ( is => 'rw' );
76              
77             has do_not_stream => ( is => 'rw' );
78              
79             # The following attributes will be determined automatically by
80             # Web::DataService and should not be overridden.
81              
82             has node_path => ( is => 'ro', init_arg => '_node_path' );
83              
84             has is_node_path => ( is => 'ro', init_arg => undef );
85              
86              
87             # BUILD ( )
88             #
89             # Finish generating a new request object. This involves determining the "node
90             # path" from the "raw path" that was specified when this object was
91             # initialized. Depending upon the features enabled for this data service, the
92             # path may be processed in different ways.
93              
94             sub BUILD {
95            
96 0     0 0   my ($self) = @_;
97            
98 0           my $ds = $self->{ds};
99             }
100              
101              
102             sub is_dataservice_object {
103            
104 0 0 0 0 0   die "must be an object of class Web::DataService"
105             unless ref $_[0] && $_[0]->isa('Web::DataService');
106             }
107              
108              
109             sub _init_value {
110            
111 0     0     my ($self, $attr) = @_;
112            
113 0 0         if ( my $special = $self->special_value($attr) )
    0          
114             {
115 0           return $special;
116             }
117            
118             elsif ( my $default = $self->{ds}->node_attr("default_$attr") )
119             {
120 0           return $default;
121             }
122            
123             else
124             {
125 0           return;
126             }
127             }
128              
129              
130             # _match_node ( )
131             #
132             # This routine will be called whenever the 'path' attribute of this request is
133             # set. It determines the closest matching 'node_path' and sets some other
134             # attributes.
135              
136             sub _match_node {
137            
138 0     0     my ($self) = @_;
139            
140 0           local($Carp::CarpLevel) = 1; # We shouldn't have to do this, but
141             # Moo and Carp don't play well together.
142            
143 0           my $ds = $self->{ds};
144 0           my $raw_path = $self->{path};
145 0           my $suffix_is_missing;
146            
147             # We start with the raw path and trim it in various ways to find the
148             # closest matching data service node.
149            
150 0           my $node_path = $raw_path;
151            
152             # If the raw path exactly matches any node, we just use that. Otherwise,
153             # apply any applicable path transformations.
154            
155 0 0         if ( exists $ds->{node_attrs}{$raw_path} )
156             {
157 0           $self->{is_node_path} = 1;
158 0 0         $self->{is_doc_request} = 1 if $ds->has_feature('format_suffix');
159             }
160            
161             else
162             {
163             # If the feature 'format_suffix' is enabled and the specified path has
164             # a suffix, split it off.
165            
166 0 0         if ( $ds->has_feature('format_suffix') )
167             {
168 0 0         if ( $node_path =~ qr{ ^ (.+) [.] (.+) }xs )
169             {
170 0           $node_path = $1;
171 0           $self->output_format($2);
172             }
173            
174             else
175             {
176 0           $suffix_is_missing = 1;
177             }
178             }
179            
180             # If the feature 'doc_paths' is enabled and the specified path ends in
181             # '_doc', remove that string and set the 'is_doc_request' flag for this
182             # request. Under this feature, the path "abc/def_doc" indicates a
183             # request for doumentation about the path "abc/def".
184            
185 0 0         if ( $ds->has_feature('doc_paths') )
    0          
186             {
187 0 0 0       if ( $node_path eq '' )
    0 0        
    0          
    0          
188             {
189 0           $self->{is_doc_request} = 1;
190             }
191            
192             elsif ( ref $ds->{doc_path_regex} eq 'Regexp' && $node_path =~ $ds->{doc_path_regex} )
193             {
194 0           $node_path = $1;
195 0           $self->{is_doc_request} = 1;
196             }
197            
198             elsif ( $ds->{doc_index} && $node_path eq $ds->{doc_index} )
199             {
200 0           $node_path = '';
201 0           $self->{is_doc_request} = 1;
202             }
203            
204             elsif ( $suffix_is_missing )
205             {
206 0           $self->{is_doc_request} = 1;
207             }
208             }
209            
210             # Otherwise, if the special parameter 'document' is enabled and
211             # present then set the 'is_doc_request' flag for this request.
212            
213             elsif ( my $document_param = $ds->special_param('document') )
214             {
215 0           my $params = $Web::DataService::FOUNDATION->get_params($self->{outer});
216            
217 0 0         $self->{is_doc_request} = 1 if defined $params->{$document_param};
218             }
219            
220             # We then lop off components as necessary until we get to a node that has
221             # attributes or until we reach the empty string. We set the 'is_node_path'
222             # flag to 0 (unless it has already been set) to indicate that the request
223             # path does not fully match a defined node.
224            
225 0           while ( $node_path ne '' )
226             {
227             # If we find a node with attributes, stop here.
228            
229 0 0         last if exists $ds->{node_attrs}{$node_path};
230            
231             # If this is a documentation request and a template exists that
232             # would correspond to the current node path, then create the node
233             # and stop here.
234            
235 0 0 0       if ( $self->{is_doc_request} and my $doc_path = $ds->check_for_template($node_path) )
236             {
237 0           $ds->make_doc_node($node_path, $doc_path);
238 0           last;
239             }
240            
241             # Otherwise, lop off the last path component and try again.
242            
243 0   0       $self->{is_node_path} //= 0;
244            
245 0 0         if ( $node_path =~ qr{ ^ (.*) / (.*) }xs )
246             {
247 0           $node_path = $1;
248             }
249            
250             else
251             {
252 0           $node_path = '';
253             }
254             }
255             }
256            
257             # An empty path should always produce documentation. In fact, it should
258             # produce a "main documentation page" for this data service. The data
259             # service author should make sure that this is so.
260            
261 0 0         if ( $node_path eq '' )
    0          
262             {
263 0           $self->{is_doc_request} = 1;
264             }
265            
266             # If the selected node is disabled, set the 'is_invalid_request' attribute.
267            
268             elsif ( $ds->node_attr($node_path, 'disabled') )
269             {
270 0           $self->{is_invalid_request} = 1;
271             }
272            
273             # If 'is_node_path' has not yet been set, then we assume it should be 1.
274            
275 0   0       $self->{is_node_path} //= 1;
276            
277             # We save all of the characters removed from the raw path as $rest_path,
278             # so that (for example) we can send a requested file.
279            
280 0           $self->{rest_path} = substr($raw_path, length($node_path));
281            
282             # If we got an empty path, turn it into the root node path '/'.
283            
284 0 0         $self->{node_path} = $node_path eq '' ? '/' : $node_path;
285            
286             # If the node that we got has either the 'file_path' or 'file_dir'
287             # attribute, then mark this request as 'is_file_path'. If it has
288             # 'file_path', then it is invalid unless $rest_path is empty. If it has
289             # 'file_dir', then it is invalid unless $rest_path is NOT empty.
290            
291 0 0         if ( $ds->node_attr($self->{node_path}, 'file_dir') )
    0          
292             {
293 0           $self->{is_file_path} = 1;
294             $self->{is_invalid_request} = 1 unless defined $self->{rest_path} &&
295 0 0 0       $self->{rest_path} ne '';
296             }
297            
298             elsif ( $ds->node_attr($self->{node_path}, 'file_path' ) )
299             {
300 0           $self->{is_file_path} = 1;
301             $self->{is_invalid_request} = 1 if defined $self->{rest_path} &&
302 0 0 0       $self->{rest_path} ne '';
303             }
304             }
305              
306              
307             # execute ( )
308             #
309             # Execute this request, and return the result.
310              
311             sub execute {
312            
313 0     0 1   return $_[0]->{ds}->execute_request($_[0]->{outer});
314             }
315              
316              
317             # configure ( )
318             #
319             # Configure this request for execution.
320              
321             sub configure {
322              
323 0     0 0   return $_[0]->{ds}->configure_request($_[0]->{outer});
324             }
325              
326              
327             # Common methods needed for both execution and documentation
328              
329             # request_url
330             #
331             # Return the raw (unparsed) request URL
332              
333             sub request_url {
334            
335 0     0 1   return $Web::DataService::FOUNDATION->get_request_url($_[0]->{outer});
336             }
337              
338              
339             # base_url
340             #
341             # Return the base component of the URL for this request, of the form "http://some.host/".
342              
343             sub base_url {
344            
345 0     0 1   return $Web::DataService::FOUNDATION->get_base_url($_[0]->{outer});
346             }
347              
348              
349             # root_url ( )
350             #
351             # Return the base url plus the path prefix.
352              
353             sub root_url {
354            
355 0     0 1   return $Web::DataService::FOUNDATION->get_base_url($_[0]) . $_[0]->{ds}{path_prefix};
356             }
357              
358              
359             # path_prefix ( )
360             #
361             # Return the path prefix for this request.
362              
363             sub path_prefix {
364            
365 0     0 1   return $_[0]->{ds}{path_prefix};
366             }
367              
368              
369             # generate_url ( attrs )
370             #
371             # Generate a URL based on the specified attributes. This routine calls
372             # Web::DataService::generate_url to create a site-relative URL, then applies
373             # the base URL from the current request if asked to do so.
374              
375             sub generate_url {
376            
377 0     0 1   my ($self, $attrs) = @_;
378            
379 0           return $self->{ds}->generate_site_url($attrs);
380             }
381              
382              
383             # data_info ( )
384             #
385             # Return a hash of information about the request.
386              
387             sub data_info {
388            
389 0     0 1   my ($self) = @_;
390            
391             # We start with the information provided by the data service, and add some
392             # info specific to this request.
393            
394 0           my $ds = $self->{ds};
395 0           my $info = $ds->data_info;
396            
397 0           my $node_path = $self->node_path;
398 0           my $base_url = $self->base_url;
399            
400 0           my $doc_url = $self->generate_url({ node => $node_path });
401 0           $doc_url =~ s{^/}{};
402 0           my $data_url = $self->request_url;
403 0           $data_url =~ s{^/}{};
404            
405 0 0         $info->{documentation_url} = $base_url . $doc_url if $ds->{feature}{documentation};
406 0           $info->{data_url} = $base_url . $data_url;
407            
408 0           return $info;
409             }
410              
411              
412             sub data_info_keys {
413              
414 0     0 1   return $_[0]->{ds}->data_info_keys;
415             }
416              
417              
418             # contact_info ( )
419             #
420             # Return a hash of information indicating who to contact about this data service.
421              
422             sub contact_info {
423            
424 0     0 1   my ($self) = @_;
425              
426 0           my $ds = $self->{ds};
427 0           return $ds->contact_info;
428             }
429              
430              
431             # node_attr ( )
432             #
433             # Return the specified attribute of the node that matches this request.
434              
435             sub node_attr {
436            
437 0     0 1   my ($self, $attr) = @_;
438            
439 0           my $ds = $self->{ds};
440 0           my $path = $self->node_path;
441            
442 0           return $ds->node_attr($path, $attr);
443             }
444              
445             # special_value ( param )
446             #
447             # Return the value of the specified special param, if it is enabled, and if
448             # it was specified. Return undefined otherwise.
449              
450             sub special_value {
451              
452 0     0 1   my ($self, $param) = @_;
453            
454 0           my $ds = $self->{ds};
455            
456 0   0       my $param_name = $ds->special_param($param) || return;
457            
458             # If we have already passed the params through HTTP::Validate, return the
459             # cleaned value.
460            
461 0 0         if ( ref $self->{valid} )
462             {
463 0           my $value = $self->{valid}->value($param_name);
464 0 0         return @$value if ref $value eq 'ARRAY';
465 0 0         return $value if defined $value;
466 0           return; # otherwise
467             }
468            
469             # Otherwise, return the raw value if it exists and undefined otherwise.
470            
471 0           return $self->{raw_params}{$param_name};
472             }
473              
474              
475             # special_given ( param )
476             #
477             # Return true if the given special parameter was specified in the request,
478             # regardless of its value.
479              
480             sub special_given {
481              
482 0     0 1   my ($self, $param) = @_;
483            
484 0           my $ds = $self->{ds};
485 0   0       my $param_name = $ds->special_param($param) || return;
486            
487 0           return exists $self->{raw_params}{$param_name};
488             }
489              
490              
491             # default_limit ( )
492             #
493             # Return the default result limit, if any. Return undefined otherwise.
494              
495             sub default_limit {
496            
497 0     0 1   my ($self) = @_;
498            
499 0           my $path = $self->{node_path};
500 0           return $self->{ds}->node_attr($path, 'default_limit');
501             }
502              
503              
504             sub set_scratch {
505            
506 0     0 0   my ($self, $key, $value) = @_;
507            
508 0           return $self->{ds}->set_scratch($key, $value);
509             }
510              
511              
512             sub get_scratch {
513            
514 0     0 0   my ($self, $key) = @_;
515            
516 0           return $self->{ds}->get_scratch($key);
517             }
518              
519              
520             sub add_warning {
521              
522 0     0 1   my ($self, $warn_msg) = @_;
523            
524 0 0         $self->{warnings} = [] unless ref $self->{warnings} eq 'ARRAY';
525 0           push @{$self->{warnings}}, $warn_msg;
  0            
526             }
527              
528              
529             sub warnings {
530              
531 0     0 1   my ($self) = @_;
532            
533 0 0         return @{$self->{warnings}} if ref $self->{warnings} eq 'ARRAY';
  0            
534 0           return;
535             }
536              
537              
538             sub errors {
539              
540 0     0 1   my ($self) = @_;
541            
542 0 0         return @{$self->{errors}} if ref $self->{errors} eq 'ARRAY';
  0            
543 0           return;
544             }
545              
546              
547             sub cautions {
548              
549 0     0 1   my ($self) = @_;
550            
551 0 0         return {@$self->{cautions}} if ref $self->{cautions} eq 'ARRAY';
552 0           return;
553             }
554              
555              
556             sub error_result {
557            
558 0     0 1   my ($self, $error) = @_;
559            
560 0           return $self->{ds}->error_result($error, $self);
561             }
562              
563             =head1 NAME
564              
565             Web::DataService::Request - object class for data service requests
566              
567             =head1 SYNOPSIS
568              
569             As each incoming request is handled by the Web::DataService framework, a
570             request object is created to represent it. This object is blessed into a
571             subclass of Web::DataService::Request which provides the methods listed here
572             and also includes one or more L with methods that you have
573             written for evaluating the request and doing the appropriate fetching/storing
574             on the backend data system.
575              
576             The simplest way for the main application to handle a request is as follows:
577              
578             Web::DataService->handle_request(request);
579              
580             This call uses the C function provided by the foundation framework
581             (L) to get the "outer" object representing this request from the point
582             of view of the foundation framework, and then passes it to the
583             L
584             method of Web::DataService. In the process of handling the request, a new
585             "inner" request object is generated and blessed into an appropriate subclass
586             of Web::DataService::Request.
587              
588             If you wish more control over this process, you can substitute the following:
589              
590             my $inner = Web::DataService->new_request(request);
591            
592             # You can put code here to check the attributes of $inner and possibly
593             # alter them...
594            
595             $inner->execute;
596              
597             Whichever of these code fragments you use should go into a Dancer L
598             handler|Dancer/"USAGE">.
599              
600             =head2 Request handling process
601              
602             The request handling process carried out by
603             L works
604             as follows:
605              
606             =over
607              
608             =item 1.
609              
610             The request URL path and parameters are parsed according to the active set of
611             data service features and special parameters. Depending upon the set of data
612             service features that are active, the path may be processed before moving on
613             to the next step. The following is not an exhaustive list, but illustrates
614             the kinds of processing that are done:
615              
616             =over
617              
618             =item *
619              
620             If more than one data service is defined, the appropriate one is selected to
621             handle this request.
622              
623             =item *
624              
625             If the data service has the attribute "path_prefix", this prefix is removed
626             from the path.
627              
628             =item *
629              
630             If the feature 'format_suffix' is active and the path ends in a format suffix
631             such as C<.json>, then that suffix is removed and later used to set the
632             "format" attribute of the request.
633              
634             =item *
635              
636             If the feature 'doc_paths' is active and the path ends in '_doc' or in
637             '/index' then this suffix is removed and the "is_doc_request" attribute of the
638             request is set.
639              
640             =item *
641              
642             If the special parameter 'document' is active and this parameter was included
643             with the request, then the "is_doc_request" attribute of the request is set.
644              
645             =back
646              
647             =item 2.
648              
649             The modified request path is matched against the set of data service node
650             paths. Nodes with either of the attributes C or C
651             match as prefixes, all others must match exactly. If none of the nodes match,
652             then the request is rejected with a HTTP 404 error. Otherwise, a new request
653             object is created and configured using the attributes of the matching node.
654              
655             =back
656              
657             If you used L
658             instead of L
659             ] )">, then you get control at this point and can modify the request before
660             calling C<< $request->execute >> to finish the process.
661              
662             =over
663              
664             =item 3.
665              
666             If the matching node has the C attribute, then the contents of the
667             specified file are returned using the foundation framework (i.e. Dancer). If
668             the node has the C attribute instead, then the remainder of the
669             request path is applied as a relative path to that directory. The result of
670             the request will be either the contents of a matching file or a HTTP 404
671             error.
672              
673             =item 4.
674              
675             Otherwise, the new request will be blessed into an automatically generated
676             subclass of Web::DataService::Request. These subclasses are generated
677             according to the value of the "role" attribute of the matching node. Each
678             different role generates two subclasses, one for documentation requests and
679             one for operation requests. These classes are composed so that they contain
680             the necessary methods for documentation rendering and operation execution,
681             respectively, along with all of the definitions from the primary role (this
682             role module must be written by the application author).
683              
684             =item 5.
685              
686             If the "is_doc_request" attribute has been set, or if the matching node does
687             not have a value for the "method" attribute, then the documentation directory
688             is checked for a template corresponding to the matching node. If not found,
689             the appropriate default template is used. This template is rendered to
690             produce a documentation page, which is returned as the result of the request.
691              
692             =item 6.
693              
694             Otherwise, we can assume that the node has a "method" attribute. The request
695             parameters are then checked against the ruleset named by the "ruleset"
696             attribute, or the ruleset corresponding to the node path if this attribute is
697             not set.
698              
699             =item 7.
700              
701             The output is then configured according to the output blocks(s) indicated by the
702             "output" attribute plus those indicated by "optional_output" in conjunction
703             with the special parameter "show".
704              
705             =item 8.
706              
707             The method specified by the node attribute "method" is then called. This
708             method (which must be written by the application author) is responsible for
709             fetching and/or storing data using the backend system and specifying what the
710             result of the operation should be.
711              
712             =item 9.
713              
714             If the result of the operation is one or more data records, these records are
715             processed according to the specification contained in the selected output
716             block(s), and are then serialized by the module corresponding to the selected
717             output format. If "count" or "datainfo" were requested, or if any warnings or
718             errors were generated during the execution of the request, this material is
719             included in an appropriate way by the serialization module. The resulting
720             response body is returned using the foundation framework.
721              
722             =item 10.
723              
724             If the result of the operation is instead a piece of non-record data (i.e. an
725             image or other binary data), it is returned as the response body using the
726             foundation framework.
727              
728             =back
729              
730             =head1 METHODS
731              
732             =head2 Constructor
733              
734             =head3 new ( attributes... )
735              
736             You will not need to call this method directly; instead, you should call the
737             L
738             method of Web::DataService, which calls it internally after carrying out other
739             processing.
740              
741             =head2 Execution
742              
743             =head3 execute ( )
744              
745             Executes this request, and returns the serialized response data. If your main
746             application uses C, then you will not need to call this
747             method because C calls it internally.
748              
749             =head3 error_result ( error )
750              
751             Aborts processing of the request and causes a HTTP error response to be
752             returned to the client. You will probably not need to call this method, since
753             the preferred way of generating an error condition is to call
754             L. The parameter can be any of the following:
755              
756             =over
757              
758             =item *
759              
760             A HTTP error code, such as "404" or "500".
761              
762             =item *
763              
764             An error message, which will be written to the log. For security reasons, the
765             client will just get back a HTTP 500 response that tells them a server error
766             occurred and they should contact the server administrator.
767              
768             =item *
769              
770             A validation result object from L. The client will get back a
771             HTTP 400 response containing the error and warning messages contained within
772             it.
773              
774             =back
775              
776             =head2 Attribute accessors
777              
778             =head3 ds
779              
780             Returns a reference to the data service instance with which this request is
781             associated.
782              
783             =head3 outer
784              
785             Returns a reference to the "outer" request object defined by the foundation
786             framework.
787              
788             =head3 path
789              
790             Returns the raw path associated with the request.
791              
792             =head3 node_path
793              
794             Returns the path of the node that matches this request.
795              
796             =head3 rest_path
797              
798             If the node path matches the processed request path as a prefix, this accessor returns
799             the remainder of the path. Otherwise, it returns C.
800              
801             =head3 is_invalid_request
802              
803             Returns true if this request could not be matched to a node, or is otherwise
804             invalid. Returns false otherwise.
805              
806             =head3 is_doc_request
807              
808             Returns true if this request has been determined to be a request for
809             documentation, according to the features and special parameters enabled for
810             this data service. Returns false otherwise.
811              
812             =head3 is_node_path
813              
814             Returns true if the request path I matches the path of a data service
815             node, false otherwise.
816              
817             =head3 http_method
818              
819             Returns (or sets) the HTTP method associated with the request.
820              
821             =head3 request_url
822              
823             Returns the complete request URL.
824              
825             =head3 base_url
826              
827             Returns the base component of the request URL, of the form
828             "http://some.host/" or something similar.
829              
830             =head3 root_url
831              
832             Returns the base URL plus the path prefix (if any) for this data service.
833              
834             =head3 path_prefix
835              
836             Returns the path prefix (if any) for this data service.
837              
838             =head3 data_info
839              
840             Returns a hash containing information about the request and the data to be
841             returned. The hash keys will include some or all of the following, depending
842             upon the configuration of the data service.
843              
844             =over
845              
846             =item title, data_provider, data_source, data_license, license_url
847              
848             The values of these keys will be the corresponding attributes of the data
849             service. They may be undefined if no value was specified for them either when
850             the data service was instantiated or in the configuration file maintained by
851             the foundation framework.
852              
853             =item access_time
854              
855             The current time.
856              
857             =item data_url
858              
859             The complete request URL.
860              
861             =item documentation_url
862              
863             A URL that will return a documentation page describing the selected data
864             service node.
865              
866             =back
867              
868             =head3 data_info_keys
869              
870             Returns a list of the keys documented for C, in a canonical order
871             for use by the serialization modules.
872              
873             =head3 contact_info
874              
875             Returns a hash whose keys are C and C. The values will be the
876             values of the data service attributes C and C,
877             respectively.
878              
879             =head3 generate_url ( attrs )
880              
881             This method returns a URL generated from the specified attributes, which must be given
882             either as a hashref or as a string:
883              
884             # either of the following:
885            
886             $url = $request->generate_url( { op => 'abc/def', format => 'json', params => 'foo=1' } );
887             $url = $request->generate_url( "op:abc/def.json?foo=1" );
888              
889             The attributes are as follows:
890              
891             =over
892              
893             =item node
894              
895             Generate a URL which will request documentation using the node path given by
896             the value of this attribute. In the string form, this is represented by a
897             prefix of "node:".
898              
899             =item op
900              
901             Generate a URL which will request a data service operation using the node path
902             given by the value of this attribute. In the string form, this is represented
903             by a prefix of "op:".
904              
905             =item path
906              
907             Generate a URL which will request the exact path given. This is used to
908             generate URLs for requesting files, such as CSS files. In the string form,
909             this is represented by a prefix of "path:".
910              
911             =item format
912              
913             The generated URL will request output in the specified format. Depending upon
914             the features enabled for this data service, that may mean either adding the
915             specified value as a suffix to the URL path, or adding a special parameter.
916             In the string form, this is represented by adding '.' followed by the format
917             to the path (this syntax is fixed no matter which data service features are
918             enabled).
919              
920             =item params
921              
922             Configure the URL to include the specified parameters. The value of this
923             attribute must be either an arrayref with an even number of elements or a
924             single URL parameter string such as C<"foo=1&bar=2">. In the string form,
925             this is represented by a '?' followed by the parameter string.
926              
927             =item type
928              
929             The value of this attribute must be either C, C, or C. If
930             "abs" is given, then the generated URL will begin with
931             "http[s]://hostname[:port]/. If "site", then the generated URL will begin
932             with "/" followed by the path prefix for this data service (if any). If
933             "relative", no prefix will be added to the generated URL. In this case, you
934             must make sure to specify a path that will work properly relative to the URL
935             of the page on which you intend to display it.
936              
937             If this attribute is not specified, it defaults to "site". In the string
938             form, this is represented by modifying the prefix, i.e. "oprel:" or "opabs:"
939             instead of just "op:".
940              
941             =back
942              
943             =head3 node_attr ( name )
944              
945             Returns the value of the specified attribute of the node matching this
946             request, or I if the attribute is not defined for that node.
947              
948             =head3 special_value ( param )
949              
950             Returns the value of the specified special parameter, if it is enabled for
951             this data service and if it was included with this request. Returns I
952             otherwise.
953              
954             =head3 special_given ( param )
955              
956             Returns true if the specified special parameter was included in this request
957             and is enabled for this data service, regardless of its value. Returns false
958             otherwise.
959              
960             =head3 default_limit
961              
962             Returns the default result limit, if any. This is used in generating
963             documentation.
964              
965             =head2 Documentation methods
966              
967             The following methods are only available with documentation requests. They can
968             be called from documentation templates as follows:
969              
970             <% result = request.method_name(args) %>
971              
972             or, to include the result directly in the rendered output:
973              
974             <% request.method_name(args) %>
975              
976             In either case, "request" is a variable automatically provided to the
977             templating engine. The string "result" should be replaced by whatever
978             variable you wish to assign the result to, and "method_name" and "args" by the
979             desired method and arguments.
980              
981             These methods are all packaged up in blocks defined by doc_defs.tt, so you
982             will not need to call them directly unless you want to make substantive
983             changes to the look of the documentation pages.
984              
985             =head3 document_node
986              
987             Returns the documentation string for the node matching this request, or the
988             empty string if none was defined.
989              
990             =head3 list_navtrail
991              
992             Returns a list of navigation trail components for the current request, in Pod
993             format. These are generated componentwise from the node path.
994              
995             =head3 document_usage
996              
997             Returns a string in Pod format listing the URLs generated from the node
998             attribute "usage", if any were given for this node.
999              
1000             =head3 list_subnodes
1001              
1002             Returns a list of the node paths corresponding to all subnodes of the current
1003             one for which the C attribute was set.
1004              
1005             =head3 document_subnodes
1006              
1007             Returns a string in Pod format documenting the subnodes of the current one for
1008             which the C attribute was set.
1009              
1010             =head3 document_params
1011              
1012             Returns a string in Pod format documenting the parameters available for this
1013             request. This is automatically generated from the corresponding ruleset, if
1014             one was defined.
1015              
1016             =head3 list_http_methods
1017              
1018             Returns a list of HTTP methods that are allowed for this request path.
1019              
1020             =head3 document_http_methods
1021              
1022             Returns a string in Pod format documenting the HTTP methods that are allowed
1023             for this request path.
1024              
1025             =head3 document_response
1026              
1027             Returns a string in Pod format documenting the all of the fields that might be
1028             included in the result.
1029              
1030             =head3 output_label
1031              
1032             Returns the value of the node attribute "output_label", or the default value
1033             "basic" if none was defined.
1034              
1035             =head3 optional_output
1036              
1037             Returns the value of the node attribute "optional_output", if this attribute
1038             was defined.
1039              
1040             =head3 document_formats ( options )
1041              
1042             Returns a string in Pod format documenting the formats allowed for this
1043             node. If a parameter is specified, it must be a hashref. If this includes
1044             the key 'all' with a true value, then all formats defined for this
1045             data service are included. If it includes the key 'extended' with a true value, then
1046             a description of each format is included.
1047              
1048             =head3 default_format
1049              
1050             Return the name of the default format (if any was specified) for this node.
1051              
1052             =head3 document_vocabs ( options )
1053              
1054             Return a string in Pod format documenting the vocabularies allowed for this
1055             node. If a parameter is specified, it must be a hashref. If this includes
1056             the key 'all' with a true value, then all vocabularies defined for this
1057             data service are included. If it includes the key 'extended' with a true value, then
1058             a description of each vocabulary is included.
1059              
1060             =head3 output_format
1061              
1062             You can use this method to check whether the response is to be rendered into
1063             HTML or returned as Pod text. The values returned are C and
1064             respectively.
1065              
1066             =head2 Operation methods
1067              
1068             The following methods are only available with operation requests. They can be
1069             called from any of the operation methods included in the application role
1070             module(s).
1071              
1072             =head3 get_connection
1073              
1074             This method can only be used if you explicitly specified a backend plugin when
1075             instantiating the data service, or if the module L
1076             was required in your main application before Web::DataService.
1077              
1078             Assuming that the proper connection information is present in the application
1079             configuration file, this method will return a connection to your backend data
1080             store.
1081              
1082             =head3 exception ( code, message )
1083              
1084             Returns an exception object encoding the specified HTTP result code and a message to go with
1085             it. This exception object can be used as an argument to 'die'. Its type is
1086             C.
1087              
1088             =head3 debug
1089              
1090             Returns true if the data service process is running under debug mode. This can be used to output
1091             extra debugging information as appropriate.
1092              
1093             =head3 debug_line ( text )
1094              
1095             Print the specified text to standard error, followed by a newline, if debug mode is enabled for
1096             this data service process. This can be used, for example, to output the text of SQL statements
1097             executed on the underlying database, and similar information, for debugging purposes. For example:
1098              
1099             $request->debug_line($sql) if $request->debug;
1100              
1101             =head3 param_keys ( )
1102              
1103             Returns a list of the parameter keys corresponding to the request parameters.
1104             These will generally be the same as the parameter names, but may
1105             be different if you include the keys C and/or C in the parameter
1106             validation rulesets (see L).
1107              
1108             =head3 clean_param ( param )
1109              
1110             Returns the cleaned value of the specified parameter, or undefined if the
1111             parameter was not included in the request. If more than one parameter value was
1112             given, the result will be an array ref.
1113              
1114             =head3 clean_param_list ( param )
1115              
1116             Returns a list of all the cleaned values of the specified parameter (one or
1117             more), or empty if the parameter was not included in the request.
1118              
1119             =head3 clean_param_hash ( param )
1120              
1121             Returns a hashref whose keys are all of the cleaned values of the specified
1122             parameter, or an empty hashref if the parameter was not included in the
1123             request.
1124              
1125             =head3 param_given ( param )
1126              
1127             Returns true if the specified parameter was included in there request, whether
1128             or not it had a valid value. Returns false otherwise.
1129              
1130             =head3 params_for_display
1131              
1132             Returns a list of (parameter, value) pairs for use in responding to the
1133             'datainfo' special parameter. This result list leaves out any special
1134             parameters that do not affect the content of the result. Multiple values are
1135             concatenated together using commas.
1136              
1137             =head3 validate_params ( ruleset_name, param... )
1138              
1139             Validates the specified parameters (which may be hash or list refs of parameters and values) to
1140             the specified ruleset. Returns the result, which will be an object of type HTTP::Validate::Result
1141             that can then be queried for success or failure, error messages, etc. The primary purpose for this
1142             method is to allow validation of data records before they are added to the underlying database.
1143              
1144             =head3 raw_body
1145              
1146             Returns the request body as an un-decoded string. If the request does not contain a body, returns
1147             the empty string. The primary purpose for this method is to accept data for addition to the
1148             underlying database.
1149              
1150             =head3 decode_body
1151              
1152             Attempts to decode the request body, if it is in a known format. Currently, the only two formats
1153             understood are JSON and text. A JSON body will be decoded into a Perl data structure, while a text
1154             body will be split into a list of lines. If no body exists, the undefined value is returned. If an
1155             error occurs during JSON decoding, it will be returned as a second item. Consequently, the return
1156             value of this method should be assigned to a two-element list.
1157              
1158             =head3 has_block ( block )
1159              
1160             Returns true if the specified output block was selected for this request. The
1161             parameter can be either the name of the block or the parameter value by which
1162             it would be selected.
1163              
1164             =head3 select_list ( subst )
1165              
1166             Returns a list of strings derived from the 'select' configuration records
1167             found in the output blocks selected for this request. You can use these
1168             records to specify which fields need to be retrieved from the backend data
1169             store. Any given string will only appear once in the list, even if it occurs
1170             in multiple 'select' records.
1171              
1172             The optional argument should be a hashref, indicating substitutions to be
1173             made. For example, given the following code,
1174              
1175             $ds->define_block( 'block1' =>
1176             { select => '$a.name', '$a.value', 'c.size' },
1177             ... );
1178            
1179             # ...and in a different subroutine...
1180            
1181             my @fields = $request->select_list( { a => 'table1', b => 'table2' } )
1182              
1183             The result will include C, C, and C.
1184              
1185             If you are using an SQL-based backend, and if you set up the 'select' records
1186             properly, you can use this method (or see C below) to build a
1187             SELECT statement that will fetch exactly the information needed for the
1188             selected set of output blocks. This is important if your application allows
1189             optional output blocks that can be selected arbitrarily by the client. If you
1190             are using a non-SQL backend, you are free to use this in any way that makes
1191             sense given the backend interface.
1192              
1193             =head3 select_hash ( subst )
1194              
1195             Returns the same set of strings as C, but as the keys in a
1196             hash. The values will all be 1.
1197              
1198             =head3 select_string ( subst )
1199              
1200             Returns the same set of strings as C, but joined into a single
1201             string with each item separated by a comma and a space.
1202              
1203             =head3 substitute_select ( variable => value, variable => value ... )
1204              
1205             Make substitutions in the select list. For example, if passed the arguments 'v => xt', then
1206             anywhere the string '$v' appears in the select list, that string will be replaced by 'xt'. This
1207             method should be called before 'select_list' or 'select_string'. The intended use is to select
1208             between one or more alternate database tables.
1209              
1210             =head3 tables_hash
1211              
1212             Returns a hashref whose keys are derived from the 'select' configuration
1213             records found in the output blocks selected for this request. The keys from
1214             this hash will be the values specified by any 'tables' attributes in those
1215             configuration records. The values will all be 1.
1216              
1217             If you are using an SQL-based backend, and if you set up the 'select' records
1218             properly, you can use this method to keep track of which database tables will
1219             be needed in order to build a query that can satisfy all of the data blocks
1220             included in this request. You can use the set of keys to constuct an
1221             appropriate list of table joins. If you are using a non-SQL backend, you can
1222             use this in any way that makes sense given the backend interface.
1223              
1224             If you call this method multiple times, you will get a reference to the same
1225             hash each time. This means that you can safely add and remove keys during
1226             your own processing.
1227              
1228             =head3 add_table ( alias, [full_name] )
1229              
1230             Add an extra key to the tables hash. The optional second parameter can be the full name of the
1231             table to be included, but this is ignored. Note that adding a table to the table hash will I
1232             automatically include that table in any SQL statements. You need to check the table hash and add
1233             it yourself if the appropriate key is found.
1234              
1235             =head3 filter_hash
1236              
1237             Returns a hashref whose keys are derived from the 'filter' configuration
1238             records found in the output blocks selected for this request. The values will
1239             all be 1.
1240              
1241             If you are using an SQL-based backend, and if you set up the 'filter' records
1242             properly, you can use this method to get a list of (unique) filter expressions
1243             to use in building a query that can satisfy all of the data blocks included in
1244             this request. (Note: you will almost always need to add other filter
1245             expressions derived from parameter values as well). If you are using a
1246             non-SQL backend, you can use this in any way that makes sense given the
1247             backend interface.
1248              
1249             If you call this method multiple times, you will get a reference to the same
1250             hash each time. This means that you can safely add and remove keys during
1251             your own processing.
1252              
1253             =head3 output_field_list
1254              
1255             This method returns the output field list for the current request. This is the actual list, not a
1256             copy, so it can be manipulated. This is a real hack, which will probably be removed from a future
1257             version of this module. But for the time being, you can use it (for example) to go through the
1258             list and prune fields that will not be used.
1259              
1260             =head3 delete_output_field ( field )
1261              
1262             Remove the specified output field from the list. The first field whose name (not label) matches
1263             the argument is removed, regardless of what output block it occurs in. If no fields match, nothing
1264             will be removed.
1265              
1266             =head3 result_limit
1267              
1268             Returns the result limit specified for this request, or undefined if none was
1269             given or if C was specified. Even though Web::DataService will always
1270             truncate the result set if a limit was given, you may want to include this
1271             limit value in any queries you make to the backend so as to prevent your
1272             server from doing unnecessary work.
1273              
1274             =head3 result_offset ( will_handle )
1275              
1276             Returns true if a result offset was specified for this request, or zero if
1277             none was specified. If the argument value is true, then Web::DataService
1278             assumes that you will handle the process of offsetting the data result,
1279             e.g. by using modifying your backend query appropriately (see
1280             C below).
1281              
1282             If the argument is false, or if you never call either this method or
1283             C, then (if an offset was specified for this request)
1284             Web::DataService will automatically discard the corresponding number of
1285             records from the beginning of the result set before serializing the results.
1286              
1287             =head3 sql_limit_clause ( will_handle )
1288              
1289             Returns a string whose value is an LIMIT clause that can be added to an SQL
1290             query to generate a result set in accordance with result limit and offset (if
1291             any) specified for this request. If the argument is true, then
1292             Web::DataService assumes that you will actually do this.
1293              
1294             If the argument is false, or if you never call either this method or
1295             C, then (if an offset was specified for this request)
1296             Web::DataService will automatically discard the corresponding number of
1297             records from the beginning of the result set before serializing the results.
1298              
1299             If a result limit was specified for this request, and if the result set you
1300             generate exceeds this size, Web::DataService will always truncate it to match
1301             the specified limit.
1302              
1303             =head3 sql_count_clause ( )
1304              
1305             Returns a string that can be added to an SQL statement to generate a result
1306             count in accordance with the request parameters. If the special parameter
1307             "count" was specified for this request, the result will be
1308             C. Otherwise, it will be the empty string.
1309              
1310             If you are using a non-SQL backend, you can still use this as a boolean
1311             variable to determine if the result should include a count of the number of
1312             records found.
1313              
1314             =head3 sql_count_rows ( )
1315              
1316             Execute the SQL statement "SELECT FOUND ROWS" and store the result for use in generating the
1317             response header. But only do this if the request parameters specify that result counts should
1318             be returned.
1319              
1320             =head3 set_result_count ( count )
1321              
1322             Use this method to tell Web::DataService the result count if you are using
1323             C. In this case, you will generally need to execute a separate query
1324             such as "SELECT FOUND_ROWS()" after your main query.
1325              
1326             =head3 output_format
1327              
1328             Returns the name of the response format selected for this request.
1329              
1330             =head3 output_vocab
1331              
1332             Returns the name of the response vocabulary selected for this request. If no
1333             vocabularies have been defined for this data service, it will return "null",
1334             the name of the default vocabulary.
1335              
1336             =head3 output_linebreak
1337              
1338             Returns the string to be inserted between output lines in text-based response
1339             formats. This will be either a carriage return, a linefeed, or both.
1340              
1341             =head3 result_limit
1342              
1343             Returns the limit (if any) specified for the size of the result set.
1344              
1345             =head3 result_offset
1346              
1347             Returns the offset (if any) specified for the start of the result set.
1348              
1349             =head3 display_header
1350              
1351             Returns true if header material is to be displayed in text-based response
1352             formats, false otherwise.
1353              
1354             =head3 display_datainfo
1355              
1356             Returns true if a description of the dataset is to be included in
1357             the response, false otherwise.
1358              
1359             =head3 display_counts
1360              
1361             Returns true if result counts and elapsed time are to be included in the
1362             response, false otherwise.
1363              
1364             =head3 save_output
1365              
1366             Returns true if the special parameter 'save' was included in the request.
1367              
1368             =head3 get_config
1369              
1370             Returns a hashref providing access to the attributes defined in the
1371             application configuration file. Allows you to include application-specific
1372             directives in the file and retrieve them as needed from your operation
1373             methods.
1374              
1375             =head3 set_content_type
1376              
1377             Specify the value for the "Content-type" HTTP response header. You will
1378             probably not need to call this, since it is set automatically based on the
1379             selected response format.
1380              
1381             =h3ad3 exception ( code, message )
1382              
1383             Returns an exception object which can be used as an argument to C. This
1384             will abort processing of the current request and generate an HTTP error
1385             result. The first argument must be a valid HTTP error code.
1386              
1387             =head2 Result methods
1388              
1389             These methods are also available with operation requests. I
1390             call at least one of them from each of your operation methods.> These methods
1391             are how you tell Web::DataService the result of each operation.
1392              
1393             You can make more than one of these calls from a single operation, but note
1394             that each call (except for C in some cases) wipes out any result
1395             specified by previous calls.
1396              
1397             =head3 single_result ( record )
1398              
1399             The argument must be a hashref representing a single data record. The result
1400             of this operation will be that single record.
1401              
1402             =head3 list_result ( record... )
1403              
1404             You can call this method either with a single arrayref argument whose members
1405             are hashrefs, or with a list of hashrefs. Either way, the result of this
1406             operation will be the specified list of records.
1407              
1408             =head3 add_result ( record... )
1409              
1410             Adds the specified record(s) to a result set previously specified by
1411             C. All arguments must be hashrefs.
1412              
1413             =head3 sth_result ( sth )
1414              
1415             The argument must be a valid DBI statement handle that has already been
1416             executed. Once your operation method returns, Web::DataService will then
1417             fetch the result records from this sth one by one, process them according to
1418             the selected set of output blocks for this request, and serialize the result.
1419              
1420             If you use this result method, you will need to call either C
1421             or C to determine if a result count is needed. If so,
1422             execute a "SELECT FOUND_ROWS()" query (or the equivalent) and use
1423             C to tell Web::DataService how many records were found.
1424              
1425             =head3 data_result ( data )
1426              
1427             The argument must be either a scalar or a reference to a scalar. In either
1428             case, this data will be returned as the result of the operation without any
1429             further processing. You can use this, for example, to return images or other
1430             binary data. You can use C to set the result content type,
1431             or you can rely on the suffix of the URL path if appropriate.
1432              
1433             =head3 clear_result
1434              
1435             This call clears any results that have been specified for this operation by
1436             any of the other methods in this section.
1437              
1438             =head3 add_warning ( message )
1439              
1440             Add the specified warning message to this request. The warnings will be
1441             automatically included in the result, in a manner appropriate for the selected
1442             response format.
1443              
1444             =head3 warnings ( )
1445              
1446             Return a list of the warning messages (if any) that have been added to this
1447             request.
1448              
1449             =head3 add_caution ( message )
1450              
1451             Add the specified caution message to this request. The caution messages will be automatically
1452             included in the result, in a manner appropriate for the selected response format.
1453              
1454             =head3 cautions ( )
1455              
1456             Return a list of the caution messages (if any) that have been added to this request.
1457              
1458             =head3 add_error ( message )
1459              
1460             Add the specified error message to this request. The error messages will be automatically
1461             included in the result, in a manner appropriate for the selected response format.
1462              
1463             =head3 errors ( )
1464              
1465             Return a list of the error messages (if any) that have been added to this request.
1466              
1467             =head1 AUTHOR
1468              
1469             mmcclenn "at" cpan.org
1470              
1471             =head1 BUGS
1472              
1473             Please report any bugs or feature requests to C, or through
1474             the web interface at L. I will be notified, and then you'll
1475             automatically be notified of progress on your bug as I make changes.
1476              
1477             =head1 COPYRIGHT & LICENSE
1478              
1479             Copyright 2014 Michael McClennen, all rights reserved.
1480              
1481             This program is free software; you can redistribute it and/or modify it
1482             under the same terms as Perl itself.
1483              
1484             =cut
1485              
1486             1;