Perl/Plack Middleware for Emulating An Apache HTTP Server
One of the greatest strengths of the Perl ecosystem is Plack. It provides a super-flexible interface between web servers and Perl web applications. Because of its middleware architecture, it is incredibly easy to compose complex behaviors by snapping together small, focused modules.
Recently, I wanted to create a local testing environment for websites that are normally deployed on the Apache HTTP Server. While there are already some nice plack-based local web servers, I had a laundry list of my own requirements, and nothing quite fit the bill.
In order to solve two of my issues, I created and released two new Plack middleware modules to CPAN.
Plack::Middleware::DirIndex::Htaccess
In a standard Apache setup, developers often define default pages other than index.html using the DirectoryIndex directive inside a .htaccess file:
$ less gallery/.htaccess
DirectoryIndex gallery.html
This module is an extension of Plack::Middleware::DirIndex. But first it checks for an .htaccess file and, if it has a DirectoryIndex directive, serve that file as the default. Otherwise, it will serve the global default page if present, which by default is index.html.
Plack::Middleware::DirListing
When a directory doesn’t have a default index page, the web server usually generates a file listing. There are Plack implementations for this, including Plack::App::Directory and Plack::App::DirectoryIndex. But these act as standalone apps, and I wanted a middleware solution that would only generate a directory listing and not serve any other files.
If the request is a directory, Plack::Middleware::DirListing
generates a rich, HTML-formatted listing of the directory contents, complete with last modified dates, file sizes, and file types. It also includes sorting functionality (by name, date, etc.).
Example Static Site Web Server Implementation
By combining these two modules, you can build a app.psgi that effectively emulates an Apache server for static sites. This example also includes Plack::Middleware::SSI as I (still) occasionally use server-side includes. For directories, it checks for a directory index file first first and falls back to a directory listing if none are found. Otherwise, it serves static files if requested.
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use Plack::Builder;
use Plack::Request;
my $app = sub {
my $env = shift;
my $req = Plack::Request->new( $env );
my $root = '.';
my $status = '200';
my $response = 'OK';
if (! -e "$root$env->{ PATH_INFO }") {
$status = '404';
$response = 'Not found';
}
return [
$status,
[ 'Content-Type' => 'text/html; charset=utf-8' ],
[ $response ]
];
};
builder {
enable 'SSI';
enable 'TrailingSlash', ignore => [ '.htaccess' ];
enable 'DirIndex::Htaccess';
enable 'DirListing';
enable 'Static', path => qr/(css|eot|gif|heic|html|ico|jpe?g|js(?:on)?|pdf|png|svg|swf|txt|ttf|webp|woff2?|xml)/, root => '.';
$app;
}
Available on CPAN
These modules are available now. If you are looking to mirror your Apache environment locally using the power of Perl, give them a try:
Plack::Middleware::DirIndex::Htaccess Plack::Middleware::DirListing
