The story behind a new module

Dave Cross - Dec 9 '20 - - Dev Community

I really like http_this. Whenever I'm working on a static site (or even a semi-static site) 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. 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 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 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 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
Enter fullscreen mode Exit fullscreen mode

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 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 to use my module in place of Plack::App::Directory :-)

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .