| Squatting documentation | Contained in the Squatting distribution. |
Squatting::On::Catalyst - embed a Squatting app into a Catalyst app
Add these 4 lines to your Catalyst app's Root Controller to embed a Squatting App.
use App 'On::Catalyst'
App->init;
App->relocate('/somewhere')
sub somewhere : Local { App->catalyze($_[1]) }
The purpose of this module is to allow Squatting apps to be embedded inside
Catalyst apps. This is done by adding a catalyze method to the Squatting
app that knows how to "translate" between Catalyst and Squatting. To use this
module, pass the string 'On::Catalyst' to the use statement that loads
your Squatting app.
This method takes a Catalyst object, and uses the information it contains to let the Squatting app handle one HTTP request. First, it translates the Catalyst::Request object into terms Squatting can understand. Then it lets the Squatting app handle the request. Finally, it takes the Squatting app's output and populates the Catalyst::Response object. When this method is done, the Catalyst object should have everything it needs to send back a complete HTTP response.
NOTE: If you want to communicate something from the Catalyst app to the Squatting app, you can put data in $c->stash or $c->session before calling catalyze(). From inside a Squatting controller, these can be accessed via $self->v and $self->state. Squatting controllers also get access to Catalyst's logging object via $self->log.
In summary:
Catalyst Squatting -------- --------- $c->stash $self->v $c->session $self->state $c->log $self->log
| Squatting documentation | Contained in the Squatting distribution. |
package Squatting::On::Catalyst; use strict; no strict 'refs'; use warnings; # In order to embed a Squatting app into an app written in another framework, # we need to be able to do the following things. # # get incoming CGI parameters # get incoming HTTP request headers # get incoming `-cookies # get incoming HTTP method # set outgoing HTTP status # set outgoing HTTP response headers # set outgoing content my %p; $p{e} = sub { my $cat = shift; my $req = $cat->req; my $uri = $req->uri; my %env; $env{QUERY_STRING} = $uri->query || ''; $env{REQUEST_PATH} = '/' . $req->path; $env{REQUEST_URI} = "$env{REQUEST_PATH}?$env{QUERY_STRING}"; $env{REQUEST_METHOD} = $req->method; my $h = $req->headers; $h->scan(sub{ my ($header, $value) = @_; my $key = uc $header; $key =~ s/-/_/g; $key = "HTTP_$key"; $env{$key} = $value; }); \%env; }; $p{c} = sub { my $cat = shift; my $c = $cat->req->cookies; my %k; $k{$_} = $$c{$_}->value for (keys %$c); \%k; }; # init_cc($controller, $catalyst) -- initialize a controller clone $p{init_cc} = sub { my ($c, $cat) = @_; my $cc = $c->clone; $cc->env = $p{e}->($cat); $cc->cookies = $p{c}->($cat); $cc->input = $cat->req->parameters; $cc->headers = { 'Content-Type' => 'text/html' }; $cc->v = $cat->stash; $cc->state = $cat->session if ($cat->can('session')); $cc->log = $cat->log if ($cat->can('log')); $cc->status = 200; $cc; }; sub catalyze { my ($app, $cat) = @_; my ($c, $p) = &{ $app . "::D" }('/'.$cat->request->path); my $cc = $p{init_cc}->($c, $cat); my $content = $app->service($cc, @$p); my $h = $cat->response->headers; my $ch = $cc->headers; for (keys %$ch) { $h->header($_ => $ch->{$_}); } $cat->response->status($cc->status); $cat->response->body($content); } 1;
# Local Variables: *** # mode: cperl *** # indent-tabs-mode: nil *** # cperl-close-paren-offset: -2 *** # cperl-continued-statement-offset: 2 *** # cperl-indent-level: 2 *** # cperl-indent-parens-as-block: t *** # cperl-tab-always-indent: nil *** # End: *** # vim:tabstop=8 softtabstop=2 shiftwidth=2 shiftround expandtab