This specification aims to formalize the Strata protocol for building web
applications using the node.js JavaScript platform. You can (and should) use
the strata.lint middleware to enforce it. When you develop middleware, be sure
to add a strata.lint before and after to catch all mistakes.

# Applications

A Strata application is a function that takes exactly two arguments: the
*environment* and a *callback*.

## The Environment

The environment is an object that contains CGI-like properties. It MUST include
the following:

  - protocol          The request protocol. Must be "http:" or "https:"
  - protocolVersion   The version of the protocol used in the request
  - requestMethod     The request method (e.g. "GET" or "POST")
  - requestTime       A Date that indicates the time the request was received
  - remoteAddr        The IP address of the client
  - remotePort        The number of the port on the client that is being used.
                      May be 0 if unknown
  - serverName        The host name of the server. Defaults to the value of
                      process.env.SERVER_NAME or the bound address of the server
                      as reported by the operating system
  - serverPort        The number of the TCP port the server is bound to. May be
                      0 when using Unix domain sockets
  - scriptName        The initial portion of the request URL's "path" that
                      corresponds to the application, so that it knows its
                      virtual "location". This may be an empty string, if the
                      application corresponds to the "root" of the server
  - pathInfo          The remainder of the request URL's "path", designating
                      the virtual "location" of the target resource within the
                      application. This may be an empty string if the request
                      URL targets the "root" of the application and does not
                      have a trailing slash. This value may be percent-encoded
                      when originating from a URL
  - queryString       The portion of the request URL that follows the "?", if
                      any. May be an empty string
  - headers           An object of client-supplied HTTP headers and their values.
                      All header names must be lower-cased
  - input             A readable Stream of data contained in the request body
  - error             A writable Stream for error output
  - strataVersion     A string that indicates the current version of strata

In addition to these, the environment MAY include the following properties:

  - flash             A string containing the flash message, if any. This is a
                      message that was set using the flash module and is
                      available to all applications downstream from a
                      strata.flash middleware
  - remoteUser        A string containing the name of the authorized user when
                      using HTTP basic auth. Available to all applications
                      downstream from a strata.basicAuth middleware
  - route             An object containing information about the route that was
                      triggered. Available to all applications downstream from a
                      strata.Router application
  - session           An object containing session data. Available to all
                      applications downstream from a strata.sessionCookie
                      middleware
  - timeout           The numerical id of the timeout set by the timeout
                      middleware. May be used by downstream apps to cancel the
                      timeout using clearTimeout

When combined with scriptName and pathInfo, the serverName and serverPort
variables may be used to reconstruct the original request URL. Note, however,
that if httpHost is present it should be used in preference to serverName.

There are the following additional restrictions:

  - requestMethod must be a valid HTTP verb as an uppercase String
  - scriptName and pathInfo, if not empty, should start with a "/"
  - scriptName should never be "/" but instead be empty
  - pathInfo should be "/" if scriptName is empty
  - headers['content-length'], if given, must consist of only digits
  - input must be paused

The application is free to modify the environment. Property names must be
prefixed uniquely. The prefix "strata" is reserved for use within the Strata
core distribution and other accepted specifications and is not available for
use elsewhere.

## The Callback

The callback is used to issue a response to the client and must be called with
exactly three arguments: the response *status*, HTTP *headers*, and *body*.

### The Status

The status must be an HTTP status code as a Number.

### The Headers

The headers must be an object whose properties are the names of HTTP headers in
their canonical form (i.e. "Content-Type" instead of "content-type"). Header
names may contain only letters, digits, "-", and "_" and must start with a
letter and must not end with a "-" or "_". If more than one value for a header
is required, the value for that property must be an array. Otherwise it may be
a string or a number.

There must be a Content-Type header, except for when the status is 1xx, 204, or
304, in which case there must be none given.

There must not be a Content-Length header when the status is 1xx, 204, or 304,
or it must be "0".

### The Body

The body must be either a string or a readable Stream. If it is a Stream, the
response will be pumped through to the client.

# Acknowledgements

Some parts of this specification are adopted from PEP333: Python Web Server
Gateway Interface v1.0 (http://www.python.org/dev/peps/pep-0333/) and the Rack
specification (http://rack.rubyforge.org/doc/files/SPEC.html).