The story behind a new module
Tags: perl, plack, directory
Published: 2020-12-09 18:04:00

---
title: The story behind a new module
published: true
description: In which I explain why and how I wrote Plack::App::DirectoryIndex
tags: perl, plack, directory
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/1t02vuaxb0ikmmoq9fs6.png
---

I really like [`http_this`](https://metacpan.org/pod/http_this). Whenever I'm working on a static site (or even [a semi-static site](https://dev.to/davorg/github-actions-for-semi-static-web-sites-597g)) and I want to check how it looks, I can run a simple command-line program and have a local web server serving my site. And I don't have to worry about relative or absolute URLs - everything just works.

Well, almost everything. There's one bit of `http_this` that always annoys me. It doesn't support `index.html`. If I request a directory that includes an `index.html` file, then I'd expect to see that file served to me, but instead, I get a directory listing. If I choose `index.html` from that list, then everything works as expected. But it's an annoying extra step.

Recently, I'd had enough of this problem and I decided to do something about it.

Digging into the code of `http_this`, I soon discovered that it was really just a thin layer over the standard Plack application [Plack::App::Directory](https://metacpan.org/pod/Plack::App::Directory). And I like Plack applications. They have a nice modular architecture that makes them easy to hack on.

In my experience, the first thing to do when trying to find a solution to a Plack problem is to find a piece of middleware that addresses your problem. And, sure enough, there was [Plack::Middleware::DirIndex](https://metacpan.org/pod/Plack::Middleware::DirIndex) which says that it does this:

> If `$env->{PATH_INFO}` ends with a '/' then we will append the dir_index value to it (defaults to index.html)

And that sounds like exactly what we want. So I quickly hacked a solution using this into App::HTTPThis (the module that actually drives `http_this`). It took about five minutes.

But on testing it, I realised there was a problem. Look at its description again. For any request where the path ends with a `/`, the middleware will add the index filename to the request. And that's subtly different to what we want (actually, I think it's subtly different to what anyone wants). If you send a request to a web server to view a directory (i.e. one where the path ends with '/') there are two things that might happen:

* If there is an `index.html` file in the directory, then you want to see the contents of that file
* If there is no `index.html` file,  then you want to see a directory listing

The current behaviour of `http_this` is to always return a directory listing. Adding in Plack::Middleware::DirIndex means it will always look for `index.html`. And if there is no `index.html`, then you'll get a 404. I don't think that's very useful.

So I moved on. (I've just gone back and [proposed a patch](https://github.com/ranguard/plack-middleware-dirindex/pull/4) that gives the behaviour I want.)

Next, I looked at Plack::App::Directory itself. That is the module which provides the directory listing that `http_this` uses. What if I could add support for a directory index file to that module?

That actually proved to be pretty simple. In half an hour or so, I had sent [a pull request](https://github.com/plack/Plack/pull/654) that added support for an (optional) `dir_index` parameter. Without my new parameter, the module's behaviour is unchanged. But with it, the behaviour would be:

    IF we have a request for a directory
      AND we have a dir_index configured
      AND there is a dir_index file in the directory
      THEN serve the dir_index file
    ELSE serve a directory listing

I think it's a reasonable patch, but it hasn't been addressed by the author yet. I got one comment from someone else, suggesting that I used Plack::Middleware::DirIndex - but I've already explained why I don't think that's a good solution.

I guess I should wait to see if my patch is accepted into Plack::App::Directory, but it has been three weeks and I confess to being rather impatient.

So I've ended up writing my own module. It's called [Plack::App::DirectoryIndex](https://metacpan.org/pod/Plack::App::DirectoryIndex) and it's on CPAN now. It works exactly how I'd like it too, supporting both the situation where an `index.html` exists and the one where it doesn't. Perhaps you'll find it useful. Please let me know if you do (or if you find any bugs in it).

Now, I just need to [persuade the author of `http_this`](https://github.com/melo/app-htttpthis/pull/4) to use my module in place of Plack::App::Directory :-)