=encoding utf-8

=head1 NAME

PSGI - Perl Web Server Gateway Interface Specification

=head1 ABSTRACT

This document specifies a standard interface between web servers and
Perl web applications or frameworks, to promote web application
portability and reduce the duplicated efforts by web application
framework developers.

Keep in mind that PSGI is not Yet Another web application
framework. PSGI is a specification to decouple web server environments
from web application framework code. PSGI is also not the web
application API. Web application developers (end users) are not
supposed to run their web applications directly using the PSGI
interface, but instead are encouraged to use frameworks that
support PSGI, or use the helper implementations like Plack (more on
that later).

=head1 TERMINOLOGIES

=over 4

=item Servers

Servers are web servers that accept HTTP requests, dispatch the
requests to the web applications and return the HTTP response to the
clients. In PSGI specification it's a Perl process that's running
inside an HTTP server (e.g. mod_perl in Apache), a daemon process
called from a web server (e.g. FastCGI daemon) or a pure perl HTTP
server.

Servers are also called I<PSGI implementations> as well as
I<Backends>.

=item Applications

Applications are web applications that actually get HTTP requests
and return HTTP response. In PSGI it's a code reference: see below.

=item Middleware

Middleware is a PSGI application, which is a code reference, but also
runs like a server to run other applications. It can be thought of a
I<plugin> to extend PSGI application: see below.

=item Framework developers

Framework developers are authors of web application frameworks. They
need to write adapters (or engines) to read PSGI input, then run the
application logic and returns PSGI response to the server.

=item Web application developers

Web application developers are developers who write code that uses one
of the web application framework that uses PSGI interface. They
usually don't need to deal with nor care about PSGI protocol at all.

=back

=head1 SPECIFICATION

=head2 Applications

A PSGI application is a Perl code reference. It takes exactly one
argument, the environment and returns an array reference of exactly
three values.

  sub app {
      my $env = shift;
      return [
          '200',
          [ 'Content-Type' => 'text/plain' ],
          [ "Hello World" ], # or IO::Handle-like object
      ];
  }

=head3 The Environment

The environment MUST be a hash reference that includes CGI-like
headers. The application is free to modify the environment. The
environment is required to include these variables (adopted from
PEP333, Rack and JSGI) except when they'd be empty, but see below:

=over 4

=item *

C<REQUEST_METHOD>: The HTTP request method, such as "GET" or
"POST". This cannot ever be an empty string, and so is always
required.

=item *

C<SCRIPT_NAME>: The initial portion of the request URL's I<path> that
corresponds to the application, so that the application knows its
virtual "location". This may be an empty string if the application
corresponds to the "root" of the server.

=item *

C<PATH_INFO>: The remainder of the request URL's "path", designating
the virtual "location" of the request's target within the
application. This may be an empty string if the request URL targets
the application root and does not have a trailing slash. This value
should be URI decoded by servers to be compatible to RFC 3875.

=item *

C<REQUEST_URI>: The undecoded, raw request URL line. It is the raw URI
path and query part that appears in the HTTP C<GET /... HTTP/1.x> line
and doesn't contain URI scheme and host names.

Unlike C<PATH_INFO>, this value SHOULD NOT be decoded by servers and
hence it is an application's responsibility to properly decode paths
to map URL to application handlers, when using C<REQUEST_URI> over
C<PATH_INFO>.

=item *

C<QUERY_STRING>: The portion of the request URL that follows the C<?>,
if any. May be empty, but is always required.

=item *

C<SERVER_NAME>, C<SERVER_PORT>: When combined with C<SCRIPT_NAME> and
C<PATH_INFO>, these variables can be used to complete the URL. Note,
however, that C<HTTP_HOST>, if present, should be used in preference
to C<SERVER_NAME> for reconstructing the request URL. C<SERVER_NAME>
and C<SERVER_PORT> can never be empty strings, and so are always
required.

=item *

C<SERVER_PROTOCOL>: The version of the protocol the client used to
send the request. Typically this will be something like "HTTP/1.0" or
"HTTP/1.1" and may be used by the application to determine how to
treat any HTTP request headers.

=item *

C<HTTP_> Variables: Variables corresponding to the client-supplied
HTTP request headers (i.e., variables whose names begin with
C<HTTP_>). The presence or absence of these variables should
correspond to the presence or absence of the appropriate HTTP header
in the request.

If there are multiple header lines sent with the same key, the server
should treat them as if they're sent in one line, i.e. combine them
with C<, > as in RFC 2616.

=back

In addition to this, the PSGI environment MUST include these
PSGI-specific variables:

=over 4

=item *

C<psgi.version>: An array ref [1,0] representing this version of PSGI.

=item *

C<psgi.url_scheme>: A string C<http> or C<https>, depending on the request URL.

=item *

C<psgi.input>: the input stream. See below.

=item *

C<psgi.errors>: the error stream. See below.

=item *

C<psgi.multithread>: true if the application may be simultaneously
invoked by another thread in the same process, false otherwise.

=item *

C<psgi.multiprocess>: true if an equivalent application object may be
simultaneously invoked by another process, false otherwise.

=back

The PSGI environment MAY include these optional PSGI variables:

=over 4

=item *

C<psgi.run_once>: true if the server expects (but does not guarantee!)
that the application will only be invoked this one time during the
life of its containing process. Normally, this will only be true for a
server based on CGI (or something similar).

=item *

C<psgi.nonblocking>: true if the server is calling the application in an
non-blocking event loop.

=item *

C<psgi.streaming>: true if the server supports callback style delayed
response and streaming writer object.

=back

The server or the application can store its own data in the
environment, too. The keys MUST contain at least one dot, and should
be prefixed uniquely. The prefix C<psgi.> is reserved for use with the
PSGI core implementation and other accepted extensions and MUST NOT be
used otherwise. The environment MUST NOT contain the keys
C<HTTP_CONTENT_TYPE> or C<HTTP_CONTENT_LENGTH> (use the versions
without C<HTTP_>). The CGI keys (named without a period) MUST have a
scalar variable containing strings. There are the following
restrictions:

=over 4

=item *

C<psgi.version> MUST be an array of integers.

=item *

C<psgi.url_scheme> MUST be a scalar variable containing either the
string C<http> or C<https>.

=item *

There MUST be a valid input stream in C<psgi.input>.

=item *

There MUST be a valid error stream in C<psgi.errors>.

=item *

The C<REQUEST_METHOD> MUST be a valid token.

=item *

The C<SCRIPT_NAME>, if non-empty, MUST start with C</>

=item *

The C<PATH_INFO>, if non-empty, MUST start with C</>

=item *

The C<CONTENT_LENGTH>, if given, MUST consist of digits only.

=item *

One of C<SCRIPT_NAME> or C<PATH_INFO> MUST be set. C<PATH_INFO> should
be C</> if C<SCRIPT_NAME> is empty. C<SCRIPT_NAME> should never be C</>,
but should instead be empty.

=back

=head3 The Input Stream

The input stream in C<psgi.input> is an IO::Handle-like object which
streams the raw HTTP POST or PUT data. If it is a file handle then it
MUST be opened in binary mode. The input stream MUST respond to
C<read> and MAY implement C<seek>.

The built-in filehandle or IO::Handle based objects should work fine
everywhere. Application developers SHOULD NOT inspect the type or
class of the stream, but instead just call C<read> to duck type.

Application developers SHOULD NOT use the built-in C<read> function to
read from the input stream, because C<read> function only works with
the real IO object (a glob ref based file handle or PerlIO) and makes
duck typing difficult. Web application framework developers, if
they know the input stream will be used with the built-in read() in any
upstream code they can't touch, SHOULD use PerlIO or tie handle to
work around with this problem.

=over 4

=item read

  $input->read($buf, $len [, $offset ]);

Returns the number of characters actually read, 0 at end of file, or
undef if there was an error.

=item seek

  $input->seek($pos, $whence);

Returns 1 on success, 0 otherwise.

=back

=head3 The Error Stream

The error stream in C<psgi.errors> is an IO::Handle-like object to
print errors. The error stream must implement C<print>.

The built-in filehandle or IO::Handle based objects should work fine
everywhere. Application developers SHOULD NOT inspect the type or
class of the stream, but instead just call C<print> to duck type.

=over 4

=item print

  $errors->print($error);

Returns true if successful.

=back

=head3 The Response

The response MUST be a three element array reference if the
application wants to directly return the HTTP response.

An application MAY choose to return other type of responses such as a
code reference, to delay the response only if the server supports the
streaming (See below).

=head4 Status

HTTP status code, is an integer and MUST be greater than or equal to 100.

=head4 Headers

The headers must be an array reference (and NOT a hash reference!)
containing key and value pairs.  Its number of elements MUST be
even. The header MUST NOT contain a C<Status> key, contain keys with
C<:> or newlines in their name, contain keys that end in C<-> or C<_>
but only contain keys that consist of letters, digits, C<_> or C<->
and start with a letter. The value of the header must be a scalar
value that contain a string. The value string MUST NOT contain
characters below chr(37) except chr(32) (whitespace).

If the same key name appears multiple times in an array ref, those
header lines MUST be sent to the client separately (e.g. multiple
C<Set-Cookie> lines).

=head4 Content-Type

There MUST be a C<Content-Type> except when the C<Status> is 1xx, 204
or 304, in which case there MUST be none given.

=head4 Content-Length

There MUST NOT be a C<Content-Length> header when the C<Status> is
1xx, 204 or 304.

If the Status is not 1xx, 204 or 304 and there is no C<Content-Length>
header, servers MAY calculate the content length by looking at Body,
in case it can be calculated (i.e. if it's an array ref of body chunk
or a real file handle), and append to the outgoing headers.

=head4 Body

The response body is returned from the application in one of following
two types of scalar variable.

=over 4

=item *

An array reference containing body as lines.

  my $body = [ "Hello\n", "World\n" ];

Note that the elements in an array reference are NOT REQUIRED to end
in a newline. The servers SHOULD just write each elements as is to the
client, and SHOULD NOT care if the line ends with newline or not.

So, when you have a big chunk of HTML in a single scalar C<$body>,

  [ $body ]

is a valid response body.

=item *

An IO::Handle-like object or a built-in filehandle.

  open my $body, "</path/to/file";
  open my $body, "<:via(SomePerlIO)", ...;
  my $body = IO::File->new("/path/to/file");

  my $body = SomeClass->new(); # mock class that implements getline() and close()

Servers SHOULD NOT check the type or class of the body but instead
just call C<getline> (i.e. duck type) to iterate over the body and
call C<close> when done.

Servers MAY check if the body is a real filehandle using C<fileno> and
C<Scalar::Util::reftype> and if it's a real filehandle that has a file
descriptor, it MAY optimize the file serving using techniques like
I<sendfile(2)>.

The body object MAY respond to C<path> method to return the local file
system path, which MAY be used by some servers to switch to more
efficient file serving method using the file path instead of a file
descriptor.

Servers are RECOMMENDED to set C<$/> special variable to the buffer
size when reading content from C<$body> using C<getline> method, in
case it's a binary filehandle. Applications, when it returns a mock
object that implements C<getline> are NOT REQUIRED to respect the
C<$/> value.

=back

=head2 Delayed Reponse and Streaming Body

PSGI interface allows applications and servers optionally handle
callback-style response (instead of three-element array reference) to
delay the HTTP response and stream content (server push).

To enable delayed response, an application SHOULD check if
C<psgi.streaming> environment is true, and in that case, MAY return a
callback that is passed another callback (response starter) as its
first argument, and pass the three element response to the callback.

  my $app = sub {
      my $env = shift;

      # Delays response until it fetches content from the network
      return sub {
          my $respond = shift;
          fetch_content_from_server(sub {
              my $content = shift;
              # ...
              $respond->([ 200, $headers, [ $content ] ]);
          });
      };
  };

Similarly, an application MAY omit the third element (the body) in the
callback to get a response writer object, that implements C<write>,
C<poll_cb> and C<close> method to push the response body.

  my $app = sub {
      my $env = shift;

      # immediately starts the response and stream the content
      return sub {
          my $respond = shift;
          my $writer = $respond->([ 200, [ 'Content-Type', 'application/json' ]]);

          wait_for_events(sub {
              my $new_event = shift;
              if ($new_event) {
                  $writer->write($new_event->as_json . "\n");
                  # Or:
                  # $writer->poll_cb(sub { $_[0]->write($new_event->as_json . "\n") });
              } else {
                  $writer->close;
              }
          });
      };
  };

Delayed response and streaming should be useful if you want to
implement non-blocking I/O based server streaming or long-poll Comet
push technology. IO::Handle-like object is I<pull>, while this
streaming response implements I<push>.

This interface is optional: An applciation SHOULD check if the server
supports streaming. Servers MAY decide to not accept this streaming
response and throws an exception. Servers MUST set C<psgi.streaming>
to true if this interface is supported. Servers MUST return a writer
object if the third argument (response body) is omitted or not
defined in the response starter callback arguments.

=head2 Middleware

Middleware is itself a PSGI application but it takes an existing PSGI
application and runs it like a server, mostly to do pre-processing on
C<$env> or post-processing on the response objects.

Here's a simple example that appends special HTTP header
I<X-PSGI-Used> to any PSGI application.

  # $app is a simple PSGI application
  my $app = sub {
      my $env = shift;
      return [ '200', [ 'Content-Type' => 'text/plain' ], [ "Hello World" ] ];
  };

  # $xheader is a middleware to wrap $app
  my $xheader = sub {
      my $env = shift;
      my $res = $app->($env);
      push @{$res->[1]}, 'X-PSGI-Used' => 1;
      return $res;
  };

Middleware itself MUST behave exactly like a PSGI application: take
C<$env> and return C<$res>. Middleware MAY decide not to support the
streaming interface (see above) but SHOULD pass through the response
types that it doesn't understand.

=head1 ACKNOWLEDGEMENTS

Some parts of this specification are adopted from the following specifications.

=over 4

=item *

PEP333 Python Web Server Gateway Interface L<http://www.python.org/dev/peps/pep-0333>

=item *

Rack L<http://rack.rubyforge.org/doc/SPEC.html>

=item *

JSGI Specification L<http://jackjs.org/jsgi-spec.html>

=back

I'd like to thank authors of these great documents.

=head1 AUTHOR

Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt>

=head1 CONTRIBUTORS

The following people have contributed to the PSGI specification and
Plack implementation by commiting their code, sending patches,
reporting bugs, asking questions, suggesting useful advices,
nitpicking, chatting on IRC or commenting on my blog (in no particular
order):

  Tokuhiro Matsuno
  Kazuhiro Osawa
  Yuval Kogman
  Kazuho Oku
  Alexis Sukrieh
  Takatoshi Kitano
  Stevan Little
  Daisuke Murase
  mala
  Pedro Melo
  Jesse Luehrs
  John Beppu
  Shawn M Moore
  Mark Stosberg
  Matt S Trout
  Jesse Vincent
  Chia-liang Kao
  Dave Rolsky
  Hans Dieter Pearcey
  Randy J Ray
  Benjamin Trott
  Max Maischein
  Slaven Rezić
  Marcel Grünauer
  Masayoshi Sekimura
  Brock Wilcox
  Piers Cawley
  Daisuke Maki
  Kang-min Liu
  Yasuhiro Matsumoto
  Ash Berlin
  Artur Bergman
  Simon Cozens
  Scott McWhirter
  Jiro Nishiguchi
  Masahiro Chiba
  Patrick Donelan
  Paul Driver

=head1 COPYRIGHT AND LICENSE

Copyright Tatsuhiko Miyagawa, 2009.

This document is licensed under the Creative Commons license by-sa.

=cut
