[Catalyst] Dispatch matching more than the path?

John Napiorkowski jjn1056 at yahoo.com
Thu Sep 7 15:22:41 CEST 2006


I'm not trying to make something as magical as
InstantCRUD, but I'd like to add some RESTful matching
and convienence to Catalyst actions.  So I'd like to
be able to match on various HTTP method types and
preparse XML type bodies by various modules (XML::Atom
if it's an atom feed, XML::Simple if it's
application/xml, etc.)

My goal is to make it easy to build web services
similar to the Google Data API.

As a side project, but related, I'm working up a
controller to handle different error types, so you can
just say $c->detach('/errors/method_not_allowed') and
have it give a meaningful response.

I've attached something I'm working on (which I am
sure doesn't work yet :) ) to give you the idea of my
direction.  If you think it looks in the same ballpark
as your goal we should followup.

Seems all the cool REST articles are using Python or
Ruby, I'd like to give them a reason to use Perl
instead :)

--john

--- Garrett Goebel <ggoebel at goebel.ws> wrote:

> On Sep 6, 2006, at 3:35 PM, John Napiorkowski wrote:
> 
> > Garrett,
> >
> > Looks like we are working on something similar.  I
> > hadn't noticed your postings about two weeks about
> (I
> > was in the middle of moving from Beijing back to
> the
> > USA and missed about a week of Catalyst postings)
> or I
> > might have saved time asking the same questions
> you
> > asked.
> >
> > I'm actually doing this as an Action class.  Since
> I
> > don't find any additional posts I'm not sure your
> > status.  Want to collaborate?  I am also very
> > interested in REST based services and would enjoy
> > having someone to bounce ideas off of.
> >
> >
> 
> I've just been through something similar. Moving
> back to the USA from  
> Lima, Peru.
> 
> I spent the week following that last post dissecting
> InstantCRUD and  
> rewriting something similar but RESTful for the work
> I've previously  
> mentioned. I had to present something that kinda
> sorta worked on the  
> 28th. Which led to many shortcuts being taken. I'm
> still not happy  
> with where I'm at. But the last week of
> transitioning back to the  
> states and getting the kids into school is settling
> down. Reminder to  
> self... I still need to send a foreign key patch for
>  
> DBIx::Class::Schema::Loader::DBI::SQLite to Brandon.
> 
> I'd be happy to collaborate. I'm fully aware that
> I'm unaware of  
> Catalyst best practices. And like you, I'd love to
> bounce ideas and  
> code around.
> 
> Perhaps you could start by describing your goals and
> your approach in  
> more detail. I still need to convert my hacked
> Catalyst::Action into  
> an class derived from ActionClass. If I get some
> time tomorrow, I'll  
> work that up and post some code.
> 
> cheers,
> 
> Garrett
> 
> 
> > --- Garrett Goebel <ggoebel at goebel.ws> wrote:
> >
> >> On Aug 22, 2006, at 3:49 AM, Matt S Trout wrote:
> >>>> Garrett Goebel wrote:
> >>>>
> >>>> I hacked something into the Path and Regex
> >> dispatchers to get
> >> collective
> >>>> matching on method and path working in the
> >> prototype.
> >>>
> >>> You shouldn't need to hack anything into these;
> >> just use a custom
> >> ActionClass
> >>> that overrides $action->match to introspect onto
> >> the request
> >> method and
> >>> anything else you need (this is already how
> :Args
> >> is handled, see the
> >>> Catalyst::Action source for the implementation).
> >>
> >> Thanks. I'd found the :Args code in
> Catalyst::Action
> >> last night and
> >> managed to shoehorn the request method and path
> >> parameter matching
> >> checks into it. How to subclass or override it
> was
> >> going to be my
> >> next question. I'll check out using a custom
> >> ActionClass.
> >>
> >> Last night I also sub-classed the Request class
> to
> >> add:
> >> __PACKAGE__->mk_accessors(qw/path_parameters
> >> accept_extension/);
> >>
> >> And I'm currently subclassing the Dispatcher to
> >> override
> >> prepare_action in order to:
> >> o  remove uri path parameters from
> $c->request->path
> >> and add to
> >>     $c->request->path_parameters
> >> o  remove "file" extension from last path segment
> >> and add to
> >>     $c->request->accept_extension
> >> o  filter body parameters from using content_type
> >> implied by the
> >>     accept_extension (json, yaml, etc) and add to
> >> $c->request-
> >>> parameters.
> >>     Perhaps I should consider just using the
> >> $c->request->content_type?
> >> o  check POST requests for hidden
> _methodÞLETE|PUT
> >> parameter and
> >> update
> >>     $c->request->method accordingly
> >>
> >> These are all things I want to do once per
> request,
> >> not once per
> >> action. Certainly there are better places to
> perform
> >> some of these
> >> tasks. And I would like to hear any advice on the
> >> best place to
> >> override catalyst for each. In the mean time, at
> >> least I've got a
> >> proof of concept working.
> >>
> >>
> >> My controller now is able to look like:
> >>
> >> # GET http://foo.com/model
> >> # GET http://foo.com/model.json
> >> sub index :GET :Path('') Args(0) {
> >>      my ($self, $c) > >>      my @models > >> UNIVERSAL::can($c->model($_),
> >> 'result_source') }
> >>                   $c->models;
> >>      $self->out($c, \@models);
> >>      1;
> >> }
> >>
> >> # GET http://foo.com/model/Person
> >> sub show :GET :Path('') :Args(1) {
> >>      my ($self, $c, $model) > >>      my @pkcols > >>
> $c->model($model)->result_source->primary_columns;
> >>      my @pk_tuples > >>          { my $tuple > >> $tuple->$_ } @pkcols)) }
> >>          $c->model($model)->search(undef,
> >>                                    {columns  =>
> >> \@pkcols,
> >>                                     distinct =>
> 1,
> >>                                     order_by =>
> >> \@pkcols})
> >>      );
> >>      $self->out($c, \@pk_tuples);
> >>      1;
> >> }
> >>
> >> # GET http://foo.com/model/Person;edit
> >> sub edit :GET :Path('') :PathParam(edit) :Args(1)
> >> {...}
> >>
> >> # GET http://foo.com/model/Person;add
> >> sub add :GET :Path('') :PathParam(add) :Args(1)
> >> {...}
> >>
> >>
> >> # GET http://foo.com/model/Person;column_info
> >> # GET
> http://foo.com/model/Person.yaml;column_info
> >> sub show_column_info :GET :Path('')
> >> :PathParam(column_info) :Args(1) {
> >>      my ($self, $c, $model) > >>      my $rs  > >>      my %column_info > >> $rs->column_info($_)} $rs->columns;
> >>      $self->out($c, \%column_info);
> >>      1;
> >> }
> >>
> >> # POST http://foo.com/model/Person;new
> >> sub create :POST :Path('') :PathParam(new)
> :Args(1)
> >> {...}
> >>
> >> # PUT http://foo.com/model/Person/32
> >> sub update :PUT :Path('') :Args(2) {...}
> >>
> >> # DELETE http://foo.com/model/Person/32
> >> sub destroy :DELETE :Path('') :Args(2) {...}
> >>
> 
> 
> _______________________________________________
> List: Catalyst at lists.rawmode.org
> Listinfo:
> http://lists.rawmode.org/mailman/listinfo/catalyst
> Searchable archive:
>
http://www.mail-archive.com/catalyst@lists.rawmode.org/
> Dev site: http://dev.catalyst.perl.org/
> 

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Rest.pm
Type: application/octet-stream
Size: 2209 bytes
Desc: 3911937034-Rest.pm
Url : http://lists.rawmode.org/pipermail/catalyst/attachments/20060907/04eb4447/attachment.obj 


More information about the Catalyst mailing list