[Catalyst] RESTful perl implementations...

Garrett Goebel ggoebel at goebel.ws
Fri Sep 8 06:56:25 CEST 2006


My apologies. I haven't made the time yet to fix my code to use an  
ActionClass. And it doesn't look like I'll have a chance to work on  
things again until this weekend at the earliest.

In the mean time, you might consider checking out the  
Jifty::Plugin::REST::Dispatcher in the svn repository (http:// 
svn.jifty.org/svn/jifty.org) and the slides from the following  
presentation: http://pugs.blogs.com/talks/oscon-rhox.pdf.

cheers,

Garrett


On Sep 7, 2006, at 8:22 AM, John Napiorkowski wrote:

> 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=DELETE|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 = grep {
>>>> 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 = map(
>>>>          { my $tuple = $_; csv_encode(map({
>>>> $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  = $c->model($model)->result_source;
>>>>      my %column_info = map { $_ =>
>>>> $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
> <Rest.pm>
> _______________________________________________
> List: Catalyst at lists.rawmode.org
> Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
> Searchable archive: http://www.mail-archive.com/ 
> catalyst at lists.rawmode.org/
> Dev site: http://dev.catalyst.perl.org/




More information about the Catalyst mailing list