perlplack

understanding this Plack implementation


I am looking at a strange implementation of a web service using Plack, and I can't quite understand how all the pieces come together (a coworker copied and modified it from a tutorial, but he can't find the tutorial any more).

First of all, this code does work, as strange as it is.

Here is what I know: At a high level, this code implements a web service. Due to the conventions of Plack, this file has to return a method which takes request parameters as input and then returns a HTTP code and body. That is why there is the "my $app = sub {". Assuming this is the last line in the file (which is app.psgi) it will be the return value of the file.

I don't understand some things beginning with "return sub." I believe that is essentially overriding "my $app = sub {", because now that is the function that the file will return.

However, that might be wrong because it seems to take different arguments. Instead of taking $env (which is information about the request including GET params), it takes an argument $responder. When I print out the type of that, it is CODE. I don't know what that means.

Then the next line seems to simultaneously return an HTTP code (beginning our response) and get a writer for writing additional data. Everything after that makes sense.

So in summary I need help understanding what this second method is doing, and what the nature of its arguments are. Thanks very much in advance.

use strict;
use warnings;

use Plack::Request;
use POSIX ":sys_wait_h";
use IO::Handle;

STDOUT->autoflush(1);
my $app = sub {
    my $env = shift;
    my $req = Plack::Request->new($env);
    print "Worker PID: $$\n";
    my $params = $req->parameters();

    return sub {
        my $responder = shift;

        #this will print "responder type: CODE"
        print "responder type: " . (ref $responder) . "\n";

        my $writer = $responder->(
            [ 200, [ 'Content-Type', 'application/html' ]]);
        $writer->write("some content");
        $writer->close();
    }
}

Solution

  • Using return in a sub takes effect only when the sub is being run, not when it's being returned.

    Instead of directly returning the response, the application can return a code reference:

    Applications MUST return a response as either a three element array reference, or a code reference for a delayed/streaming response.

    The details are described under Delayed Response and Streaming Body in PSGI.