[Catalyst] Converting a GET request to a POST request

Ronald J Kimball rkimball at pangeamedia.com
Mon Nov 22 17:44:37 GMT 2010


I want to convert a GET request to a POST request, inside my Catalyst
app, before dispatching happens.  For example, I want to take a
request like:

GET /foo?method=POST&body={"foo":1}&content-type=text/javascript

and convert it into a request like this:

POST /foo
Content-Type: text/javascript

{"foo":1}


Background: I'm implementing a REST API using
Catalyst::Controller::REST.  The API will be accessed via Ajax running
on third party websites, using JSONP to get around the same-origin
policy.  Unfortunately, JSONP can only make GET requests.  So, I want
to take that GET request and turn it into a POST before
Catalyst::Action::Deserialize does its magic.


This is as far as I've gotten, in my app's base class:

around 'prepare' => sub {
  my $orig  = shift;
  my $class = shift;

  my $c = $class->$orig(@_);

  if ($c->req->method eq 'GET' && $c->req->param('method') &&
      $c->req->param('content-type')) {
    my $type = $c->req->param('content-type');
    my $body = $c->req->param('body');

    $c->req->method(scalar $c->req->param('method'));
    $c->req->content_type($type);
    $c->req->_body(HTTP::Body->new($type, length $body));
    $c->req->_body->add($body);
  }

  return $c;
};

This works for JSON requests (e.g. application/json), but not for
JSONP requests (e.g. text/javascript), because there is no
Catalyst::Action::Deserialize::JSONP.  I guess I could create one that
extends Catalyst::Action::Deserialize::JSON...

Even then, this solution has some drawbacks: it covers every request,
not just those for the relevant controller/actions; it probably leaves
the request object's attributes in an inconsistent state; and it makes
me feel really dirty.

Is there a better way to modify the request, or a better way to solve
my general problem in the first place?

thanks,
Ronald



More information about the Catalyst mailing list