Merge
Tomas Doran (t0m) [Sat, 25 Jul 2009 10:21:29 +0000 (11:21 +0100)]
1  2 
lib/Catalyst/Action/REST.pm
lib/Catalyst/Request/REST.pm
lib/Catalyst/RequestRole/REST.pm

@@@ -3,25 -3,29 +3,21 @@@
  # Created by: Adam Jacob, Marchex, <adam@hjksolutions.com>
  # Created on: 10/12/2006 03:00:32 PM PDT
  #
--# $Id$
  
  package Catalyst::Action::REST;
--
--use strict;
--use warnings;
--
--use base 'Catalyst::Action';
++use Moose;
  use Class::Inspector;
 -use Catalyst::Request::REST;
 +use Moose::Util qw(does_role);
- use Catalyst;
 +use Catalyst::RequestRole::REST;
  use Catalyst::Controller::REST;
 +use namespace::clean -except => 'meta';
 +
++extends 'Catalyst::Action';
  BEGIN { require 5.008001; }
  
- our $VERSION = '0.73';
+ our $VERSION = '0.74';
  
 -sub new {
 -  my $class  = shift;
 -  my $config = shift;
 -  Catalyst::Request::REST->_insert_self_into( $config->{class} );
 -  return $class->next::method($config, @_);
 -}
 -
  =head1 NAME
  
  Catalyst::Action::REST - Automated REST Method Dispatching
@@@ -3,18 -3,18 +3,13 @@@
  # Created by: Adam Jacob, Marchex, <adam@hjksolutions.com>
  # Created on: 10/13/2006 03:54:33 PM PDT
  #
--# $Id: $
  
  package Catalyst::Request::REST;
--
--use strict;
--use warnings;
 -use Scalar::Util qw/blessed/;
 -
 -use base qw/Catalyst::Request Class::Accessor::Fast/;
 +use Moose;
 +extends qw/Catalyst::Request/;
 +with qw/Catalyst::RequestRole::REST Catalyst::RequestRole::Deserialize/;
  
  use Catalyst::Utils;
 -use HTTP::Headers::Util qw(split_header_words);
  
  sub _insert_self_into {
    my ($class, $app_class ) = @_;
index c46a7c7,0000000..707e5e1
mode 100644,000000..100644
--- /dev/null
@@@ -1,140 -1,0 +1,140 @@@
 +package Catalyst::RequestRole::REST;
 +# ABSTRACT: A REST-y role for Catalyst::Request
 +use Moose::Role;
 +
 +use Catalyst::Utils;
 +use HTTP::Headers::Util qw(split_header_words);
 +use namespace::clean -except => 'meta';
 +
 +has accept_only => (
-   is      => 'ro',
++  is      => 'rw',
 +  isa     => 'Bool',
-   writer  => '_set_accept_only',
++#  writer  => '_set_accept_only', FIXME fails for me if I use this
 +  default => 0,
 +);
 +
 +has accepted_content_types => (
 +  is         => 'ro',
 +  isa        => 'ArrayRef',
 +  init_arg   => undef,
 +  lazy_build => 1,
 +);
 +
 +has _accepted_content_types_hash => (
 +  is         => 'ro',
 +  isa        => 'HashRef',
 +  init_arg   => undef,
 +  lazy_build => 1,
 +);
 +
 +sub _build_accepted_content_types {
 +  my $self = shift;
 +  my %types;
 +
 +  # First, we use the content type in the HTTP Request.  It wins all.
 +  $types{ $self->content_type } = 3 if $self->content_type;
 +
 +  if ($self->method eq "GET" &&
 +    (my $ct = $self->params->{'content-type'})) {
 +    $types{ $ct } = 2;
 +  }
 +
 +  # Third, we parse the Accept header, and see if the client
 +  # takes a format we understand.
 +  #
 +  # This is taken from chansen's Apache2::UploadProgress.
 +  if ( $self->header('Accept') ) {
-     $self->_set_accept_only(1) unless keys %types;
++    $self->accept_only(1) unless keys %types; # FIXME fails if _set_accept_only
 +
 +    my $accept_header = $self->header('Accept');
 +    my $counter       = 0;
 +
 +    foreach my $pair ( split_header_words($accept_header) ) {
 +      my ( $type, $qvalue ) = @{$pair}[ 0, 3 ];
 +      next if $types{$type};
 +
 +      unless ( defined $qvalue ) {
 +        $qvalue = 1 - ( ++$counter / 1000 );
 +      }
 +
 +      $types{$type} = sprintf( '%.3f', $qvalue );
 +    }
 +  }
 +
 +  return [ sort { $types{$b} <=> $types{$a} } keys %types ];
 +}
 +
 +sub preferred_content_type { $_[0]->accepted_content_types->[0] }
 +
 +sub _build__accepted_content_types_hash {
 +  return { map {; $_ => 1 } @{ $_[0]->accepted_content_types } };
 +}
 +
 +sub accepts { $_[0]->_accepted_content_types_hash->{$_[1]} }
 +
 +1;
 +
 +__END__
 +
 +=head1 SYNOPSIS
 +
 +     if ( $c->request->accepts('application/json') ) {
 +         ...
 +     }
 +
 +     my $types = $c->request->accepted_content_types();
 +
 +=head1 DESCRIPTION
 +
 +This is a subclass of C<Catalyst::Request> that adds a few methods to
 +the request object to faciliate writing REST-y code. Currently, these
 +methods are all related to the content types accepted by the client.
 +
 +Note that if you have a custom request class in your application, and it does
 +not inherit from C<Catalyst::Request::REST>, your application will fail with an
 +error indicating a conflict the first time it tries to use
 +C<Catalyst::Request::REST>'s functionality.  To fix this error, make sure your
 +custom request class inherits from C<Catalyst::Request::REST>.
 +
 +=method accepted_content_types
 +
 +Returns an array reference of content types accepted by the
 +client.
 +
 +The list of types is created by looking at the following sources:
 +
 +=over 4
 +
 +=item * Content-type header
 +
 +If this exists, this will always be the first type in the list.
 +
 +=item * content-type parameter
 +
 +If the request is a GET request and there is a "content-type"
 +parameter in the query string, this will come before any types in the
 +Accept header.
 +
 +=item * Accept header
 +
 +This will be parsed and the types found will be ordered by the
 +relative quality specified for each type.
 +
 +=back
 +
 +If a type appears in more than one of these places, it is ordered based on
 +where it is first found.
 +
 +=method preferred_content_type
 +
 +This returns the first content type found. It is shorthand for:
 +
 +  $request->accepted_content_types->[0]
 +
 +=method accepts
 +
 +Given a content type, this returns true if the type is accepted.
 +
 +Note that this does not do any wildcard expansion of types.
 +
 +=cut