Meddling with Middlewares

Plack provides a useful component called a Middleware, which wraps applications with functionality.

You can use them to your advantage to tack on additional features and improvements to your application.

Middleware usage

Adding middlewares can be breeze using the Plack::Builder syntax:

use MyApp;
use Plack::Builder;

builder {
    enable 'Auth::Basic', authenticator => sub {
        my ( $user, $pass, $env ) = @_;
        # test $user and $pass somehow
    };

    MyApp->to_app;
};

Since to_app returns an app, you can use it as the last statement to builder. In this example we add Plack::Middleware::Auth::Basic middleware to our new application stack.

We can add more:

builder {
    enable 'Auth::Basic', authenticator => sub { ... };

    enable 'Rewrite', rules => sub {
        return 301
            if s{^/foo/?$}{/bar/}
            or s{^/baz/?$}{/quux/};

        ...
    };

    MyApp->to_app;
};

Now having Plack::Middleware::Rewrite as well. Having it before Auth::Basic will assure the rewrites will happen first. Having it after Auth::Basic will assure authentication will happen first.

Multiple Dancer applications

As explained in our to_app article, you can set up multiple Dancer2 applications using the same syntax:

use MyApp;
use MyApp::Admin;
use Plack::Builder;

builder {
    mount '/'      => MyApp->to_app;
    mount '/admin' => MyApp::Admin->to_app;
};

We can still add middlewares to that stack:

builder {
    enable 'Rewrite', rules => sub {
        ...
    };

    mount '/'      => MyApp->to_app;
    mount '/admin' => MyApp::Admin->to_app;
};

Not bad, but there's one more situation to cover.

Going nuts

Let's take a look at another situation: adding authentication using a middleware:

builder {
    enable 'Auth::Basic', authenticator => sub { ... };

    mount '/'      => MyApp->to_app;
    mount '/admin' => MyApp::Admin->to_app;
};

But wait. This doesn't make sense. We want to only enable authentication for the admin application. This will set it up to both of them.

Since the Dancer application is a callback, and builder wraps callbacks by providing another callback... you might see where this is heading:

builder {
    mount '/'      => MyApp->to_app;
    mount '/admin' => builder {
        enable 'Auth::Basic', authenticator => sub { ... };

        MyApp::Admin->to_app;
    };
};

Pretty cool, huh? Very!

Conclusion

Middlewares are awesome and very easy to integrate with Dancer. In fact, we use middlewares internally in Dancer2, which you will read about in the next article.

Author

This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.

Copyright

No copyright retained. Enjoy.

2014 // Sawyer X <xsawyerx@cpan.org>