NAME

Web::Light - A light weight web framework

VERSION

Version 0.02

SYNOPSIS

Use as a subclass

# myapp.pl

package MyApp;

use base qw/ Web::Light /;
my $app = __PACKAGE__->new();

$app->stash();
$app->dispatch();
$app->setup();

Launch...

$ perl myapp.pl

or

$ perl myapp.pl --help

Description

Web::Light is a light-weight web framework. It's basically just a wrapper around HTTP::Engine and does some stuff to handle plugins. If you are looking for a more tested, developed, and supported web framework, consider using Catalyst.

Web::Light by default launches a stand alone web server that you can connect to with your browser. Since Web::Light can do whatever HTTP::Engine can, you can specify different interfaces like ServerSimple and FastCGI.

Usage

new( %args )

Creates a Web::Light instance

PLUGINS => \@locations

Web::Light can load all the modules under $class::* (or MyApp::* in this example). You can specify a list of locations to use when loading modules. The list just gets passed to Module::Find's setmoduledirs() method.

# will default to @INC if PLUGINS is not defined

new(
   PLUGINS => [ @INC, './' ],
);

If you don't want to search @INC, and only want to use modules in your current directory, an example of your directory structure might look like this:

$ ls

-rw-r--r--    myapp.pl
drwxr-xr-x    MyApp/
drwxr-xr-x    MyApp/Plugin
-rw-r--r--    MyApp/Plugin/Root.pm


# then for PLUGINS:
new(
    PLUGINS => [ './' ],
);
NOLOAD => \@list

If there is a module you do not want loaded, you can do this:

 new(
    PLUGINS => [ @INC, './' ],
    NOLOAD  => [qw/ MyApp::Plugin::Something  MyApp::Foo::Bar /],
);
404 => $plugin

Specify a plugin to handle 404:

new(
   404 => 'MyApp::Plugin::My404',
);
AUTH => $plugin

Set the plugin to handle authentication. See dispatch() below on sessions. If a session variable is not set, then the AUTH plugin will be forced.

new(
   AUTH => 'MyApp::Plugin::MyAuth',
);
MOUNT => 'path'

If you are using FastCGI, and wish to have the webserver handle static content, then you can't just Alias / to your application.

Your httpd.conf (Apache) might look like this:

<VirtualHost 192.168.1.100:80>
    servername example.org 
    FastCGIExternalServer /fastcgi -socket /tmp/MyApp.sock
    Alias /dynamic /fastcgi/
    DocumentRoot /home/user/MyApp/static
</VirtualHost>

With the above example, you would have to mount Web::Light on 'dynamic'

new(
    MOUNT => 'dynamic',
);

You cannot mount Web::Light any deeper than one path.

# INVALID!!!
new(
    MOUNT => 'site/dynamic',
);

new() Example...

# All together now ...

package MyApp;

use base qw/ Web::Light/;

my $app = __PACKAGE__->new(
    PLUGINS => [ @INC, './' , '/path/to/lib' ],
    NOLOAD  => [ qw/ MyApp::Plugin::OLD  MyApp::Auth::File /],

    404     => 'MyApp::Plugin::Cool404',
    AUTH    => 'MyApp::Auth::Awesome',
    MOUNT   => 'dynamic',
);

dispatch( %args )

Define how URLs get dispatched.

dispatch(
   root => {
        plugin  => 'MyApp::Plugin::Root',
        methods => [qw/ default /],
   },
   home => {
        plugin  => 'MyApp::Plugin::CoolHome,
        methods => [qw/ default test /],
        session => [qw/ username /],
   },
);

The above example will dispatch the following to the appropriate plugin:

http://localhost/          --> MyApp::Plugin::Root->default()
http://localhost/hello     --> MyApp::Plugin::Cool404->default()

http://localhost/home      --> MyApp::Plugin::CoolHome->default()  
http://localhost/home/test --> MyApp::Plugin::CoolHome->test()

If 'session' contains a list, this forces Web::Light to check if each variable in that list is set. If they aren't, the 'AUTH' plugin that was defined with new() will be forced.

I was going to auto add the 'default' method to the list, but I felt having to specify the methods for each plugin will help remember that this is how it works.

root => { plugin => ... }

Note: If you do not dispatch a root URL somewhere, Web::Light will set root to dispatch to MyApp::Plugin::Root by default. So either create this plugin:

$ perl myapp.pl --create

... or dispatch root to an already existing plugin:

$app->dispatch(
    root => {
        plugin  => 'MyApp::Foo::Something',
        methods => [qw/ default /],
    },
);

Also note that root can only have 1 (one) method, and it should be 'default'.

stash( %args )

Just a simple hash to pass around stuff to your plugins.

use MyDatabase::Main;  # your DBIx::Class
use Template;
my $tt = Template->new;

$app->stash(
    tt => $tt,
    db => MyDatabase::Main->connect(dbi:mysql .. ...),
);

setup( %args )

Define your HTTP::Engine and Middleware preferences here. If no arguments are passed, Web::Light will use ServerSimple and port 5000 by default.

engine => ( $args )

Define HTTP::Engine. Be aware that these settings can be defined on the command line too, like:

$ perl myapp.pl --interface fcgi --nproc 1 --listen /tmp/MyApp.sock --detach

Otherwise, you can specify it like so:

   $app->setup(
       engine => {    
           interface => {
               module => 'ServerSimple',
               args => {
                   host => '127.0.0.1',
                   port => 4000,
               }
           },
       }
   );


   # FastCGI?

   $app->setup(
       engine => {
           interface => {
               module => 'FCGI',
               args   => { },
           },
       },
   );
session => ( $args )

Define HTTP::Engine::Middleware::HTTPSession

$app->setup(
    session => {
        store => {
            class => 'File',
            args => { dir => './tmp' },
        },
        state => {
            class => 'Cookie',
            args => {
                name => 'MyApp',
                path => '/',
                domain => 'example.org',
            },
        }
    }
);
static => ( $args )

Define HTTP::Engine::Middleware::Static to handle your static content

   $app->setup(
       static => {
           regexp => qr{^/(robots.txt|favicon.ico|(?:css|js|images)/.+)$},
           docroot => '/home/user/MyApp/',
       }
   );

method_match()

Gets called by dispatch(). This just verifies that the methods you specify in your dispatch map to an actual subroutine.

dispatch_match()

Gets called by dispatch(). This verifies that your dispatch maps to actual plugins

handler()

Handler subroutine sent to HTTP::Engine

createRootPlugin()

Creates the default YourApp::Plugin::Root plugin when called with:

$ perl myapp.pl --create

Creating Plugins

You can name your plugins anything, but in our example, the plugins need to be under MyApp::*

$ mkdir -p MyApp/Foo

$ vi MyApp/Foo/Something.pm

A minimal plugin:

package MyApp::Foo::Something;

sub default {
    return "Hello World!";
}
1;

More detailed:

package MyApp::Foo::Something;

use strict;
use warnings;

sub default {

    my ($self,$app) = @_;
    my $req         = $app->{req};          # perldoc HTTP::Engine::Request
    my $param       = $req->paramenters;    # GET/POST paramenters
    my $session     = $req->session;        # perldoc HTTP::Session
    my $tt          = $app->{stash}{tt};    # Template-Toolkit from your stash
    my $schema      = $app->{stash}{db};    # your DBIx::Class from your stash

    $vars = {
        message => "Hello World!",
    };
    $tt->process('index.tt', $vars, \my $out) 
        or return $tt->error();
    
    return $out;
}

sub test {
    return "Just a test method!";
}

1;

To use this plugin, make sure you dispatch it to a URL...

$app->dispatch(
    newplugin => {
        plugin => 'MyApp::Foo::Something',
        methods => [qw/ default test /],
    },
);

Then go to http://localhost/newplugin to see it in action

Benchmarks

I've done some quick benchmarking, just to get some frame of reference.

   # P3 1.4GHz 
   # Document Length: 696 bytes
   # ab -n 100 -c 2 http://localhost/
   
   
   FastCGI interface, and Apache handling static content.
   --->   Requests per second:    171.53 [#/sec] (mean)

   ServerSimple interface, serving all content.
   --->   Requests per second:    180.51 [#/sec] (mean)


   *shrug*  I'll play around some more.  Maybe not.

AUTHOR

Michael Kroher, <infrared at cpan.org>

BUGS

Please report any bugs or feature requests to bug-web-light at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Web-Light. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

See Also

HTTP::Engine

HTTP::Engine::Middleware

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc Web::Light

You can also look for information at:

TO-DO

Not sure yet.

COPYRIGHT & LICENSE

Copyright 2010 Michael Kroher, all rights reserved.

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