|
|
Introduction
The current svn version of IWL (post 0.52) supports pure perl servers, like HTTP::Server::Simple::CGI. In order to do so, several steps, which are outlined below, must be taken.
Details
Installation
Generally, the IWL client-side data has to be installed in a convenient place. This script assumes that it has been installed in the following way:
iwl-install -d . -j iwl/jscript -s iwl/skin -c .
Server script
The server script for HTTP::Server::Simple::CGI is made up of 3 classes. The FOOServer class inherits from HTTP::Server::Simple::CGI, handles server requests. For simplicity and illustration, it also sends to content back to the server as well. This particular server requires that all client-side data to be sent to the servers, and for this reason, a big part of the handle_request subroutine handles scanning the URL for such data.
The IWL::RPC class has been improved, in order to facilitate such servers. It can be made to return, instead of exit, when handling event requests, and its parameters can be set by means other than reading STDIN or $ENV{QUERY_STRING}.
The CGIResponse class handles this server's specific way of expecting submitted data. The IWL::Response class checks whether a RESPONSE_CLASS Configuration variable is present, and uses it. In this case, CGIResponse is set as the RESPONSE_CLASS variable.
The main class handles running the server itself.
#! /usr/bin/perl
use strict;
package FOOServer;
use base 'HTTP::Server::Simple::CGI';
use IWL;
use IWL::Config '%IWLConfig';
use HTTP::Date qw(time2str);
sub new {
$IWLConfig{RESPONSE_CLASS} = 'CGIResponse';
return shift->SUPER::new(shift);
}
sub handle_request {
my ($self, $cgi) = @_;
my $uri = $ENV{REQUEST_URI};
# Redirection to client-side data
if (substr($uri, 0, 5) eq '/iwl/' && $uri ne '/iwl/') {
my ($resp, $modtime, $ctype);
substr($uri, 0, 1, '') if substr($uri, 0, 1) eq '/';
$modtime = time2str((stat($uri))[9]);
return unless $modtime;
my $method = $ENV{REQUEST_METHOD};
if ($method eq 'GET') {
local *INF;
return unless open(INF, $uri);
binmode INF
unless ((substr($uri, -4) eq '.css') || (substr($uri, -3) eq '.js'));
my $sep = $/;
$/ = undef;
$resp = <INF>;
close INF;
$/ = $sep;
} else {
$resp = (stat($uri))[7];
}
$ctype =
(substr($uri, -4) eq '.css') ? 'text/css; charset=utf-8'
: (substr($uri, -3) eq '.js') ? 'text/javascript; charset=utf-8'
: (substr($uri, -5) eq '.jpg') ? 'image/jpeg'
: 'image/' . substr($uri, -3);
return printStaticContent($ctype, $modtime, $resp);
}
IWL::Object::cleanStateful;
my $rpc = IWL::RPC->new(deferExit => 1, parameters => {$cgi->Vars});
unless ($rpc->handleEvent('IWL-Button-click', sub {
my $params = shift;
return ""
unless ($params->{calendar});
return IWL::Calendar->new(id => 'calendar');
})) {
return test();
}
}
sub printStaticContent {
my $content_type = shift;
my $modtime = shift;
return print join("\r\n",
'HTTP/1.0 200 OK',
"Content-type: $content_type",
'Content-length: ' . ((lc $ENV{REQUEST_METHOD} eq 'head') ? $_[0] : length($_[0])),
"Last-Modified: $modtime",
"\r\n"),
((lc $ENV{REQUEST_METHOD} eq 'head') ? '' : $_[0]);
}
sub test {
my $page = IWL::Page->new;
my $button = IWL::Button->newFromStock('IWL_STOCK_CALENDAR');
$button->registerEvent('IWL-Button-click', '/', {calendar => 1}, {
onComplete => q{IWL.Status.display("Event completed.")},
onStart => q{if ($('calendar')) delete params.calendar; },
update => 'document.body',
insertion => 'bottom',
evalScripts => 1,
});
$page->appendChild($button);
$page->send(type => 'html');
}
package CGIResponse;
sub new { return bless {}, shift}
sub send {
my ($self, %args) = @_;
my $header = $args{header};
return print join("\r\n",
'HTTP/1.0 200 OK',
((join "\n", map {$_ . ": " . $header->{$_}} keys %$header)
. "\nContent-length: " . length($args{content})),
"\r\n"),
((lc $ENV{REQUEST_METHOD} eq 'head') ? '' : $args{content});
}
package main;
my $server = FOOServer->new(27541);
$server->run();As of 0.60
With IWL code as of 10.04.08, the IWL::Static module can be used to handle the static file requests. The IWL client side files should be istalled in the following manner, in order to take advantage of IWL::Static
iwl-install -d . -c . --static_uri_script=SERVER_SCRIPT.pl
The server script itself is significantly smaller than the previously posted one. IWL::Static is used to fetch any requested static content, and serve it back to the client.
#! /usr/bin/perl
use strict;
package FOOServer;
use base 'HTTP::Server::Simple::CGI';
use IWL;
use IWL::Static;
use IWL::Config '%IWLConfig';
use HTTP::Date qw(time2str);
sub new {
$IWLConfig{RESPONSE_CLASS} = 'CGIResponse';
my $self = shift->SUPER::new(shift);
$self->{__static} = IWL::Static->new(deferExit => 1);
return $self;
}
sub handle_request {
my ($self, $cgi) = @_;
$ENV{HTTP_IF_NONE_MATCH} = undef;
$self->{__static}->clearParams->setParams($cgi->Vars);
return if $self->{__static}->handleRequest;
unless ($self->{__static}->handleEvent('IWL-Button-click', sub {
my $params = shift;
return ""
unless ($params->{calendar});
return IWL::Calendar->new(id => 'calendar');
})) {
return test();
}
}
sub test {
my $page = IWL::Page->new;
my $button = IWL::Button->newFromStock('IWL_STOCK_CALENDAR');
$button->registerEvent('IWL-Button-click', '/', {calendar => 1}, {
onComplete => q{IWL.Status.display("Event completed.")},
onStart => q{if ($('calendar')) delete params.calendar; },
update => 'document.body',
insertion => 'bottom',
evalScripts => 1,
});
$page->appendChild($button);
$page->send(type => 'html');
}
package CGIResponse;
sub new { return bless {}, shift}
sub send {
my ($self, %args) = @_;
my $header = $args{header};
return print join("\r\n",
'HTTP/1.0 200 OK',
((join "\n", map {$_ . ": " . $header->{$_}} keys %$header)
. "\nContent-length: " . length($args{content})),
"\r\n"),
((lc $ENV{REQUEST_METHOD} eq 'head') ? '' : $args{content});
}
package main;
my $server = FOOServer->new(27541);
$server->run();
Sign in to add a comment
