- From: Roy T. Fielding <fielding@avron.ICS.UCI.EDU>
- Date: Tue, 10 Oct 1995 17:35:40 -0700
- To: http-wg%cuckoo.hpl.hp.com@hplb.hpl.hp.com
- Cc: efrank@ncsa.uiuc.edu
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