PSGI Environment Utilities

Overview

Help to properly localize your $PSGI env

Introduction

We added a feature to Catalyst that allows you to use the response of another Plack type application as your main response. In order to take better advantage of this new feature we added some utility helpers that lets you localize the $env under the current controller or action.

Example

Here's a simple example that uses the bundled Plack static file appliaction to serve files under a Catalyst controller;

    package MyApp::Controller::Static;

    use base 'Catalyst::Controller';
    use Plack::App::File;

    my $app = Plack::App::File->new(root => "static")->to_app;

    sub serve :Path('') Args {
      my ( $self, $c) = @_;
      my $env = $c->req->env;
      $c->res->from_psgi_response($app->($env));
    }

    1;

Discussion

This would not work as expected since the $env) passed to the File serving application will have "/static/@args" (like /static/favicon.ico, /static/js/app.js) as its PATH info. This means that your directory structure would need to be like "./static/static/favicon.ico" or "./static/static/js/apps.js". It is likely you would prefer and expect this to work similiarly to how Plack::Builder's 'mount' works. This 'localizes' the $env such as to make the underlying application think the mounted path is the root path or in other words instead of /static/static/favicon.ico you have /static/favicon.ico.

For these cases Catalyst now bundles three utility functions to localize the $env under the controller namespace, the action namespace or the current path. Of the three localizing under the action namespace is the one you are most likely to use since it most closely resembles how Plack::Builder's mount works. Lests rewrite the above.

    package MyApp::Controller::Static;

    use base 'Catalyst::Controller';
    use Plack::App::File;
    use Catalyst::Utils;

    my $app = Plack::App::File->new(root => "static")->to_app;

    sub serve :Path('') Args {
      my ( $self, $c) = @_;
      my $env = $c->Catalyst::Utils::env_at_action;
      $c->res->from_psgi_response($app->($env));
    }

    1;

and lets assume you have a directory structure like this:

    /$ROOT
      /lib
      /t
      /static
        /js
          app.js
          jquery.js
        /css
          main.css
          locale.css
        favicon.ico

Now when you GET localhost://static/js/app.js this will service the file located at $ROOT/static/js/app.js

See https://metacpan.org/pod/Catalyst::Utils#PSGI-Helpers for more.

Alternatives include Catalyst::Action::FromPSGI and CatalystX::Controller::PSGI.

More Information

You should review Plack::Middleware::HTTPExceptions for more details.

Author

John Napiorkowski jjnapiork@cpan.org