Following my earlier tests, I’ve got good hopes for Plack on Windows. To ramp it up from the hello world example I thought I’d try a simple network cache. HTTP isn’t obviously the best protocol for this purpose, but it’s widely used, presumably due to the existence of many robust servers (also maybe because people [including me of course!] can’t be bothered to check for short tcp reads/writes).
To make the example simple, I have (a) elided the actual call to retrieve the data and (b) put all of the code in one file. Obviously I wouldn’t recommend doing this in production but hopefully it will convey the intent.
# —
Most of my perl starts with a preamble that looks somewhat like this.
use 5.010; use strict; use warnings; use POSIX;
get_data represents a call (to a database for example) that will take a while to complete.
sub get_data { my $key = shift; sleep 5; return "[$key]"; }
get_cached_data is also very much simplified. Normally I’d expect to use something like the Cache::XXX modules.
sub get_cached_data { my $key = shift; state %cache; if (! exists($cache{$key})) { $cache{$key} = get_data($key); } return $cache{$key}; }
response wraps the PSGI response to make the example a bit cleaner. It obviously wouldn’t be appropriate if other http response types were returned.
sub response { my $data = shift; return [ 200, ['Content-Type' => 'text/plain'], [$data], ]; }
Twiggy doesn’t log the information about the request by default in the same way as plackup does. There may be a flag to enable that (should look at the code) but for now I synthesise it from $env.
sub request_info { my $env = shift; my $ts = POSIX::strftime('%d/%b/%Y %H:%M:%S', localtime(time())); return qq{$env->{REMOTE_ADDR} - - [$ts] } . qq{"$env->{REQUEST_METHOD} $env->{PATH_INFO} $env->{SERVER_PROTOCOL}" } . qq{"-" "$env->{HTTP_USER_AGENT}"}; }
And there should be nothing surprising in the main.
# -- main my $app = sub { my $env = shift; # foreach my $key (keys %$env) { # print "$key $env->{$key}\n"; # } # Twiggy doesn't give the same request info as vanilla plack say request_info($env); # Could map METHOD/PATH to subroutine calls using a hash my $method = $env->{REQUEST_METHOD}; my $path_info = $env->{PATH_INFO}; my $start = time(); my $response = response(get_cached_data($path_info)); my $time = time() - $start; my $s = ($time == 1) ? '' : 's'; say "Generating response took $time second$s"; return $response; };
Testing with firefox is a bit crufty, but I haven’t got around to adapting my test client yet.
$ twiggy --listen :8080 obj-cache.psgi 127.0.0.1 - - [30/Mar/2010 21:24:47] "GET /someurl/ HTTP/1.1" "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2 (.NET CLR 3.5.30729)" Generating response took 5 seconds 127.0.0.1 - - [30/Mar/2010 21:25:02] "GET /someurl/ HTTP/1.1" "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2 (.NET CLR 3.5.30729)" Generating response took 0 seconds # Yes, looks good!