[Catalyst] RESTful perl implementations...

John Napiorkowski jjn1056 at yahoo.com
Sun Sep 10 03:56:27 CEST 2006


I'd like something like that for creating my atom
services, or at least to get me started on them. 
Ideally this could be something that could also
generate code I could save and then tweak as well as a
'plug and go' deal.

I think thing project has a couple of pieces I can
see.  Let me put them down and see what you all think

- A way to match actions based on http methods or http
headers.  I mention headers because the google API
supports using POST as PUT if there is a certain
header (which one I forgot).  That way we can make it
easy to dispatch REST style without needing to right
if($c->method eq "POST")... type code everywhere. 
Thise would have the benefit of playing really nice
with the new chaining dispatcher.

- W'd like to automatically inflate/deflate the http
body to make it easy to access. I think
XML::Atom::Server has some good ideas for this and
I've been using bits of that package in my app.  So if
you Atom entry had an iCal as the content body it
should autmatically create an iCal object, and so
forth.

- Another piece would be to have an easy way to use a
CRUD tool to setup the Atom services.  So something
given a table it would auto publish feeds and entries
for this.

- Then we'd like to have an easy way to use the
services in another catalyst application server. 
There's the XML::Feed model that was recently
published to serve as a guide for this I think.

I think a lot of this is already out there in bits and
pieces, particularly the XML::Atom group of modules.

A have an actionclass for the above almost working in
some form.  I'll try to wrap up a workable version of
it for you to try out tonight.

--john

--- Zbigniew Lukasiak <zzbbyy at gmail.com> wrote:

> Hi all,
> 
> Do you think it would fit into InstantCRUD?  I can
> imagine that if you make
> it easily pluggable I could include it into the
> generator.
> 
> --
> Zbyszek
> 
> On 9/9/06, John Napiorkowski <jjn1056 at yahoo.com>
> wrote:
> >
> > I'd like something that would be similar to the
> Google
> > API (Based on Atom) and would also support JSON
> for
> > the feed data.  I also think RPC of some sort is
> > useful for particular method oriented tasks,
> certain
> > things just don't fit well into the REST paradigm
> (in
> > my opinion, but don't want to start a flame war :)
> )
> >
> > I'd be into meeting up on IRC sometime.  I'm in
> the
> > East Coast USA timezone (GMT-5).  What about the
> rest
> > of you?  I can meet up during this coming weekend.
> >
> > --john
> >
> > --- "J. Shirley" <jshirley at gmail.com> wrote:
> >
> > > I'm working on a similar thing, except relying
> > > heavier on JSON-RPC for
> > > certain things, and a mix of RESTful constructs
> for
> > > the rest.
> > >
> > > Maybe an IRC meeting where we can get together
> and
> > > compare notes to
> > > solidify our efforts?
> > >
> > > -J
> > >
> > > On 9/7/06, Garrett Goebel <ggoebel at goebel.ws>
> wrote:
> > > > 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
> >
> > _______________________________________________
> > 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/
> >
> 
> 
> 
> -- 
> Zbigniew Lukasiak
> http://brudnopis.blogspot.com/
> > _______________________________________________
> 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 



More information about the Catalyst mailing list