File Coverage

lib/Web/DataService/Request.pm
Criterion Covered Total %
statement 12 148 8.1
branch 0 74 0.0
condition 0 26 0.0
subroutine 4 33 12.1
pod 17 27 62.9
total 33 308 10.7


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         19  
  2         89  
11              
12             package Web::DataService::Request;
13              
14 2     2   13 use Carp 'croak';
  2         3  
  2         99  
15              
16 2     2   1168 use Moo;
  2         5531  
  2         11  
17 2     2   3883 use namespace::clean;
  2         19564  
  2         13  
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}, 'query');
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 datainfo {
388            
389 0     0 0   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 {
413            
414 0     0 1   goto &datainfo;
415             }
416              
417              
418             sub datainfo_keys {
419              
420 0     0 0   return $_[0]->{ds}->data_info_keys;
421             }
422              
423              
424             sub extra_datainfo_keys {
425            
426 0     0 0   my ($request) = @_;
427            
428 0 0         return unless ref $request->{list_datainfo} eq 'ARRAY';
429              
430 0           my @keys;
431             my %found;
432            
433 0           foreach my $k ( @{$request->{list_datainfo}} )
  0            
434             {
435 0 0         next if $found{$k};
436 0 0         next unless defined $request->{extra_datainfo}{$k};
437              
438 0           push @keys, $k;
439 0           $found{$k} = 1;
440             }
441              
442 0           return @keys;
443             }
444              
445              
446             sub extra_datainfo {
447              
448 0     0 0   my ($request, $key) = @_;
449              
450 0 0         if ( defined $key )
451             {
452 0           return $request->{extra_datainfo}{$key};
453             }
454              
455             else
456             {
457 0           return $request->{extra_datainfo};
458             }
459             }
460              
461              
462             sub extra_datainfo_title {
463            
464 0     0 0   my ($request, $key) = @_;
465              
466 0 0         if ( defined $key )
467             {
468 0           return $request->{title_datainfo}{$key};
469             }
470              
471             else
472             {
473 0           return $request->{title_datainfo};
474             }
475             }
476              
477              
478             # contact_info ( )
479             #
480             # Return a hash of information indicating who to contact about this data service.
481              
482             sub contact_info {
483            
484 0     0 1   my ($self) = @_;
485              
486 0           my $ds = $self->{ds};
487 0           return $ds->contact_info;
488             }
489              
490              
491             # node_attr ( )
492             #
493             # Return the specified attribute of the node that matches this request.
494              
495             sub node_attr {
496            
497 0     0 1   my ($self, $attr) = @_;
498            
499 0           my $ds = $self->{ds};
500 0           my $path = $self->node_path;
501            
502 0           return $ds->node_attr($path, $attr);
503             }
504              
505             # special_value ( param )
506             #
507             # Return the value of the specified special param, if it is enabled, and if
508             # it was specified. Return undefined otherwise.
509              
510             sub special_value {
511              
512 0     0 1   my ($self, $param) = @_;
513            
514 0           my $ds = $self->{ds};
515            
516 0   0       my $param_name = $ds->special_param($param) || return;
517            
518             # If we have already passed the params through HTTP::Validate, return the
519             # cleaned value.
520            
521 0 0         if ( ref $self->{valid} )
522             {
523 0           my $value = $self->{valid}->value($param_name);
524 0 0         return @$value if ref $value eq 'ARRAY';
525 0 0         return $value if defined $value;
526 0           return; # otherwise
527             }
528            
529             # Otherwise, return the raw value if it exists and undefined otherwise.
530            
531 0           return $self->{raw_params}{$param_name};
532             }
533              
534              
535             # special_given ( param )
536             #
537             # Return true if the given special parameter was specified in the request,
538             # regardless of its value.
539              
540             sub special_given {
541              
542 0     0 1   my ($self, $param) = @_;
543            
544 0           my $ds = $self->{ds};
545 0   0       my $param_name = $ds->special_param($param) || return;
546            
547 0           return exists $self->{raw_params}{$param_name};
548             }
549              
550              
551             # default_limit ( )
552             #
553             # Return the default result limit, if any. Return undefined otherwise.
554              
555             sub default_limit {
556            
557 0     0 1   my ($self) = @_;
558            
559 0           my $path = $self->{node_path};
560 0           return $self->{ds}->node_attr($path, 'default_limit');
561             }
562              
563              
564             sub set_scratch {
565            
566 0     0 0   my ($self, $key, $value) = @_;
567            
568 0           return $self->{ds}->set_scratch($key, $value);
569             }
570              
571              
572             sub get_scratch {
573            
574 0     0 0   my ($self, $key) = @_;
575            
576 0           return $self->{ds}->get_scratch($key);
577             }
578              
579              
580             sub add_warning {
581              
582 0     0 1   my ($self, $warn_msg) = @_;
583            
584 0 0         $self->{warnings} = [] unless ref $self->{warnings} eq 'ARRAY';
585 0           push @{$self->{warnings}}, $warn_msg;
  0            
586             }
587              
588              
589             sub warnings {
590              
591 0     0 1   my ($self) = @_;
592            
593 0 0         return @{$self->{warnings}} if ref $self->{warnings} eq 'ARRAY';
  0            
594 0           return;
595             }
596              
597              
598             sub errors {
599              
600 0     0 1   my ($self) = @_;
601            
602 0 0         return @{$self->{errors}} if ref $self->{errors} eq 'ARRAY';
  0            
603 0           return;
604             }
605              
606              
607             sub cautions {
608              
609 0     0 1   my ($self) = @_;
610            
611 0 0         return {@$self->{cautions}} if ref $self->{cautions} eq 'ARRAY';
612 0           return;
613             }
614              
615              
616             sub error_result {
617            
618 0     0 1   my ($self, $error) = @_;
619            
620 0           return $self->{ds}->error_result($error, $self);
621             }
622              
623             =head1 NAME
624              
625             Web::DataService::Request - object class for data service requests
626              
627             =head1 SYNOPSIS
628              
629             As each incoming request is handled by the Web::DataService framework, a
630             request object is created to represent it. This object is blessed into a
631             subclass of Web::DataService::Request which provides the methods listed here
632             and also includes one or more L with methods that you have
633             written for evaluating the request and doing the appropriate fetching/storing
634             on the backend data system.
635              
636             The simplest way for the main application to handle a request is as follows:
637              
638             Web::DataService->handle_request(request);
639              
640             This call uses the C function provided by the foundation framework
641             (L) to get the "outer" object representing this request from the point
642             of view of the foundation framework, and then passes it to the
643             L
644             method of Web::DataService. In the process of handling the request, a new
645             "inner" request object is generated and blessed into an appropriate subclass
646             of Web::DataService::Request.
647              
648             If you wish more control over this process, you can substitute the following:
649              
650             my $inner = Web::DataService->new_request(request);
651            
652             # You can put code here to check the attributes of $inner and possibly
653             # alter them...
654            
655             $inner->execute;
656              
657             Whichever of these code fragments you use should go into a Dancer L
658             handler|Dancer/"USAGE">.
659              
660             =head2 Request handling process
661              
662             The request handling process carried out by
663             L works
664             as follows:
665              
666             =over
667              
668             =item 1.
669              
670             The request URL path and parameters are parsed according to the active set of
671             data service features and special parameters. Depending upon the set of data
672             service features that are active, the path may be processed before moving on
673             to the next step. The following is not an exhaustive list, but illustrates
674             the kinds of processing that are done:
675              
676             =over
677              
678             =item *
679              
680             If more than one data service is defined, the appropriate one is selected to
681             handle this request.
682              
683             =item *
684              
685             If the data service has the attribute "path_prefix", this prefix is removed
686             from the path.
687              
688             =item *
689              
690             If the feature 'format_suffix' is active and the path ends in a format suffix
691             such as C<.json>, then that suffix is removed and later used to set the
692             "format" attribute of the request.
693              
694             =item *
695              
696             If the feature 'doc_paths' is active and the path ends in '_doc' or in
697             '/index' then this suffix is removed and the "is_doc_request" attribute of the
698             request is set.
699              
700             =item *
701              
702             If the special parameter 'document' is active and this parameter was included
703             with the request, then the "is_doc_request" attribute of the request is set.
704              
705             =back
706              
707             =item 2.
708              
709             The modified request path is matched against the set of data service node
710             paths. Nodes with either of the attributes C or C
711             match as prefixes, all others must match exactly. If none of the nodes match,
712             then the request is rejected with a HTTP 404 error. Otherwise, a new request
713             object is created and configured using the attributes of the matching node.
714              
715             =back
716              
717             If you used L
718             instead of L
719             ] )">, then you get control at this point and can modify the request before
720             calling C<< $request->execute >> to finish the process.
721              
722             =over
723              
724             =item 3.
725              
726             If the matching node has the C attribute, then the contents of the
727             specified file are returned using the foundation framework (i.e. Dancer). If
728             the node has the C attribute instead, then the remainder of the
729             request path is applied as a relative path to that directory. The result of
730             the request will be either the contents of a matching file or a HTTP 404
731             error.
732              
733             =item 4.
734              
735             Otherwise, the new request will be blessed into an automatically generated
736             subclass of Web::DataService::Request. These subclasses are generated
737             according to the value of the "role" attribute of the matching node. Each
738             different role generates two subclasses, one for documentation requests and
739             one for operation requests. These classes are composed so that they contain
740             the necessary methods for documentation rendering and operation execution,
741             respectively, along with all of the definitions from the primary role (this
742             role module must be written by the application author).
743              
744             =item 5.
745              
746             If the "is_doc_request" attribute has been set, or if the matching node does
747             not have a value for the "method" attribute, then the documentation directory
748             is checked for a template corresponding to the matching node. If not found,
749             the appropriate default template is used. This template is rendered to
750             produce a documentation page, which is returned as the result of the request.
751              
752             =item 6.
753              
754             Otherwise, we can assume that the node has a "method" attribute. The request
755             parameters are then checked against the ruleset named by the "ruleset"
756             attribute, or the ruleset corresponding to the node path if this attribute is
757             not set.
758              
759             =item 7.
760              
761             The output is then configured according to the output blocks(s) indicated by the
762             "output" attribute plus those indicated by "optional_output" in conjunction
763             with the special parameter "show".
764              
765             =item 8.
766              
767             The method specified by the node attribute "method" is then called. This
768             method (which must be written by the application author) is responsible for
769             fetching and/or storing data using the backend system and specifying what the
770             result of the operation should be.
771              
772             =item 9.
773              
774             If the result of the operation is one or more data records, these records are
775             processed according to the specification contained in the selected output
776             block(s), and are then serialized by the module corresponding to the selected
777             output format. If "count" or "datainfo" were requested, or if any warnings or
778             errors were generated during the execution of the request, this material is
779             included in an appropriate way by the serialization module. The resulting
780             response body is returned using the foundation framework.
781              
782             =item 10.
783              
784             If the result of the operation is instead a piece of non-record data (i.e. an
785             image or other binary data), it is returned as the response body using the
786             foundation framework.
787              
788             =back
789              
790             =head1 METHODS
791              
792             =head2 Constructor
793              
794             =head3 new ( attributes... )
795              
796             You will not need to call this method directly; instead, you should call the
797             L
798             method of Web::DataService, which calls it internally after carrying out other
799             processing.
800              
801             =head2 Execution
802              
803             =head3 execute ( )
804              
805             Executes this request, and returns the serialized response data. If your main
806             application uses C, then you will not need to call this
807             method because C calls it internally.
808              
809             =head3 error_result ( error )
810              
811             Aborts processing of the request and causes a HTTP error response to be
812             returned to the client. You will probably not need to call this method, since
813             the preferred way of generating an error condition is to call
814             L. The parameter can be any of the following:
815              
816             =over
817              
818             =item *
819              
820             A HTTP error code, such as "404" or "500".
821              
822             =item *
823              
824             An error message, which will be written to the log. For security reasons, the
825             client will just get back a HTTP 500 response that tells them a server error
826             occurred and they should contact the server administrator.
827              
828             =item *
829              
830             A validation result object from L. The client will get back a
831             HTTP 400 response containing the error and warning messages contained within
832             it.
833              
834             =back
835              
836             =head2 Attribute accessors
837              
838             =head3 ds
839              
840             Returns a reference to the data service instance with which this request is
841             associated.
842              
843             =head3 outer
844              
845             Returns a reference to the "outer" request object defined by the foundation
846             framework.
847              
848             =head3 path
849              
850             Returns the raw path associated with the request.
851              
852             =head3 node_path
853              
854             Returns the path of the node that matches this request.
855              
856             =head3 rest_path
857              
858             If the node path matches the processed request path as a prefix, this accessor returns
859             the remainder of the path. Otherwise, it returns C.
860              
861             =head3 is_invalid_request
862              
863             Returns true if this request could not be matched to a node, or is otherwise
864             invalid. Returns false otherwise.
865              
866             =head3 is_doc_request
867              
868             Returns true if this request has been determined to be a request for
869             documentation, according to the features and special parameters enabled for
870             this data service. Returns false otherwise.
871              
872             =head3 is_node_path
873              
874             Returns true if the request path I matches the path of a data service
875             node, false otherwise.
876              
877             =head3 http_method
878              
879             Returns (or sets) the HTTP method associated with the request.
880              
881             =head3 request_url
882              
883             Returns the complete request URL.
884              
885             =head3 base_url
886              
887             Returns the base component of the request URL, of the form
888             "http://some.host/" or something similar.
889              
890             =head3 root_url
891              
892             Returns the base URL plus the path prefix (if any) for this data service.
893              
894             =head3 path_prefix
895              
896             Returns the path prefix (if any) for this data service.
897              
898             =head3 data_info
899              
900             Returns a hash containing information about the request and the data to be
901             returned. The hash keys will include some or all of the following, depending
902             upon the configuration of the data service.
903              
904             =over
905              
906             =item title, data_provider, data_source, data_license, license_url
907              
908             The values of these keys will be the corresponding attributes of the data
909             service. They may be undefined if no value was specified for them either when
910             the data service was instantiated or in the configuration file maintained by
911             the foundation framework.
912              
913             =item access_time
914              
915             The current time.
916              
917             =item data_url
918              
919             The complete request URL.
920              
921             =item documentation_url
922              
923             A URL that will return a documentation page describing the selected data
924             service node.
925              
926             =back
927              
928             =head3 data_info_keys
929              
930             Returns a list of the keys documented for C, in a canonical order
931             for use by the serialization modules.
932              
933             =head3 contact_info
934              
935             Returns a hash whose keys are C and C. The values will be the
936             values of the data service attributes C and C,
937             respectively.
938              
939             =head3 generate_url ( attrs )
940              
941             This method returns a URL generated from the specified attributes, which must be given
942             either as a hashref or as a string:
943              
944             # either of the following:
945            
946             $url = $request->generate_url( { op => 'abc/def', format => 'json', params => 'foo=1' } );
947             $url = $request->generate_url( "op:abc/def.json?foo=1" );
948              
949             The attributes are as follows:
950              
951             =over
952              
953             =item node
954              
955             Generate a URL which will request documentation using the node path given by
956             the value of this attribute. In the string form, this is represented by a
957             prefix of "node:".
958              
959             =item op
960              
961             Generate a URL which will request a data service operation using the node path
962             given by the value of this attribute. In the string form, this is represented
963             by a prefix of "op:".
964              
965             =item path
966              
967             Generate a URL which will request the exact path given. This is used to
968             generate URLs for requesting files, such as CSS files. In the string form,
969             this is represented by a prefix of "path:".
970              
971             =item format
972              
973             The generated URL will request output in the specified format. Depending upon
974             the features enabled for this data service, that may mean either adding the
975             specified value as a suffix to the URL path, or adding a special parameter.
976             In the string form, this is represented by adding '.' followed by the format
977             to the path (this syntax is fixed no matter which data service features are
978             enabled).
979              
980             =item params
981              
982             Configure the URL to include the specified parameters. The value of this
983             attribute must be either an arrayref with an even number of elements or a
984             single URL parameter string such as C<"foo=1&bar=2">. In the string form,
985             this is represented by a '?' followed by the parameter string.
986              
987             =item type
988              
989             The value of this attribute must be either C, C, or C. If
990             "abs" is given, then the generated URL will begin with
991             "http[s]://hostname[:port]/. If "site", then the generated URL will begin
992             with "/" followed by the path prefix for this data service (if any). If
993             "relative", no prefix will be added to the generated URL. In this case, you
994             must make sure to specify a path that will work properly relative to the URL
995             of the page on which you intend to display it.
996              
997             If this attribute is not specified, it defaults to "site". In the string
998             form, this is represented by modifying the prefix, i.e. "oprel:" or "opabs:"
999             instead of just "op:".
1000              
1001             =back
1002              
1003             =head3 node_attr ( name )
1004              
1005             Returns the value of the specified attribute of the node matching this
1006             request, or I if the attribute is not defined for that node.
1007              
1008             =head3 special_value ( param )
1009              
1010             Returns the value of the specified special parameter, if it is enabled for
1011             this data service and if it was included with this request. Returns I
1012             otherwise.
1013              
1014             =head3 special_given ( param )
1015              
1016             Returns true if the specified special parameter was included in this request
1017             and is enabled for this data service, regardless of its value. Returns false
1018             otherwise.
1019              
1020             =head3 default_limit
1021              
1022             Returns the default result limit, if any. This is used in generating
1023             documentation.
1024              
1025             =head2 Documentation methods
1026              
1027             The following methods are only available with documentation requests. They can
1028             be called from documentation templates as follows:
1029              
1030             <% result = request.method_name(args) %>
1031              
1032             or, to include the result directly in the rendered output:
1033              
1034             <% request.method_name(args) %>
1035              
1036             In either case, "request" is a variable automatically provided to the
1037             templating engine. The string "result" should be replaced by whatever
1038             variable you wish to assign the result to, and "method_name" and "args" by the
1039             desired method and arguments.
1040              
1041             These methods are all packaged up in blocks defined by doc_defs.tt, so you
1042             will not need to call them directly unless you want to make substantive
1043             changes to the look of the documentation pages.
1044              
1045             =head3 document_node
1046              
1047             Returns the documentation string for the node matching this request, or the
1048             empty string if none was defined.
1049              
1050             =head3 list_navtrail
1051              
1052             Returns a list of navigation trail components for the current request, in Pod
1053             format. These are generated componentwise from the node path.
1054              
1055             =head3 document_usage
1056              
1057             Returns a string in Pod format listing the URLs generated from the node
1058             attribute "usage", if any were given for this node.
1059              
1060             =head3 list_subnodes
1061              
1062             Returns a list of the node paths corresponding to all subnodes of the current
1063             one for which the C attribute was set.
1064              
1065             =head3 document_subnodes
1066              
1067             Returns a string in Pod format documenting the subnodes of the current one for
1068             which the C attribute was set.
1069              
1070             =head3 document_params
1071              
1072             Returns a string in Pod format documenting the parameters available for this
1073             request. This is automatically generated from the corresponding ruleset, if
1074             one was defined.
1075              
1076             =head3 list_http_methods
1077              
1078             Returns a list of HTTP methods that are allowed for this request path.
1079              
1080             =head3 document_http_methods
1081              
1082             Returns a string in Pod format documenting the HTTP methods that are allowed
1083             for this request path.
1084              
1085             =head3 document_response
1086              
1087             Returns a string in Pod format documenting the all of the fields that might be
1088             included in the result.
1089              
1090             =head3 output_label
1091              
1092             Returns the value of the node attribute "output_label", or the default value
1093             "basic" if none was defined.
1094              
1095             =head3 optional_output
1096              
1097             Returns the value of the node attribute "optional_output", if this attribute
1098             was defined.
1099              
1100             =head3 document_formats ( options )
1101              
1102             Returns a string in Pod format documenting the formats allowed for this
1103             node. If a parameter is specified, it must be a hashref. If this includes
1104             the key 'all' with a true value, then all formats defined for this
1105             data service are included. If it includes the key 'extended' with a true value, then
1106             a description of each format is included.
1107              
1108             =head3 default_format
1109              
1110             Return the name of the default format (if any was specified) for this node.
1111              
1112             =head3 document_vocabs ( options )
1113              
1114             Return a string in Pod format documenting the vocabularies allowed for this
1115             node. If a parameter is specified, it must be a hashref. If this includes
1116             the key 'all' with a true value, then all vocabularies defined for this
1117             data service are included. If it includes the key 'extended' with a true value, then
1118             a description of each vocabulary is included.
1119              
1120             =head3 output_format
1121              
1122             You can use this method to check whether the response is to be rendered into
1123             HTML or returned as Pod text. The values returned are C and
1124             respectively.
1125              
1126             =head2 Operation methods
1127              
1128             The following methods are only available with operation requests. They can be
1129             called from any of the operation methods included in the application role
1130             module(s).
1131              
1132             =head3 get_connection
1133              
1134             This method can only be used if you explicitly specified a backend plugin when
1135             instantiating the data service, or if the module L
1136             was required in your main application before Web::DataService.
1137              
1138             Assuming that the proper connection information is present in the application
1139             configuration file, this method will return a connection to your backend data
1140             store.
1141              
1142             =head3 exception ( code, message )
1143              
1144             Returns an exception object encoding the specified HTTP result code and a message to go with
1145             it. This exception object can be used as an argument to 'die'. Its type is
1146             C.
1147              
1148             =head3 debug
1149              
1150             Returns true if the data service process is running under debug mode. This can be used to output
1151             extra debugging information as appropriate.
1152              
1153             =head3 debug_line ( text )
1154              
1155             Print the specified text to standard error, followed by a newline, if debug mode is enabled for
1156             this data service process. This can be used, for example, to output the text of SQL statements
1157             executed on the underlying database, and similar information, for debugging purposes. For example:
1158              
1159             $request->debug_line($sql) if $request->debug;
1160              
1161             =head3 param_keys ( )
1162              
1163             Returns a list of the parameter keys corresponding to the request parameters.
1164             These will generally be the same as the parameter names, but may
1165             be different if you include the keys C and/or C in the parameter
1166             validation rulesets (see L).
1167              
1168             =head3 clean_param ( param )
1169              
1170             Returns the cleaned value of the specified parameter, or undefined if the
1171             parameter was not included in the request. If more than one parameter value was
1172             given, the result will be an array ref.
1173              
1174             =head3 clean_param_list ( param )
1175              
1176             Returns a list of all the cleaned values of the specified parameter (one or
1177             more), or empty if the parameter was not included in the request.
1178              
1179             =head3 clean_param_hash ( param )
1180              
1181             Returns a hashref whose keys are all of the cleaned values of the specified
1182             parameter, or an empty hashref if the parameter was not included in the
1183             request.
1184              
1185             =head3 param_given ( param )
1186              
1187             Returns true if the specified parameter was included in there request, whether
1188             or not it had a valid value. Returns false otherwise.
1189              
1190             =head3 params_for_display
1191              
1192             Returns a list of (parameter, value) pairs for use in responding to the
1193             'datainfo' special parameter. This result list leaves out any special
1194             parameters that do not affect the content of the result. Multiple values are
1195             concatenated together using commas.
1196              
1197             =head3 validate_params ( ruleset_name, param... )
1198              
1199             Validates the specified parameters (which may be hash or list refs of parameters and values) to
1200             the specified ruleset. Returns the result, which will be an object of type HTTP::Validate::Result
1201             that can then be queried for success or failure, error messages, etc. The primary purpose for this
1202             method is to allow validation of data records before they are added to the underlying database.
1203              
1204             =head3 raw_body
1205              
1206             Returns the request body as an un-decoded string. If the request does not contain a body, returns
1207             the empty string. The primary purpose for this method is to accept data for addition to the
1208             underlying database.
1209              
1210             =head3 decode_body
1211              
1212             Attempts to decode the request body, if it is in a known format. Currently, the only two formats
1213             understood are JSON and text. A JSON body will be decoded into a Perl data structure, while a text
1214             body will be split into a list of lines. If no body exists, the undefined value is returned. If an
1215             error occurs during JSON decoding, it will be returned as a second item. Consequently, the return
1216             value of this method should be assigned to a two-element list.
1217              
1218             =head3 has_block ( block )
1219              
1220             Returns true if the specified output block was selected for this request. The
1221             parameter can be either the name of the block or the parameter value by which
1222             it would be selected.
1223              
1224             =head3 select_list ( subst )
1225              
1226             Returns a list of strings derived from the 'select' configuration records
1227             found in the output blocks selected for this request. You can use these
1228             records to specify which fields need to be retrieved from the backend data
1229             store. Any given string will only appear once in the list, even if it occurs
1230             in multiple 'select' records.
1231              
1232             The optional argument should be a hashref, indicating substitutions to be
1233             made. For example, given the following code,
1234              
1235             $ds->define_block( 'block1' =>
1236             { select => '$a.name', '$a.value', 'c.size' },
1237             ... );
1238            
1239             # ...and in a different subroutine...
1240            
1241             my @fields = $request->select_list( { a => 'table1', b => 'table2' } )
1242              
1243             The result will include C, C, and C.
1244              
1245             If you are using an SQL-based backend, and if you set up the 'select' records
1246             properly, you can use this method (or see C below) to build a
1247             SELECT statement that will fetch exactly the information needed for the
1248             selected set of output blocks. This is important if your application allows
1249             optional output blocks that can be selected arbitrarily by the client. If you
1250             are using a non-SQL backend, you are free to use this in any way that makes
1251             sense given the backend interface.
1252              
1253             =head3 select_hash ( subst )
1254              
1255             Returns the same set of strings as C, but as the keys in a
1256             hash. The values will all be 1.
1257              
1258             =head3 select_string ( subst )
1259              
1260             Returns the same set of strings as C, but joined into a single
1261             string with each item separated by a comma and a space.
1262              
1263             =head3 substitute_select ( variable => value, variable => value ... )
1264              
1265             Make substitutions in the select list. For example, if passed the arguments 'v => xt', then
1266             anywhere the string '$v' appears in the select list, that string will be replaced by 'xt'. This
1267             method should be called before 'select_list' or 'select_string'. The intended use is to select
1268             between one or more alternate database tables.
1269              
1270             =head3 tables_hash
1271              
1272             Returns a hashref whose keys are derived from the 'select' configuration
1273             records found in the output blocks selected for this request. The keys from
1274             this hash will be the values specified by any 'tables' attributes in those
1275             configuration records. The values will all be 1.
1276              
1277             If you are using an SQL-based backend, and if you set up the 'select' records
1278             properly, you can use this method to keep track of which database tables will
1279             be needed in order to build a query that can satisfy all of the data blocks
1280             included in this request. You can use the set of keys to constuct an
1281             appropriate list of table joins. If you are using a non-SQL backend, you can
1282             use this in any way that makes sense given the backend interface.
1283              
1284             If you call this method multiple times, you will get a reference to the same
1285             hash each time. This means that you can safely add and remove keys during
1286             your own processing.
1287              
1288             =head3 add_table ( alias, [full_name] )
1289              
1290             Add an extra key to the tables hash. The optional second parameter can be the full name of the
1291             table to be included, but this is ignored. Note that adding a table to the table hash will I
1292             automatically include that table in any SQL statements. You need to check the table hash and add
1293             it yourself if the appropriate key is found.
1294              
1295             =head3 filter_hash
1296              
1297             Returns a hashref whose keys are derived from the 'filter' configuration
1298             records found in the output blocks selected for this request. The values will
1299             all be 1.
1300              
1301             If you are using an SQL-based backend, and if you set up the 'filter' records
1302             properly, you can use this method to get a list of (unique) filter expressions
1303             to use in building a query that can satisfy all of the data blocks included in
1304             this request. (Note: you will almost always need to add other filter
1305             expressions derived from parameter values as well). If you are using a
1306             non-SQL backend, you can use this in any way that makes sense given the
1307             backend interface.
1308              
1309             If you call this method multiple times, you will get a reference to the same
1310             hash each time. This means that you can safely add and remove keys during
1311             your own processing.
1312              
1313             =head3 output_field_list
1314              
1315             This method returns the output field list for the current request. This is the actual list, not a
1316             copy, so it can be manipulated. This is a real hack, which will probably be removed from a future
1317             version of this module. But for the time being, you can use it (for example) to go through the
1318             list and prune fields that will not be used.
1319              
1320             =head3 delete_output_field ( field )
1321              
1322             Remove the specified output field from the list. The first field whose name (not label) matches
1323             the argument is removed, regardless of what output block it occurs in. If no fields match, nothing
1324             will be removed.
1325              
1326             =head3 result_limit
1327              
1328             Returns the result limit specified for this request, or undefined if none was
1329             given or if C was specified. Even though Web::DataService will always
1330             truncate the result set if a limit was given, you may want to include this
1331             limit value in any queries you make to the backend so as to prevent your
1332             server from doing unnecessary work.
1333              
1334             =head3 result_offset ( will_handle )
1335              
1336             Returns true if a result offset was specified for this request, or zero if
1337             none was specified. If the argument value is true, then Web::DataService
1338             assumes that you will handle the process of offsetting the data result,
1339             e.g. by using modifying your backend query appropriately (see
1340             C below).
1341              
1342             If the argument is false, or if you never call either this method or
1343             C, then (if an offset was specified for this request)
1344             Web::DataService will automatically discard the corresponding number of
1345             records from the beginning of the result set before serializing the results.
1346              
1347             =head3 sql_limit_clause ( will_handle )
1348              
1349             Returns a string whose value is an LIMIT clause that can be added to an SQL
1350             query to generate a result set in accordance with result limit and offset (if
1351             any) specified for this request. If the argument is true, then
1352             Web::DataService assumes that you will actually do this.
1353              
1354             If the argument is false, or if you never call either this method or
1355             C, then (if an offset was specified for this request)
1356             Web::DataService will automatically discard the corresponding number of
1357             records from the beginning of the result set before serializing the results.
1358              
1359             If a result limit was specified for this request, and if the result set you
1360             generate exceeds this size, Web::DataService will always truncate it to match
1361             the specified limit.
1362              
1363             =head3 sql_count_clause ( )
1364              
1365             Returns a string that can be added to an SQL statement to generate a result
1366             count in accordance with the request parameters. If the special parameter
1367             "count" was specified for this request, the result will be
1368             C. Otherwise, it will be the empty string.
1369              
1370             If you are using a non-SQL backend, you can still use this as a boolean
1371             variable to determine if the result should include a count of the number of
1372             records found.
1373              
1374             =head3 sql_count_rows ( )
1375              
1376             Execute the SQL statement "SELECT FOUND ROWS" and store the result for use in generating the
1377             response header. But only do this if the request parameters specify that result counts should
1378             be returned.
1379              
1380             =head3 set_result_count ( count )
1381              
1382             Use this method to tell Web::DataService the result count if you are using
1383             C. In this case, you will generally need to execute a separate query
1384             such as "SELECT FOUND_ROWS()" after your main query.
1385              
1386             =head3 output_format
1387              
1388             Returns the name of the response format selected for this request.
1389              
1390             =head3 output_vocab
1391              
1392             Returns the name of the response vocabulary selected for this request. If no
1393             vocabularies have been defined for this data service, it will return "null",
1394             the name of the default vocabulary.
1395              
1396             =head3 output_linebreak
1397              
1398             Returns the string to be inserted between output lines in text-based response
1399             formats. This will be either a carriage return, a linefeed, or both.
1400              
1401             =head3 result_limit
1402              
1403             Returns the limit (if any) specified for the size of the result set.
1404              
1405             =head3 result_offset
1406              
1407             Returns the offset (if any) specified for the start of the result set.
1408              
1409             =head3 display_header
1410              
1411             Returns true if header material is to be displayed in text-based response
1412             formats, false otherwise.
1413              
1414             =head3 display_datainfo
1415              
1416             Returns true if a description of the dataset is to be included in
1417             the response, false otherwise.
1418              
1419             =head3 display_counts
1420              
1421             Returns true if result counts and elapsed time are to be included in the
1422             response, false otherwise.
1423              
1424             =head3 save_output
1425              
1426             Returns true if the special parameter 'save' was included in the request.
1427              
1428             =head3 get_config
1429              
1430             Returns a hashref providing access to the attributes defined in the
1431             application configuration file. Allows you to include application-specific
1432             directives in the file and retrieve them as needed from your operation
1433             methods.
1434              
1435             =head3 set_content_type
1436              
1437             Specify the value for the "Content-type" HTTP response header. You will
1438             probably not need to call this, since it is set automatically based on the
1439             selected response format.
1440              
1441             =h3ad3 exception ( code, message )
1442              
1443             Returns an exception object which can be used as an argument to C. This
1444             will abort processing of the current request and generate an HTTP error
1445             result. The first argument must be a valid HTTP error code.
1446              
1447             =head2 Result methods
1448              
1449             These methods are also available with operation requests. I
1450             call at least one of them from each of your operation methods.> These methods
1451             are how you tell Web::DataService the result of each operation.
1452              
1453             You can make more than one of these calls from a single operation, but note
1454             that each call (except for C in some cases) wipes out any result
1455             specified by previous calls.
1456              
1457             =head3 single_result ( record )
1458              
1459             The argument must be a hashref representing a single data record. The result
1460             of this operation will be that single record.
1461              
1462             =head3 list_result ( record... )
1463              
1464             You can call this method either with a single arrayref argument whose members
1465             are hashrefs, or with a list of hashrefs. Either way, the result of this
1466             operation will be the specified list of records.
1467              
1468             =head3 add_result ( record... )
1469              
1470             Adds the specified record(s) to a result set previously specified by
1471             C. All arguments must be hashrefs.
1472              
1473             =head3 sth_result ( sth )
1474              
1475             The argument must be a valid DBI statement handle that has already been
1476             executed. Once your operation method returns, Web::DataService will then
1477             fetch the result records from this sth one by one, process them according to
1478             the selected set of output blocks for this request, and serialize the result.
1479              
1480             If you use this result method, you will need to call either C
1481             or C to determine if a result count is needed. If so,
1482             execute a "SELECT FOUND_ROWS()" query (or the equivalent) and use
1483             C to tell Web::DataService how many records were found.
1484              
1485             =head3 data_result ( data )
1486              
1487             The argument must be either a scalar or a reference to a scalar. In either
1488             case, this data will be returned as the result of the operation without any
1489             further processing. You can use this, for example, to return images or other
1490             binary data. You can use C to set the result content type,
1491             or you can rely on the suffix of the URL path if appropriate.
1492              
1493             =head3 clear_result
1494              
1495             This call clears any results that have been specified for this operation by
1496             any of the other methods in this section.
1497              
1498             =head3 skip_output_record ( record )
1499              
1500             The given record is marked in such a way as to cause it to be omitted from the output. The record
1501             counts are not updated, however, which limits its utility. This method can be called from an
1502             operation method if C is being used, or else from a C routine.
1503              
1504             =head3 select_output_block ( record, block_name )
1505              
1506             The given record will be output using the specified output block, instead of the output
1507             block specified by the operation node attributes. That output block will be configured if
1508             it has not yet been configured for this operation. Optional output blocks are not affected.
1509             A future version of this module will provide ways to alter the optional output blocks.
1510              
1511             =head3 add_warning ( message )
1512              
1513             Add the specified warning message to this request. The warnings will be
1514             automatically included in the result, in a manner appropriate for the selected
1515             response format.
1516              
1517             =head3 warnings ( )
1518              
1519             Return a list of the warning messages (if any) that have been added to this
1520             request.
1521              
1522             =head3 add_caution ( message )
1523              
1524             Add the specified caution message to this request. The caution messages will be automatically
1525             included in the result, in a manner appropriate for the selected response format.
1526              
1527             =head3 cautions ( )
1528              
1529             Return a list of the caution messages (if any) that have been added to this request.
1530              
1531             =head3 add_error ( message )
1532              
1533             Add the specified error message to this request. The error messages will be automatically
1534             included in the result, in a manner appropriate for the selected response format.
1535              
1536             =head3 errors ( )
1537              
1538             Return a list of the error messages (if any) that have been added to this request.
1539              
1540             =head1 AUTHOR
1541              
1542             mmcclenn "at" cpan.org
1543              
1544             =head1 BUGS
1545              
1546             Please report any bugs or feature requests to C, or through
1547             the web interface at L. I will be notified, and then you'll
1548             automatically be notified of progress on your bug as I make changes.
1549              
1550             =head1 COPYRIGHT & LICENSE
1551              
1552             Copyright 2014 Michael McClennen, all rights reserved.
1553              
1554             This program is free software; you can redistribute it and/or modify it
1555             under the same terms as Perl itself.
1556              
1557             =cut
1558              
1559             1;