Serving a Local Directory with Plack


One of my small projects (10 Years Later, Only 250 SLOC) is a mostly static website generated by some backend programs. (Some of the UI is JavaScript, but it's all data-driven.)

I've spent plenty of time tweaking the page generation, and as such I need to know how things look after running through all of the data-driven templates. While I could deploy to a live web server after running the "Regenerate the desired pages" program, I pulled out the Plack hammer.

Remember how stupidly simple Plack is? A Plack application is just a function. Plack comes with some demonstration applications which are a page or two of code apiece—including the almost exactly right Plack::App::File. You can even run it as a Plack one-liner.

I wanted something a little more: a program I could run with a single argument, the name of the directory root from which to serve files. Something like:

$ plackfile .
$ plackfile root/static/

... would do. This took only a few lines of code:

#!/usr/bin/env perl

use Plack::Runner;

my $app    = Plack::App::IndexFile->new({ root => shift })->to_app;
my $runner = Plack::Runner->new;
$runner->parse_options( '--access-log' => '/dev/null', @ARGV );
$runner->run( $app );

package Plack::App::IndexFile;

use parent 'Plack::App::File';

sub locate_file
    my ($self, $env) = @_;
    my $path         = $env->{PATH_INFO} || '';

    return $self->SUPER::locate_file( $env ) unless $path && $path =~ m{/$};
    $env->{PATH_INFO} .= 'index.html';
    return $self->SUPER::locate_file( $env );

Plack::Runner is the module at the core of plackup, and Plack::App::File is a Plack core application which serves static files beneath a root directory.

Unfortunately, Plack::App::File doesn't default to index.html when the user requests a directory, so I had to override its locate_file() method to add this behavior. It's a touch fragile, as a better approach would be to let P::A::F take an extra optional coderef constructor parameter to use as a last resort when the user has requested a directory. Still, this works.

The only other interesting part of this code is the argument handling. Plack::Runner takes the same arguments as the plackup file, but this code defaults to redirecting the access log normally printed to STDOUT to /dev/null. This is quieter, which matches my normal purposes, but it's overrideable if necessary.

Two minutes of work on my part (plus 10 writing this post) will save me a tremendous amount of time. Hopefully it will do the same for you.


This is really nifty and i can't remember how often i hacked together something stupid for such a purpose.

Two things to note:

The Plack::App::File link is broken.

Are you intending to submit a pull req to Plack::App::File? :)

Looks like you've re-implemented weborf in Plack :)

Very fun and useful!

I played with Plack::File::Directory too, making a fake cherokee static file server in front of it.

It looks better than the original, and is definitely more perlish ;-) .

Modern Perl: The Book

cover image for Modern Perl: the book

The best Perl Programmers read Modern Perl: The Book.

affiliated with Modern Perl Whitepapers



About this Entry

This page contains a single entry by chromatic published on August 24, 2011 6:15 PM.

No Policy Can Save Wrong Code was the previous entry in this blog.

Why My Side Project Doesn't Use Perl 6 is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Sponsored by Make a Smoothie guide and the Trendshare how to invest guide

Powered by the Perl programming language

what is programming?