1# vi:ai:sm:et:sw=4:ts=4:tw=0 2# 3# REST::Application - A framework for building RESTful web-applications. 4# 5# Copyright 2005 Matthew O'Connor <matthew@canonical.org> 6package REST::Application; 7use strict; 8use warnings; 9use Carp; 10use Tie::IxHash; 11use UNIVERSAL; 12use CGI; 13 14our $VERSION = '0.992'; 15 16#################### 17# Class Methods 18#################### 19 20sub new { 21 my ($proto, %args) = @_; 22 my $class = ref($proto) ? ref($proto) : $proto; 23 my $self = bless({ __defaultQuery => CGI->new() }, $class); 24 $self->setup(%args); 25 return $self; 26} 27 28################################## 29# Instance Methods - Object State 30################################## 31 32sub query { 33 my $self = shift; 34 35 # Set default value if this method hasn't been called yet. 36 if (not exists $self->{__query}) { 37 $self->{__query} = $self->defaultQueryObject(); 38 } 39 40 # Set the field if we got any arguments. 41 $self->{__query} = shift if @_; 42 43 return $self->{__query}; 44} 45 46sub defaultQueryObject { 47 my $self = shift; 48 49 # Set the field if we got any arguments. 50 if (@_) { 51 $self->{__defaultQuery} = shift; 52 } 53 54 return $self->{__defaultQuery}; 55} 56 57sub resourceHooks { 58 my $self = shift; 59 60 # Set default value if this method hasn't been called yet. 61 if (not exists $self->{__resourceHooks}) { 62 my %hooks; 63 tie(%hooks, "Tie::IxHash"); # For keeping hash key order preserved. 64 $self->{__resourceHooks} = \%hooks; 65 } 66 67 # If we got arguments then they should be an even sized list, otherwise a 68 # hash reference. 69 if (@_ and @_%2 == 0) { 70 %{ $self->{__resourceHooks} } = @_; 71 } elsif (@_ == 1) { 72 my $value = shift; 73 if (ref($value) ne 'HASH') { 74 croak "Expected hash reference or even-sized list."; 75 } 76 %{ $self->{__resourceHooks} } = %$value; 77 } 78 79 return $self->{__resourceHooks}; 80} 81 82sub extraHandlerArgs { 83 my $self = shift; 84 85 # Set default value for method if it hasn't been called yet. 86 if (not exists $self->{__extraHandlerArgs}) { 87 $self->{__extraHandlerArgs} = []; 88 } 89 90 # If got arguments then process them. We expect either a single array 91 # reference or a list 92 if (@_) { 93 if (@_ == 1 and ref($_[0]) eq 'ARRAY') { 94 $self->{__extraHandlerArgs} = shift; 95 } else { 96 $self->{__extraHandlerArgs} = [ @_ ]; 97 } 98 } 99 100 return @{ $self->{__extraHandlerArgs} }; 101} 102 103################################## 104# Instance Methods - Proxies 105################################## 106 107sub getPathInfo { 108 my $self = shift; 109 return $self->query->path_info(); 110} 111 112sub getRealRequestMethod { 113 my $self = shift; 114 return uc( $self->query->request_method() || "" ); 115} 116 117sub getRequestMethod { 118 my $self = shift; 119 my $real_method = $self->getRealRequestMethod(); 120 my $tunnel_method = uc( 121 $self->query->http('X-HTTP-Method') 122 || $self->query->url_param('http_method') 123 || $self->query->param('http_method') 124 || $real_method 125 ); 126 127 # POST can tunnel any method. 128 return $tunnel_method if $real_method eq 'POST'; 129 130 # GET can only tunnel GET/HEAD 131 if ( $real_method eq 'GET' and $tunnel_method =~ /^(GET|HEAD)$/ ) { 132 return $tunnel_method; 133 } 134 135 return $real_method; 136} 137 138############################# 139# Instance Methods - Public 140############################# 141 142sub loadResource { 143 my ($self, $path, @extraArgs) = @_; 144 $path ||= $self->getMatchText(); 145 my $handler = sub { $self->defaultResourceHandler(@_) }; 146 my $matches = []; 147 148 # Loop through the keys of the hash returned by resourceHooks(). Each of 149 # the keys is a regular expression, see if the current path info matches 150 # that regular expression. Save the parent matches for passing into the 151 # handler. 152 for my $pathRegex (keys %{ $self->resourceHooks() }) { 153 if ($self->checkMatch($path, $pathRegex)) { 154 $handler = $self->_getHandlerFromHook($pathRegex); 155 last; 156 } 157 } 158 159 return $self->callHandler($handler, @extraArgs); 160} 161 162sub getHandlerArgs { 163 my ($self, @extraArgs) = @_; 164 my @args = ($self, 165 $self->_getLastRegexMatches(), 166 $self->extraHandlerArgs(), 167 @extraArgs); 168 169 # Don't make $self the first argument if the handler is a method on $self, 170 # because in that case it'd be redundant. Also see _getHandlerFromHook(). 171 shift @args if $self->{__handlerIsOurMethod}; 172 173 return @args; 174} 175 176sub callHandler { 177 my ($self, $handler, @extraArgs) = @_; 178 my @args = $self->getHandlerArgs(@extraArgs); 179 180 # Call the handler, carp if something goes wrong. 181 my $result; 182 eval { 183 $self->preHandler(\@args); # no-op by default. 184 $result = $handler->(@args); 185 $self->postHandler(\$result, \@args); # no-op by default. 186 }; 187 carp "Handler failed: $@\n" if $@; 188 189 # Convert the result to a scalar result if it isn't already. 190 my $ref = (ref($result) eq 'scalar') ? $result : \$result; 191 192 return $ref; 193} 194 195sub getMatchText { 196 my $self = shift; 197 return $self->getPathInfo(); 198} 199 200sub checkMatch { 201 my ($self, $a, $b) = @_; 202 my $match = 0; 203 204 if ($a =~ /$b/) { 205 $self->_setLastRegexMatches(); 206 $self->{__last_match_path} = $a; 207 $self->{__last_match_pattern} = $b; 208 $match = 1; 209 } 210 211 return $match; 212} 213 214sub getLastMatchPath { 215 my $self = shift; 216 return $self->{__last_match_path}; 217} 218 219sub getLastMatchPattern { 220 my $self = shift; 221 return $self->{__last_match_pattern}; 222} 223 224sub run { 225 my $self = shift; 226 227 # Get resource. 228 $self->preRun(); # A no-op by default. 229 my $repr = $self->loadResource(@_); 230 $self->postRun($repr); # A no-op by default. 231 232 # Get the headers and then add the representation to to the output stream. 233 my $output = $self->getHeaders(); 234 $self->addRepresentation($repr, \$output); 235 236 # Send the output unless we're told not to by the environment. 237 print $output if not $ENV{REST_APP_RETURN_ONLY}; 238 239 return $output; 240} 241 242sub getHeaders { 243 my $self = shift; 244 my $type = $self->headerType() || ""; 245 my $header = ""; 246 247 if ($type eq 'header') { 248 $header = $self->query->header($self->header()); 249 } elsif ($type eq 'redirect') { 250 $header = $self->query->redirect($self->header()); 251 } elsif ($type ne 'none') { 252 croak "Unexpected header type: \"$type\"."; 253 } 254 255 return $header; 256} 257 258sub addRepresentation { 259 my ($self, $repr, $outputRef) = @_; 260 261 # Make sure $outputRef is a scalar ref and the scalar it references is 262 # defined. 263 return if ref($outputRef) ne 'SCALAR'; 264 return if not defined $$outputRef; 265 266 # If we're given a scalar reference then dereference it first, otherwise 267 # just treat what we got as though it's a string. 268 if (ref($repr) eq 'SCALAR') { 269 $$outputRef .= $$repr if defined $$repr; 270 } else { 271 $$outputRef .= $repr if defined $repr; 272 } 273} 274 275sub headerType { 276 my $self = shift; 277 278 # Set the default value if this method has not been called yet. 279 if (not exists $self->{__headerType}) { 280 $self->{__headerType} = "header"; 281 } 282 283 # If an argument was passed in then use them to set the header type. 284 if (@_) { 285 my $type = lc(shift || ""); 286 if ($type =~ /^(redirect|header|none)$/) { 287 $self->{__headerType} = $type; 288 } else { 289 croak "Invalid header type specified: \"$type\""; 290 } 291 } 292 293 return $self->{__headerType}; 294} 295 296sub header { 297 my $self = shift; 298 299 # Set the default value if this method has not been called yet. 300 if (not exists $self->{__header}) { 301 $self->{__header} = {}; 302 } 303 304 # If arguments were passed in then use them to set the header type. 305 # Arguments can be passed in as a hash-ref or as an even sized list. 306 if (@_) { 307 if (@_%2 == 0) { # even-sized list, must be hash 308 %{ $self->{__header} } = @_; 309 } elsif (ref($_[0]) eq 'HASH') { # First item must be a hash reference 310 $self->{__header} = shift; 311 } else { 312 croak "Expected even-sized list or hash reference."; 313 } 314 } 315 316 return %{$self->{__header}}; 317} 318 319sub resetHeader { 320 my $self = shift; 321 my %old = $self->header(); 322 $self->headerType('header'); 323 $self->{__header} = {}; 324 return %old; 325} 326 327sub setRedirect { 328 my ($self, $url) = @_; 329 $self->headerType('redirect'); 330 $self->header(-url => $url || ""); 331} 332 333############################################## 334# Instance Methods - Intended for Overloading 335############################################## 336 337sub setup { return } 338sub preRun { return } 339sub postRun{ return } 340sub preHandler { return } 341sub postHandler { return } 342sub defaultResourceHandler { return } 343 344############################# 345# Instance Methods - Private 346############################# 347 348# CodeRef _getHandlerFromHook(String $pathRegex) 349# 350# This method retrieves a code reference which will yield the resource of the 351# given $pathRegex, where $pathRegex is a key into the resource hooks hash (it 352# isn't used as a regex in this method, just a hash key). 353sub _getHandlerFromHook { 354 my ($self, $pathRegex) = @_; 355 my $ref = $self->resourceHooks()->{$pathRegex}; 356 my $refType = ref($ref); 357 my $handler = sub { $self->defaultResourceHandler(@_) }; 358 my $method = $self->getRequestMethod() || "getResource"; 359 360 # If we get a hash, then use the request method to narrow down the choice. 361 # We do this first because we allow the same range of handler types for a 362 # particular HTTP method that we do for a more generic handler. 363 if ($refType eq 'HASH') { 364 %$ref = map { uc($_) => $ref->{$_} } keys %$ref; # Uppercase the keys 365 my $http_method = $self->getRequestMethod(); 366 if (exists $ref->{$http_method}) { 367 $ref = $ref->{$http_method} 368 } elsif (exists $ref->{'*'}) { 369 $ref = $ref->{'*'}; 370 } else { 371 return $handler; # Just bail now with the default handler. 372 } 373 $refType = ref($ref); 374 } 375 376 # If we still have a hash then assume we're doing Content Negotation 377 if ($refType eq 'HASH') { 378 my $type = $self->bestContentType(keys %$ref); 379 $ref = $ref->{$type}; 380 $refType = ref($ref); 381 } 382 383 # Based on the the reference's type construct the handler. 384 if ($refType eq "CODE") { 385 # A code reference 386 $handler = $ref; 387 } elsif ($refType eq "ARRAY") { 388 # Array reference which holds a $object and "method name" pair. 389 my ($thing, $smethod) = @$ref; 390 $smethod ||= $method; 391 if (ref $thing) { 392 $handler = $self->makeHandlerFromRef($thing, $smethod); 393 } else { 394 $handler = $self->makeHandlerFromClass($thing, $smethod); 395 } 396 } elsif ($refType) { 397 # Object with GET, PUT, etc, or getResource method. 398 $handler = $self->makeHandlerFromRef($ref, $method); 399 } elsif ($ref) { 400 # A bare string signifying a method name 401 $handler = sub { $self->$ref(@_) }; 402 $self->{__handlerIsOurMethod} = 1; # See callHandler(). 403 } 404 405 return $handler; 406} 407 408sub makeHandlerFromRef { 409 my ($self, $ref, $method) = @_; 410 return sub { $ref->$method(@_) }; 411} 412 413sub makeHandlerFromClass { 414 my ($self, $class, $method) = @_; 415 return sub { $class->$method(@_) }; 416} 417 418sub bestContentType { 419 my ($self, @types) = @_; 420 return ($self->simpleContentNegotiation(@types))[0] || '*/*'; 421} 422 423# We don't support the full range of content negtiation because a) it's 424# overkill and b) it makes it hard to specify the hooks cleanly, also see (a). 425sub simpleContentNegotiation { 426 my ($self, @types) = @_; 427 my @accept_types = $self->getContentPrefs(); 428 my $score = sub { $self->scoreType(shift, @accept_types) }; 429 return sort {$score->($b) <=> $score->($a)} @types; 430} 431 432# The pattern matching stuff was stolen from CGI.pm 433sub scoreType { 434 my ($self, $type, @accept_types) = @_; 435 my $score = scalar(@accept_types); 436 for my $accept_type (@accept_types) { 437 return $score if $type eq $accept_type; 438 my $pat; 439 ($pat = $accept_type) =~ s/([^\w*])/\\$1/g; # escape meta characters 440 $pat =~ s/\*/.*/g; # turn it into a pattern 441 return $score if $type =~ /$pat/; 442 $score--; 443 } 444 return 0; 445} 446 447# Basic idea stolen from CGI.pm. Its semantics made it hard to pull out the 448# information I wanted without a lot of trickery, so I improved upon the 449# original. Same with libwww's HTTP::Negotiate algorithim, it's also hard to 450# make go with what we want. 451sub getContentPrefs { 452 my $self = shift; 453 my $default_weight = 1; 454 my @prefs; 455 456 # Parse the Accept header, and save type name, score, and position. 457 my @accept_types = split /,/, $self->getAcceptHeader(); 458 my $order = 0; 459 for my $accept_type (@accept_types) { 460 my ($weight) = ($accept_type =~ /q=(\d\.\d+|\d+)/); 461 my ($name) = ($accept_type =~ m#(\S+/[^;]+)#); 462 next unless $name; 463 push @prefs, { name => $name, order => $order++}; 464 if (defined $weight) { 465 $prefs[-1]->{score} = $weight; 466 } else { 467 $prefs[-1]->{score} = $default_weight; 468 $default_weight -= 0.001; 469 } 470 } 471 472 # Sort the types by score, subscore by order, and pull out just the name 473 @prefs = map {$_->{name}} sort {$b->{score} <=> $a->{score} || 474 $a->{order} <=> $b->{order}} @prefs; 475 return @prefs, '*/*'; # Allows allow for */* 476} 477 478sub getAcceptHeader { 479 my $self = shift; 480 return $self->query->http('accept') || ""; 481} 482 483# List _getLastRegexMatches(void) 484# 485# Returns a list of all the paren matches in the last regular expression who's 486# matches were saved with _saveLastRegexMatches(). 487sub _getLastRegexMatches { 488 my $self = shift; 489 my $matches = $self->{__lastRegexMatches} || []; 490 return @$matches; 491} 492 493# ArrayRef _setLastRegexMatches(void) 494# 495# Grabs the values of $1, $2, etc. as set by the last regular expression to run 496# in the current dyanamic scope. This of course exploits that $1, $2, etc. and 497# @+ are dynamically scoped. A reference to an array is returned where the 498# array values are $1, $2, $3, etc. _getLastRegexMatches() can also be used to 499# retrieve the values saved by this method. 500sub _setLastRegexMatches { 501 my $self = shift; 502 no strict 'refs'; # For the $$_ symbolic reference below. 503 my @matches = map $$_, (1 .. scalar(@+)-1); # See "perlvar" for @+. 504 $self->{__lastRegexMatches} = \@matches; 505} 506 5071; 508__END__ 509=pod 510 511=head1 NAME 512 513L<REST::Application> - A framework for building RESTful web-applications. 514 515=head1 SYNOPSIS 516 517 # MyRESTApp L<REST::Application> instance / mod_perl handler 518 package MyRESTApp; 519 use Apache; 520 use Apache::Constants qw(:common); 521 522 sub handler { 523 __PACKAGE__->new(request => $r)->run(); 524 return OK; 525 } 526 527 sub getMatchText { return Apache->uri } 528 529 sub setup { 530 my $self = shift; 531 $self->resourceHooks( 532 qr{/rest/parts/(\d+)} => 'get_part', 533 # ... other handlers here ... 534 ); 535 } 536 537 sub get_part { 538 my ($self, $part_num) = @_; 539 # Business logic to retrieve part num 540 } 541 542 # Apache conf 543 <Location /rest> 544 perl-script .cgi 545 PerlHandler MyRESTApp 546 </Location> 547 548=head1 DESCRIPTION 549 550This module acts as a base class for applications which implement a RESTful 551interface. When an HTTP request is received some dispatching logic in 552L<L<REST::Application>> is invoked, calling different handlers based on what the 553kind of HTTP request it was (i.e. GET, PUT, etc) and what resource it was 554trying to access. This module won't ensure that your API is RESTful but 555hopefully it will aid in developing a REST API. 556 557=head1 OVERVIEW 558 559The following list describes the basic way this module is intended to be used. 560It does not capture everything the module can do. 561 562=over 8 563 564=item 1. Subclass 565 566Subclass L<REST::Application>, i.e. C<use base 'REST::Application'>. 567 568=item 2. Overload C<setup()> 569 570Overload the C<setup()> method and set up some resource hooks with the 571C<resourceHooks()> method. Hooks are mappings of the form: 572 573 REGEX => handler 574 575where handler is either a method name, a code reference, an object which 576supports a method with the same name as the HTTP method (or C<getResource> if 577no such method), or a reference to an array of the form: C<[$objectRef, 578"methodName"]> (C<$objectRef> can be a class name instead). 579 580The regular expressions are applied, by default, to the path info of the HTTP 581request. Anything captured by parens in the regex will be passed into the 582handler as arguments. 583 584For example: 585 586 qr{/parts/(\d+)$} => "getPartByNumber", 587 588The above hook will call a method named C<getPartByNumber> on the current 589object (i.e. $self, an instance of L<REST::Application>) if the path info of 590the requested URI matches the above regular expression. The first argument to 591the method will be the part number, since that's the first element captured in 592the regular expression. 593 594=item 3. Write code. 595 596Write the code for the handler specified above. So here we'd define the 597C<getPartByNumber> method. 598 599=item 4. Create a handler/loader. 600 601Create an Apache handler, for example: 602 603 use MyRESTApp; 604 sub handler { 605 my $r = shift; 606 my $app = MyRESTApp->new(request => $r); 607 $app->run(); 608 } 609 610or a small CGI script with the following code: 611 612 #!/usr/bin/perl 613 use MyRESTApp; 614 MyRESTApp->new()->run(); 615 616In the second case, for a CGI script, you'll probably need to do something 617special to get Apache to load up your script unless you give it a .cgi 618extension. It would be unRESTful to allow your script to have a .cgi 619extension, so you should go the extra mile and configure Apache to run your 620script without it. For example, it'd be bad to have your users go to: 621 622 http://www.foo.tld/parts.cgi/12345.html 623 624=item 5. Call the C<run()> method. 625 626When the C<run()> method is called the path info is extracted from the HTTP 627request. The regexes specified in step 2 are processed, in order, and if one 628matches then the handler is called. If the regex had paren. matching then the 629matched elements are passed into the handler. A handler is also passed a copy 630of the L<REST::Application> object instance (except for the case when the 631handler is a method on the L<REST::Application> object, in that case it'd be 632redundant). So, when writing a subroutine handler you'd do: 633 634 sub rest_handler { 635 my ($rest, @capturedArgs) = @_; 636 ... 637 } 638 639=item 6. Return a representation of the resource. 640 641The handler is processed and should return a string or a scalar reference to a 642string. Optionally the handler should set any header information via the 643C<header()> method on instance object pased in. 644 645=head1 CALLING ORDER 646 647The L<REST::Application> base class provides a good number of methods, each of 648which can be overloaded. By default you only need to overload the C<setup()> 649method but you may wish to overload others. To help with this the following 650outline is the calling order of the various methods in the base class. You can 651find detailed descriptions of each method in the METHODS section of this 652document. 653 654If a method is followed by the string NOOP then that means it does nothing by 655default and it exists only to be overloaded. 656 657 new() 658 setup() - NOOP 659 run() 660 preRun() - NOOP 661 loadResource() 662 getMatchText() 663 getPathInfo() 664 query() 665 defaultQueryObject() 666 defaultResourceHandler() - NOOP 667 resourceHooks() 668 checkMatch() 669 _setLastRegexMatches() 670 _getHandlerFromHook() 671 resourceHooks() 672 defaultResourceHandler() - NOOP 673 getRequestMethod() 674 query() 675 defaultQueryObject() 676 bestContentType() 677 simpleContentNegotiation 678 getContentPrefs 679 getAcceptHeader 680 scoreType() 681 callHandler() 682 getHandlerArgs 683 _getLastRegexMatches() 684 extraHandlerArgs() 685 preHandler() - NOOP 686 ... your handler called here ... 687 postHandler() - NOOP 688 postRun() - NOOP 689 getHeaders() 690 headerType() 691 query() 692 defaultQueryObject() 693 header() 694 addRepresentation() 695 696The only methods not called as part of the new() or run() methods are the 697helper methods C<resetHeader()> and C<setRedirect()>, both of which call the 698C<header()> and C<headerType()> methods. 699 700For example, if you wanted to have your code branch on the entire URI of the 701HTTP request rather than just the path info you'd merely overload 702C<getMatchText()> to return the URI rather than the path info. 703 704=back 705 706=head1 METHODS 707 708=head2 new(%args) 709 710This method creates a new L<REST::Application> object and returns it. The 711arguments passed in via C<%args>, if any, are passed untouched to the 712C<setup()> method. 713 714=head2 query([$newCGI]) 715 716This accessor/mutator retrieves the current CGI query object or sets it if one 717is passed in. 718 719=head2 defaultQueryObject([$newCGI]) 720 721This method retrieves/sets the default query object. This method is called if 722C<query()> is called for the first time and no query object has been set yet. 723 724=head2 resourceHooks([%hash]) 725 726This method is used to set the resource hooks. A L<REST::Application> hook is 727a regex to handler mapping. The hooks are passed in as a hash (or a reference 728to one) and the keys are treated as regular expressions while the values are 729treated as handlers should B<PATH_INFO> match the regex that maps to that 730handler. 731 732Handlers can be code references, methods on the current object, methods on 733other objects, or class methods. Also, handlers can be differ based on what 734the B<REQUEST_METHOD> was (e.g. GET, PUT, POST, DELETE, etc). 735 736The handler's types are as follows: 737 738=over 8 739 740=item string 741 742The handler is considered to be a method on the current L<REST::Application> 743instance. 744 745=item code ref 746 747The code ref is considered to be the handler. 748 749=item object ref 750 751The object is considered to have a method the same name as the HTTP method. 752That is, if the object is being called because of GET then C<GET()> is called, 753if it is called because of a C<DELETE> then C<DELETE()> is called. 754C<getResource()> method will be used if C<getRequestMethod()> returns 755false. 756 757=item array ref 758 759The array is expected to be two elements long, the first element is a class 760name or object instance. The 2nd element is a method name on that 761class/instance. IF the 2nd element is ommitted then the method name is assumed 762to be the same as the B<REQUEST_METHOD>, e.g. C<GET()>, C<PUT()>, whatever. 763 764=item hash ref 765 766The current B<REQUEST_METHOD> is used as a key to the hash, the value should be 767one the four above handler types. In this way you can specify different 768handlers for each of the request types. The request method can also be 769specified as '*', in which case that is used if a more specific match is not 770found. 771 772It is possible for the value of the handler to be another hash ref, rather than 773one of the four above types. In this case it is assumed content-negotion is 774wanted. The keys of this second hash are MIME types and the values are one of 775the four above types. For example: 776 777 $self->resourceHooks( 778 qr{/parts/(\d+)} => { 779 GET => { 780 'text/json' => 'get_json', 781 'text/xml', => 'get_xml', 782 'text/xml' => 'get_html', 783 '*/*' => 'get_html', 784 }, 785 '*' => sub { die "Bad Method!" }, 786 } 787 ); 788 789=back 790 791The return value of the handler is expected to be a string, which 792L<REST::Application> will then send to the browser with the 793C<sendRepresentation()> method. 794 795If no argument is supplied to C<resourceHooks()> then the current set of hooks 796is returned. The returned hash referces is a tied IxHash, so the keys are kept 797sorted. 798 799=head2 loadResource([$path]) 800 801This method will take the value of B<PATH_INFO>, iterate through the path 802regex's set in C<resourceHooks()> and if it finds a match call the associated 803handler and return the handler's value, which should be a scalar. If $path is 804passed in then that is used instead of B<PATH_INFO>. 805 806=head2 run() 807 808This method calls C<loadResource()> with no arguments and then takes that 809output and sends it to the remote client. Headers are sent with 810C<sendHeaders()> and the representation is sent with C<sendRepresentation()>. 811 812If the environment variable B<REST_APP_RETURN_ONLY> is set then output isn't 813sent to the client. The return value of this method is the text output it 814sends (or would've sent). 815 816=head2 sendHeaders() 817 818This method returns the headers as a string. 819 820=head2 sendRepresentation($representation) 821 822This method just returns C<$representation>. It is provided soely for 823overloading purposes. 824 825=head2 headerType([$type]) 826 827This accessor/mutator controls the type of header to be returned. This method 828returns one of "header, redirect, or none." If C<$type> is passed in then that 829is used to set the header type. 830 831=head2 header([%args]) 832 833This accessor/mutator controls the header values sent. If called without 834arguments then it simply returns the current header values as a hash, where the 835keys are the header fields and the values are the header field values. 836 837If this method is called multiple times then the values of %args are additive. 838So calling C<$self->header(-type => "text/html")> and C<$self->header(-foo => 839"bar")> results in both the content-type header being set and the "foo" header 840being set. 841 842=head2 resetHeader() 843 844This header causes the current header values to be reset. The previous values 845are returned. 846 847=head2 defaultResourceHandler() 848 849This method is called by C<loadResource()> if no regex in C<resourceHooks()> 850matches the current B<PATH_INFO>. It returns undef by default, it exists for 851overloading. 852 853=head2 bestContentType(@types) 854 855Given a list of MIME types this function returns the best matching type 856considering the Accept header of the current request (as returned by 857C<getAcceptHeader()>. 858 859=head2 simpleContentNegotiation(@types) 860 861Given a list of MIME types this function returns the same list sorted from best 862match to least considering the Accept header as returned by 863C<getAcceptHeader()>. 864 865=head2 getContentPrefs() 866 867Returns the list of MIME types in the Accept header form most preferred to 868least preferred. Quality weights are taken into account. 869 870=head2 getAcceptHeader() 871 872Returns the value of the Accept header as a single string. 873 874=head2 scoreType($type, @accept_types) 875 876Returns an integer, only good for sorting, for where C<$type> fits among the 877C<@accept_types>. This method takes wildcards into account. So C<text/plain> 878matches C<text/*>. The integer returned is the position in C<@accept_types> of 879the matching MIME type. It assumped @accept_types is already sorted from best 880to worst. 881 882=head2 getLastMatchPath() 883 884Returns the last path passed to C<checkMatch()> which successfully matched 885against. Unless you're overloading things in funny ways the value returned 886will be the path that caused the current handler to be invoked. 887 888=head2 getLastMatchPattern() 889 890Similar to C<getLastMatchPath()> except this is the pattern that was applied to 891the path. 892 893=head2 getRequestMethod() 894 895This method tries to be smart and allow tunneling of the other HTTP methods 896over GET or PUT. You can tunnel three ways with the higher up taking 897precedence: 898 8991) Pass an X-HTTP-Method header 9002) Pass the 'http_method' query parameter 9013) Pass a parameter via POST 902 903Only POST and GET, being the most common, can be used to tunnel. In an attempt 904to prevent people from being bad, GET can only be used to tunnel GET or HEAD. 905POST can be used to tunnel anything. 906 907=head1 AUTHORS 908 909Matthew O'Connor E<lt>matthew@canonical.org<gt> 910 911=head1 LICENSE 912 913This program is free software. It is subject to the same license as Perl itself. 914 915=head1 SEE ALSO 916 917L<CGI>, L<CGI::Application>, L<Tie::IxHash>, L<CGI::Application::Dispatch> 918 919=cut 920