A quick static file webserver

Wow, I’ve been busy lately! This is just a quick note.

Have you ever needed a quick webserver? Just static files, nothing fancy. Well here’s a quick way to make Mojolicious’ built-in server do just that.

Just make a little file, I’ll call it server.pl and put this inside:

#!/usr/bin/env perl

use Mojolicious::Lite;

use Cwd;
app->static->paths->[0] = getcwd;

any '/' => sub {
  shift->reply->static('index.html');
};

app->start;

make it executable and then run server.pl daemon and your site will be available on port 3000. This serves all the files from the current directory (and deeper) and the root will point to index.html. Of course you may change those as you see fit.

In fact this could be used more generally, but then you want to investigate the other servers that Mojolicious provides.

Note that I have updated this post to reflect brian’s comment on removed Mojolicious functionality.

11 Comments

Very nice! If you want a ready-made solution, you can also do something like this with http_this, which I find myself doing a lot, actually.

From my aliases file:

alias pws="plackup -MPlack::App::File -e 'Plack::App::File->new->to_app'"

Easy, just Plack. Only downside is that directory requests don’t work.

theory: directory requests (by that i assume directory indexes) would work if you s/File/Directory/g :)

I think I stole this snippet from Chromatic, same thing as Theory’s, with index.html support:

#!/usr/bin/env perl

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 );
}

package main;

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 );

These little http scripts work great when I need to read Devel::Cover and Devel::NYTProf reports on a remote system (and I’m gonna try http_this).

Oh, thanks for that, preaction! Based on your code, I’ve written a short shell function:

pws () {
    plackup -MPlack::App::File -e '
        package PWS;
        use parent "Plack::App::File";
        sub locate_file {
            $_[1]->{PATH_INFO} .= "index.html"
                if $_[1]->{PATH_INFO} =~ m{/$};
            $_[0]->SUPER::locate_file($_[1]);
        }
        PWS->new->to_app;
    '
}

Pretty damned simple!

There’s also wallflower, that does it for any Plack application. (Full disclosure: I wrote it.)

When writing a static version of your application, there are a few things to consider, though.

Obviously, I didn’t understand the original post.

That’s what I’ve been looking for the last 2 months. Too many web servers on CPAN and too few Neil Bowers to sift through them all. That’s something that I can proudly share with my non-Perl friends.

I’d modified Joel’s script to include a default index file by using a before_dispatch hook. It could probably be better, but I stopped when I got it to work.

I needed this for a particular project so I haven’t stopped to make it pretty.

The render_static was deprecated in the middle of the Mojolicious 5 evolution and is now reply->static:

#!/usr/bin/env perl

use Mojolicious::Lite;

use Cwd;
app->static->paths->[0] = getcwd;

any '/' => sub {
  shift->reply->static('index.html');
};

app->start;

Leave a comment

About Joel Berger

user-pic As I delve into the deeper Perl magic I like to share what I can.