Keep-Alive Notes

Several people have asked me about the notes I sent around after the
San Jose conference regarding the Connection and Keep-Alive headers,
upon which the NCSA, Spyglass, and a number of other implementations
of Keep-Alive were based.  Since I needed to rewrite them for HTTP/1.1
anyway, here is the latest version, leaving out the discussion of
the MGET and OPTIONS methods and concentrating on what seems to work.

Please check them against your implementations and let me know if
there are any problems.

.....Roy
======================================================================
Keep-Alive Notes
================

In order for persistent connections to work properly in HTTP, there
needs to be an easy mechanism whereby all parties to the HTTP communication
can signal the desire for connection persistence and a willingness to
abide by the stricter message requirements of HTTP/1.1.  These features
can be implemented with HTTP/1.0, but cannot be used reliably with old
proxies and gateways until a new protocol version can be indicated.

The primary mechanism is the Connection header field:

    Connection  = "Connection" ":" 1#field-name      ; (see HTTP BNF)

    [NOTE: field-names are case-insensitive]

The Connection header is a list of header field names or keywords
that apply only to the immediate connection (i.e., the connection with
the next closest client or server along a possible request/response chain).
For example,

   Connection: Keep-Alive, Fred
   Keep-Alive: timeout=10, max=5

Proxies are required to remove or rewrite (replace with their own
connection options) the Connection header and any of the header fields
named by the Connection header.  This prevents the problem of connection
options being propagated beyond the immediate connection.  If a name given
by the Connection header does not correspond to a separate header field
(like Fred in the above example), then it is treated as a keyword token
without any attributes.  This allows for a minimal syntax to provide
connection-based options without pre-restricting the syntax or number
of those options.


The second mechanism is the Keep-Alive keyword/header field:

   Keep-Alive  = "Keep-Alive" ":" 1#( token ["=" word ] )

The presence of the Keep-Alive keyword in a Connection header signals
that the sender wishes to maintain a persistent connection.  The presence
of a Keep-Alive header field defines parameters for the persistence.

So, the client can send 

   Connection: keep-alive

to indicate that it desires a multiple-request session, and 
the server responds with

   Connection: keep-alive
   Keep-Alive: max=20, timeout=10

to indicate that the session is being kept alive for a maximum of
20 requests and a per-request timeout of 10 seconds.  The Connection header
with keep-alive keyword must be sent on all requests and responses that
wish to continue the persistence.  The client sends requests as normal
and the server responds as normal, except that all messages containing
an entity body must have an accurate content-length (or, if HTTP/1.1 is
used by the recipient, a chunked transfer encoding). 

The persistent connection ends when either side closes the connection or
after the receipt of a response which lacks the Keep-Alive keyword. 
The server may close the connection immediately after responding to a
request without a Keep-Alive keyword.  A client can tell if the
connection will close by looking for a Keep-Alive in the response.

The actual parameters of the Keep-Alive exchange are still unknown and
open for experimentation.  The initial idea of using "max" and "timeout"
to indicate session-length preference (on requests) and actuals
(on responses) is optional.  Another possibility is

   Keep-Alive: state="Accept,Accept-Language,..."

for indicating which header fields can be or have been stored as a
persistent request state.  This would allow the server to decide whether
or not to be stateless in its request handling, and the amount of state
it is willing/able to retain, while at the same time allowing each
request to override the saved state with or without changing what is saved.


The third mechanism is the chunked Transfer-Encoding which will be
available in HTTP/1.1.

   Transfer-Encoding  = "Transfer-Encoding" : 1#( token *(";" param))

as in

   Transfer-Encoding: chunked

The chunked transfer encoding allows the message Entity-Body length
to be determined dynamically as a sequence of data chunks prefixed by
a chunk size, ended with a zero-size chunk, and followed by a footer
containing additional entity-header fields.

   Chunky-Body = *( chunk ) 
                 "0" CRLF
                 footer
                 CRLF
 
   chunk       = chunk-size CRLF chunk-data CRLF
 
   chunk-size  = hex-no-zero *hex
 
   chunk-data  = chunk-size(OCTET)
 
   footer      = *( Entity-Header )
 
   hex         = "0" | hex-no-zero
   hex-no-zero = "1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
               | "A"|"B"|"C"|"D"|"E"|"F"
               | "a"|"b"|"c"|"d"|"e"|"f"

Chunking the content makes the protocol output identical to normal
buffered writes, and thus is trivial to implement and very fast.
In addition, it allows the server to append a dynamically generated
signature to dynamically generated content -- a required feature for
some security applications.

There are still other mechanisms which will be available for allowing
multiple requests/responses per message, such as the WRAPPED method and
restricted multipart types, but I won't be able to describe those until
I can find (or write) a working implementation.

 ...Roy T. Fielding
    Department of Information & Computer Science    (fielding@ics.uci.edu)
    University of California, Irvine, CA 92717-3425    fax:+1(714)824-4056
    http://www.ics.uci.edu/~fielding/

Received on Tuesday, 10 October 1995 17:47:35 UTC