[Catalyst] How to de-serialize json?

2010-01-23 Thread Bill Moseley
Following up on our recent simulating discussion on adding an API to an
application, I wonder is someone can help me understand something:

Catalyst uses HTTP::Body to parse body content.  It currently handles these
request content types:

our $TYPES = {
'application/octet-stream'  = 'HTTP::Body::OctetStream',
'application/x-www-form-urlencoded' = 'HTTP::Body::UrlEncoded',
'multipart/form-data'   = 'HTTP::Body::MultiPart',
'multipart/related' = 'HTTP::Body::XFormsMultipart',
'application/xml'   = 'HTTP::Body::XForms'
};

But, Catalyst::Controller::DBIC::API and Catalyst::Controller::Rest both use
Catalyst::Action::Deserialize.

My question is this:  why use an action class instead of extending
HTTP::Body to deserialize the content?  Isn't it HTTP::Body's job to decode
the body based on the content-type of the request?

I'm just wondering if I'm missing some important reason why these other
request content types are handled differently.

Seems like HTTP::Body is the correct place to do all decoding.  Decoded
JSON, for example, would just end up in $c-req-params and controllers
could be oblivious to the encoding of the request (similar to how we don't
really care how params are decoded if the body is x-www-form-urlencoded or
form-data).   True, could end up with a request parameter that is a hashref,
but I don't see anything wrong with that as long as parameters are validated
correctly.

So, why different approaches to decoding request body content?



-- 
Bill Moseley
mose...@hank.org
___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] How to de-serialize json?

2010-01-23 Thread J. Shirley
On Sat, Jan 23, 2010 at 10:16 AM, Bill Moseley mose...@hank.org wrote:
 Following up on our recent simulating discussion on adding an API to an
 application, I wonder is someone can help me understand something:

 Catalyst uses HTTP::Body to parse body content.  It currently handles these
 request content types:

 our $TYPES = {
     'application/octet-stream'  = 'HTTP::Body::OctetStream',
     'application/x-www-form-urlencoded' = 'HTTP::Body::UrlEncoded',
     'multipart/form-data'   = 'HTTP::Body::MultiPart',
     'multipart/related' = 'HTTP::Body::XFormsMultipart',
     'application/xml'   = 'HTTP::Body::XForms'
 };

 But, Catalyst::Controller::DBIC::API and Catalyst::Controller::Rest both use
 Catalyst::Action::Deserialize.

 My question is this:  why use an action class instead of extending
 HTTP::Body to deserialize the content?  Isn't it HTTP::Body's job to decode
 the body based on the content-type of the request?

 I'm just wondering if I'm missing some important reason why these other
 request content types are handled differently.

 Seems like HTTP::Body is the correct place to do all decoding.  Decoded
 JSON, for example, would just end up in $c-req-params and controllers
 could be oblivious to the encoding of the request (similar to how we don't
 really care how params are decoded if the body is x-www-form-urlencoded or
 form-data).   True, could end up with a request parameter that is a hashref,
 but I don't see anything wrong with that as long as parameters are validated
 correctly.

 So, why different approaches to decoding request body content?



Well, I never really equated deserialization to decoding, so my answer
may not be fully satisfactory.

If I assume that decoding is synonymous with de-serialization, it
makes more sense.  At first thought, I just don't think they're that
similar, though.  Maybe in implementations (comparing JSON to HTTP
POST parameters) it is, but in the case of HTTP::Body decoding a
mime64-encoded JPEG, it isn't at all.

From a behavior standpoint, having a POST/PUT'd JSON segment that ends
up in -params would be maddening to me.  They aren't parameters, not
even in the loosest of the RFC interpretations.

I can appreciate wanting to increase the reusability, and having a
deserialization component in HTTP::Body (which, in turn could be used
for Form, etc).

If HTTP::Body could support this, Catalyst::Action::REST wouldn't be
tremendously different, it has the Deserialize action so you can
specify arbitrary deserialization schemes (after the body is decoded).
 You'd still need this behavior, still have the action.

Not a bad idea, those are my thoughts on it... and to summarize in one
sentence: it does seem like a good idea that could end up with a lot
of hacking and not a lot of practical savings.

-J

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] How to de-serialize json?

2010-01-23 Thread Bill Moseley
On Sat, Jan 23, 2010 at 1:40 PM, J. Shirley jshir...@gmail.com wrote:



 If I assume that decoding is synonymous with de-serialization, it
 makes more sense.  At first thought, I just don't think they're that
 similar, though.  Maybe in implementations (comparing JSON to HTTP
 POST parameters) it is, but in the case of HTTP::Body decoding a
 mime64-encoded JPEG, it isn't at all.



With a jpeg I assume the content type would be form-data (that included an
upload in the form) where the file ends up in $req-uploads, not as a
request parameter.

I find decoding requests analogous to Views.  In my apps controllers take
input (params, arguments and uploads) and the result is data in the stash.
 Then the View has the job of serializing (normally to HTML via template,
but no reason it can't be JSON or anything else).  In fact I have many
controller actions that are used for both normal full-page HTTP requests and
AJAX requests.  So, similar to how the controller action does not know or
care what view is going to be used, the controller action doesn't know or
care how the request is serialized over the wire.  That's how I picture it.




 From a behavior standpoint, having a POST/PUT'd JSON segment that ends
 up in -params would be maddening to me.  They aren't parameters, not
 even in the loosest of the RFC interpretations.


I'm trying to understand that point of view.  Why is that maddening?  If you
have a request serialized as json then $req-parameters would go unused and
instead have the deserialzed request end up some place else, say as
$req-data?

I have an XMLRPC API to an application.  I implemented it by creating an
HTTP::Body subclass that parses the XMLRPC XML body.  The method ends up
mapped to an action, the params ends up as body parameters, and base64
elements end up as uploads.  As a result existing controller actions can be
used for both XMLRPC request and for normal web requests.  All I have to do
to expose the action in the API is add  XMLRPC( $method_name ) as a action
attribute.

Catalyst::Engine hard-codes HTTP::Body.  I think it would be more flexible
if the body parser class could be a config option (to allow easy
sub-classing), -- similar to how the request class can be defined -- but
it's not that difficult to set up now.   Just have to add the content type
to  %HTTP::Body::TYPES.

Thanks for your comments, I appreciate the feedback.


-- 
Bill Moseley
mose...@hank.org
___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] How to de-serialize json?

2010-01-23 Thread Hans Dieter Pearcey
Excerpts from Bill Moseley's message of Sat Jan 23 19:45:28 -0500 2010:
 On Sat, Jan 23, 2010 at 1:40 PM, J. Shirley jshir...@gmail.com wrote:
 
 
 
  If I assume that decoding is synonymous with de-serialization, it
  makes more sense.  At first thought, I just don't think they're that
  similar, though.  Maybe in implementations (comparing JSON to HTTP
  POST parameters) it is, but in the case of HTTP::Body decoding a
  mime64-encoded JPEG, it isn't at all.
 
 
 
 With a jpeg I assume the content type would be form-data (that included an
 upload in the form) where the file ends up in $req-uploads, not as a
 request parameter.

That assumption may hold true for *your* applications, but he didn't say
anything about a form or even a web browser.  It's perfectly reasonable,
especially in the context of REST APIs, to talk about non-form-based request
bodies.  (I've written actions that accepted PUT requests with a content-type
of application/vnd.ms-excel, for example.)

hdp.

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] How to de-serialize json?

2010-01-23 Thread Bill Moseley
On Sat, Jan 23, 2010 at 5:39 PM, Hans Dieter Pearcey 
hdp.perl.catalyst.us...@weftsoar.net wrote:

 Excerpts from Bill Moseley's message of Sat Jan 23 19:45:28 -0500 2010:

  With a jpeg I assume the content type would be form-data (that included
 an
  upload in the form) where the file ends up in $req-uploads, not as a
  request parameter.

 That assumption may hold true for *your* applications, but he didn't say
 anything about a form or even a web browser.  It's perfectly reasonable,
 especially in the context of REST APIs, to talk about non-form-based
 request
 bodies.  (I've written actions that accepted PUT requests with a
 content-type
 of application/vnd.ms-excel, for example.)


But, that's a different content type.  I assumed form-data.  So, in this
case in my HTTP::Body deserialization layer approach, I'd thus add:

   $HTTP::Body::Types('application/vnd.ms-excel') = 'My::ExcelParser';

which would result in $req-uploads having an upload object for the
spreadsheet.  My::ExcelParser would probably be a thin sub-class of
something like My::Upload.  Then the same controller would work with both a
web request with an upload field or this REST request and expect to find the
upload object in $req-uploads.



-- 
Bill Moseley
mose...@hank.org
___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] How to de-serialize json?

2010-01-23 Thread Hans Dieter Pearcey
Excerpts from Bill Moseley's message of Sat Jan 23 21:47:00 -0500 2010:
 On Sat, Jan 23, 2010 at 5:39 PM, Hans Dieter Pearcey 
 hdp.perl.catalyst.us...@weftsoar.net wrote:
 
  Excerpts from Bill Moseley's message of Sat Jan 23 19:45:28 -0500 2010:
 
   With a jpeg I assume the content type would be form-data (that included
  an
   upload in the form) where the file ends up in $req-uploads, not as a
   request parameter.
 
  That assumption may hold true for *your* applications, but he didn't say
 
 But, that's a different content type.  I assumed form-data.  So, in this

You said: What about extending HTTP::Body, e.g. to decode JSON into body_params?

jshirley said: Ugh.  Also, what about (non-param-like) things like jpegs?

You said: Well, they'd be file uploads.

I said: You might like that, but you can't assume everyone would, and the
  request might not even have a form content-type.

You said: Well, they'd be file uploads.

Me, writing this message: ???

As far as I can tell, you missed the point of my message, which makes me wonder
if I've missed the point of yours.  Are you talking about a set of conventions
you'd like to be able to build for your own use on top of HTTP::Body, or a set
of conventions that you expect everyone will want and so should be built into
HTTP::Body, or something else entirely?

hdp.

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/