The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

HTTP::Server::Brick - Simple pure perl http server for prototyping "in the style of" Ruby's WEBrick

VERSION

This document describes HTTP::Server::Brick version 0.1.7

SYNOPSIS

    use HTTP::Server::Brick;
    use HTTP::Status;
    
    my $server = HTTP::Server::Brick->new( port => 8888 );
    
    $server->mount( '/foo/bar' => {
        path => '/some/directory/htdocs',
    });
    
    $server->mount( '/test/proc' => {
        handler => sub {
            my ($req, $res) = @_;
            $res->add_content("<html><body>
                                 <p>Path info: $req->{path_info}</p>
                               </body></html>");
            1;
        },
        wildcard => 1,
    });
    
    $server->mount( '/test/proc/texty' => {
        handler => sub {
            my ($req, $res) = @_;
            $res->add_content("flubber");
            $res->header('Content-type', 'text/plain');
            1;
        },
        wildcard => 1,
    });
    
    # these next two are equivalent
    $server->mount( '/favicon.ico' => {
        handler => sub { RC_NOT_FOUND },
    });
    $server->mount( '/favicon.ico' => {
        handler => sub {
            my ($req, $res) = @_;
            $res->code(RC_NOT_FOUND);
            1;
        },
    });
    
    # start accepting requests (won't return unless/until process
    # receives a HUP signal)
    $server->start;

For an SSL (https) server, replace the new() line above with:

    use HTTP::Daemon::SSL;
    
    my $server = HTTP::Server::Brick->new(
                                           port => 8889,
                                           daemon_class => 'HTTP::Daemon::SSL',
                                           daemon_args  => [
                                              SSL_key_file  => 'my_ssl_key.pem',
                                              SSL_cert_file => 'my_ssl_cert.pem',
                                           ],
                                         );

See the docs of HTTP::Daemon::SSL for other options.

DESCRIPTION

HTTP::Server::Brick allows you to quickly wrap a prototype web server around some Perl code. The underlying server daemon is HTTP::Daemon and the performance should be fine for demo's, light internal systems, etc.

METHODS

new

new takes nine named arguments (all of which are optional):

error_log, access_log

Should be self-explanatory - can be anything that responds to print eg. file handle, IO::Handle, etc. Default to stderr and stdout respectively.

port

The port to listen on. Defaults to a random high port (you'll see it in the error log).

host

The server hostname. Defaults to something sensible.

timeout

Used for various timout values - see HTTP::Daemon for more information.

directory_index_file

The filename for directory indexing. Note that this only applies to static path mounts. Defaults to index.html.

directory_indexing

If no index file is available (for a static path mount), do you want a clickable list of files in the directory be rendered? Defaults to true.

leave_sig_pipe_handler_alone

HTTP::Daemon, the http server module this package is built on, chokes in certain multiple-request situations unless you ignore PIPE signals. By default PIPE signals are ignored as soon as you start the server (and restored if the server exits via HUP). If you want to handle PIPE signals your own way, pass in a true value for this.

If this makes no sense to you, just ignore it - the "right thing" will happen by default.

daemon_class

The class which actually handles webserving. The default is HTTP::Daemon. If you want SSL, use HTTP::Daemon::SSL. Whatever class you use must inherit from HTTP::Daemon.

daemon_args

Sometimes you need to pass extra arguments to your daemon_class, e.g. SSL configuration. This arrayref will be dereferenced and passed to new.

fork

Set to true if you want a forking server.

mount

mount takes two positional arguments. The first a full uri (as a string beginning with '/' - any trailing '/' will be stripped). The second is a hashref which serves as a spec for the mount. The allowable hash keys in this spec are:

path

A full path to a local filesystem directory or file for static serving. Mutually exclusive with handler.

handler

A coderef. See "Handlers" below. Mutually exclusive with path.

wildcard

If false, only exact matches will be served. If true, any requests based on the uri will be served. eg. if wildcard is false, '/foo/bar' will only match http://mysite.com/foo/bar and not, say, http://mysite.com/foo/bar/sheep. If wildcard is true, on the other hand, it will match. A handler can access the path extension as described below in "Handlers".

Static handlers that are directories default to wildcard true.

The site map is always searched depth-first, in other words a more specific uri will trump a less-specific one.

return value

mount returns $self so that it can be chained into a one-liner if desired.

shortcut invocation

As a shortcut also to aid one-liners, instead of a hashref the second argument can be either a path string or a coderef, mapped like so:

string

equivalent to { path = the_string, wildcard => 1 }>

coderef

equivalent to { handler = coderef, wildcard => 0 }>

Eg. to quickly server your current directory:

  perl -MHTTP::Server::Brick -e 'HTTP::Server::Brick->new(fork=>1)->mount(qw(/ .))->start'

start

Actually starts the server - this will loop indefinately, or until the process recieves a HUP signal in which case it will return after servicing any current request, or waiting for the next timeout (which defaults to 5s - see "new").

add_type

The mime-type of static files is automatically determined by LWP::MediaTypes. You can add any types it doesn't know about via this method.

The first argument is the mime type, all subsequent arguments form a list of possible file extensions for that mime type. See LWP::MediaTypes for more info.

Handlers

When a mounted handler codred matches a requested url, the sub is called with two arguments in @_, first a request object then a response object.

Request

The request object is an instance of HTTP::Request with two extra properties:

$req->{mount_path}

The mounted path that was matched. This will always be identical to $req->uri->path for non-wildcard mounts.

$req->{path_info}

Using nomenclature from CGI.pm, any extra path (or rather, uri) info after the matched mount_path. This will always be empty for non-wildcard mounts.

The documentation for HTTP::Request will be of use for extracting all the other useful information.

Added to the regular request headers created by HTTP::Request is an X-Remote-IP header, which allows you to obtain the remote IP of the client. (Contributed by Hans Dieter Pearcey).

Response

The response object is an instance of HTTP::Response. The useful operations (which you can learn how to do from the HTTP::Response docs) are setting headers, adding content and setting the http status code.

Response Headers

The Content-type header defaults to text/html unless your handler sets it to something else. The Content-length header is set for you.

Redirection

If you set the response code to a redirect code, you need to set a {target_uri} property on the request object to an instance of a URI::http object reflecting the uri you want to redirect to (either fully qualified or relative to the directory of the requested url). There are examples in the test file t/serving.t in this module's distribution.

This is weak because we're breaking encapsulation by assuming it's ok to stuff an extra variable into the response object (just as we are to propogate the path_info property). It does in fact work fine and is unlikely to ever break, but a future version (prior to 1.0.0) of this module will replace this behavior with a subclassed HTTP::Response and appropriate setter/getter methods.

Handler Return

The handler sub must return true for a normal response. The actual http response is determined as follows:

    1. if the handler died or returned false => RC_INTERNAL_SERVER_ERROR (ie. 500)
    2. if the handler set a code on the response object, use that
    3. if the handler returned something that looks like a return code
    4. RC_OK (ie. 200)

DEBUGGING

If an envronment variable DEBUG is set (to something Perl considers true) there will be extra logging to error_log.

DEPENDENCIES

LWP Test::More version

HISTORY

Over the past few years I've spent quite a bit of time noodling about with Ruby based web code - whether Rails or super cool continuation stuff - and it's always easy to get a prototype up and serving thanks to WEBrick (the pure-Ruby server that's part of the standard Ruby distribution). I've never found it quite as easy to throw together such a prototype in Perl, hence YASHDM (yet another simple http daemon module).

HTTP::Server::Brick is not a clone of WEBrick - it's "in the style of" WEBrick like those movies in the discount VHS bin are "in the style of Lassie": The good guys get saved, the bad guys get rounded up, but the dog's never quite as well trained...

To be more fair, I have just taken the ideas I have used (and liked) when building prototypes with WEBrick and implemented them in (what I hope is) a Perlish way.

BUGS AND LIMITATIONS

It's version 0.1.7 - there's bound to be some bugs!
The tests fail on windows due to forking limitations. I don't see any reason why the server itself won't work but I haven't tried it personally, and I have to figure out a way to test it from a test script that will work on Windows.
In forking mode there is no attempt to limit the number of forked children - beware of forking yourself ;)
No attention has been given to propagating any exception text into the http error (although the exception/die message will appear in the error_log).
Versions 1.02 and earlier of HTTP::Daemon::SSL has a feature/documentation conflict where it will never timeout. This means your server won't respond to a HUP signal until the next request is served. Version 1.03_01 (developer release) and later do not have this issue.

If you want to check out the latest development version of HTTP::Server::Brick you can do so from my GitHub account http://github.com/aufflick/p5-http-server-brick.

Please report any bugs or feature requests to bug-http-server-brick@rt.cpan.org, through the web interface at http://rt.cpan.org or via email to the author.

SEE ALSO

CPAN has various other modules that may suit you better. Search for HTTP::Server or HTTP::Daemon. HTTP::Daemon, HTTP::Daemon::App and HTTP::Server::Simple spring to mind.

AUTHOR

Original version by: Mark Aufflick <mark@aufflick.com> http://mark.aufflick.com/
SSL and original forking support by: Hans Dieter Pearcey <hdp@pobox.com>
Maintained by: Mark Aufflick

LICENCE AND COPYRIGHT

Copyright (c) 2007 2008, Mark Aufflick <mark@aufflick.com>. Portions Copyright (c) 2007 2008, Hans Dieter Pearcey <hdp@pobox.com>

All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.

DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.