#!/usr/bin/perl
# $Id: webserver.pl,v 1.5 2010/03/12 23:01:47 dk Exp $
#
=pod
This example features a minimalistic web server, that can only maintain
a counter in a http session. It uses persistent connections of HTTP/1.1,
and keeps one counter per connection. The session expires in $conn_timeout
automatically.
Open two browsers (not just two windows/tabs of the same, browsers are
smart now and share connections) and see how each has its own counter.
=cut
use strict;
use IO::Socket;
use HTTP::Request;
use HTTP::Response;
use IO::Lambda qw(:all);
use IO::Lambda::HTTP::Server;
my $port = 8080;
$port = $ARGV[0] if $ARGV[0] && $ARGV[0] =~ /^\d+$/;
my ($serv,$error) = http_server { handle( @_ ) } "localhost:$port", timeout => 5;
die "Cannot create webserver: $error\n" unless $serv;
print <<BANNER;
Listening on port $port. Specify another port as an argument, if needed.
Now, start your browser and go to this URL:
http://localhost:8080/
BANNER
my $conn_timeout = 10;
sub fail { HTTP::Response-> new( "HTTP/1.1 $_[0]", $_[1] ) }
sub handle
{
my ( $req, $session) = @_;
return fail(404, "GET request only")
if $req-> method ne 'GET';
$session-> {counter} ||= 0;
if ( $req-> uri eq '/') {
} elsif ( $req-> uri eq '/inc') {
$session-> {counter}++;
} elsif ( $req-> uri eq '/dec') {
$session-> {counter}--;
} elsif ( $req-> uri eq '/rst') {
$session-> {counter} = 0;
} elsif ( $req-> uri eq '/stp') {
$serv->shutdown;
} else {
fail( 404, "Not found");
}
my $content = <<CONTENT;
<html><body>
<h1>Counter: $session->{counter}</h1>
<p>
<a href="/inc">++</a><br>
<a href="/dec">--</a><br>
<a href="/rst">=0</a><br>
<a href="/stp">exit</a><br>
</body></html>
CONTENT
return HTTP::Response-> new(
'HTTP/1.1 200', 'OK', [
'Date' => scalar(localtime),
'Server' => 'IO::Lambda',
'Content-Type' => 'text/html',
'Content-Length' => length($content),
'Connection' => 'Keep-Alive',
'Keep-Alive' => $conn_timeout,
], $content);
}
$serv-> wait;