As I promised earlier, attached is a sample ActionClass that seems to work okay to match on HTTP request methods, but will clearly need a lot more. I'd not even a proper CPAN module and has no tests. But it shows the direction I was thinking of taking. I also included a controller that demos it, but you'll need to massage it a bit to work under your application.
I would appreciate your thoughts and criticisms. Thanks! John --- John Napiorkowski <[EMAIL PROTECTED]> wrote: > 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 <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> > > 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" <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> > > 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 <[EMAIL PROTECTED]> > > 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 <[EMAIL PROTECTED]> > > 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, [EMAIL PROTECTED]); > > > > > >>>> 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 > > > > => > > > > > >>>> [EMAIL PROTECTED], > > > > > >>>> > > distinct > > > > => > > > > > >> 1, > > > > > >>>> > > order_by > > > > => > > > > > >>>> [EMAIL PROTECTED]) > > > > > >>>> ); > > > > > >>>> $self->out($c, [EMAIL PROTECTED]); > > > > > >>>> 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: [email protected] > > > > Listinfo: > > > > > > http://lists.rawmode.org/mailman/listinfo/catalyst > > > > Searchable archive: > > > > > > > > > > http://www.mail-archive.com/[email protected]/ > > > > 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: [email protected] > > > Listinfo: > > http://lists.rawmode.org/mailman/listinfo/catalyst > > > Searchable archive: > > > > > > http://www.mail-archive.com/[email protected]/ > > > Dev site: http://dev.catalyst.perl.org/ > > > > > > > > > > > -- > > Zbigniew Lukasiak > > http://brudnopis.blogspot.com/ > > > _______________________________________________ > > List: [email protected] > > Listinfo: > > http://lists.rawmode.org/mailman/listinfo/catalyst > > Searchable archive: > > > http://www.mail-archive.com/[email protected]/ > > 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: [email protected] > Listinfo: > http://lists.rawmode.org/mailman/listinfo/catalyst > Searchable archive: > http://www.mail-archive.com/[email protected]/ > 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: [email protected] Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/[email protected]/ Dev site: http://dev.catalyst.perl.org/
