HTTP/1.1 Specification Errata

Canonical URL to the Latest Version: http://purl.org/NET/http-errata
Last modified: 2004-10-27

This page collects the known errata in the two RFCs that specify HTTP/1.1:

New drafts of both of the above are being prepared now, incorporating all of the following corrections, in preparation for requesting that they be advanced to full Standard status. If you have an issue with any of these resolutions, or if you think that you've found another, you should post it to the HTTP Working Group list and get the issue discussed there as soon as possible.

This page is maintained by Scott Lawrence, but I don't normally add to it based only on my own judgement; I prefer to see rough consensus on the list that there is an error (and the fix).

HTTP Working Group List

List Address
ietf-http-wg@w3.org
To subscribe, send mail to ietf-http-wg-request@w3.org with just the word 'subscribe' in the body
List Archive
W3C Archive (Current)
Old HTTP Working Group Mail Archive

Other Resources:

Index:

The links to specification sections below go to HTML (and therefor unofficial) versions of the specs produced by Chris Newman, then at Innosoft. The corporate successor to Innosoft does not appear to have maintained that archive, but it can still be found at http://www.apps.ietf.org/rfc/ .



RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1

HTTP Version should be case sensitive

[Archive Mail]

In general, quoted string literals in the spec are defined to be case insensitive, but the HTTP Version token should be case sensitive. In section 3.1 it says:

   The version of an HTTP message is indicated by an HTTP-Version field
   in the first line of the message.

       HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT

It should add:

   The version of an HTTP message is indicated by an HTTP-Version field
   in the first line of the message.HTTP-Version is case-sensitive.

       HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT

'unsafe' characters

[Archive Mail]

In the rules for comparison of URIs [section 3.2.3], it says:

    Characters other than those in the "reserved" and "unsafe" sets (see
    RFC 2396 [42]) are equivalent to their ""%" HEX HEX" encoding.

but RFC 2396 has no definition of a character set called "unsafe".

The paragraph should read:

    Characters other than those in the "reserved" set (see
    RFC 2396 [42]) are equivalent to their ""%" HEX HEX" encoding.

This was an historical artifact. An earlier HTTP draft had defined a set of 'unsafe' characters, but they were characters that were not valid in a URI, so making a special case in the comparison rule was not needed.

Chunk Size Definition

[Archive Mail]

In the description of chunked transfer encoding [section 3.6.1], the syntax for a chunk is given as:

        chunk          = chunk-size [ chunk-extension ] CRLF
                         chunk-data CRLF

The accompanying text defines chunk-size incorrectly as:

The chunk-size field is a string of hex digits indicating the size of the chunk.

This doesn't correctly describe what octets the chunk-size field is counting; it should be:

The chunk-size field is a string of hex digits indicating the size of the chunk-data in octets.

(in other words, the chunk length does not include the count of the octets in the chunk header and trailer).

Message Length

[Archive Mail]

In the discussion of how to determine the message length [section 4.4], the fourth possibility somehow lost a number of characters. The spec says:

   4.If the message uses the media type "multipart/byteranges", and the
     ransfer-length is not otherwise specified, then this self-
     elimiting media type defines the transfer-length. This media type
     UST NOT be used unless the sender knows that the recipient can arse
     it; the presence in a request of a Range header with ultiple byte-
     range specifiers from a 1.1 client implies that the lient can parse
     multipart/byteranges responses.

It should read:

   4.If the message uses the media type "multipart/byteranges", and the
     transfer-length is not otherwise specified, then this self-
     delimiting media type defines the transfer-length. This media type
     MUST NOT be used unless the sender knows that the recipient can parse
     it; the presence in a request of a Range header with multiple byte-
     range specifiers from a 1.1 client implies that the client can parse
     multipart/byteranges responses.

Via is a MUST

In the description of the Server header [section 14.38], the Via field is described as a SHOULD:

If the response is being forwarded through a proxy, the proxy application MUST NOT modify the Server response-header. Instead, it SHOULD include a Via field (as described in section 14.45).
It should be a MUST:
If the response is being forwarded through a proxy, the proxy application MUST NOT modify the Server response-header. Instead, it MUST include a Via field (as described in section 14.45).
The requirement is stated correctly in the description of the Via header, [section 14.45].

Fragments allowed in Location

[Archive Mail]

In the description of the Location header [section 14.30], the ABNF for the Location header is given as:

    Location       = "Location" ":" absoluteURI

This and the accompanying text are incorrect because the definition of 'absoluteURI', given in RFC 2396 does not include fragement identifiers. The correct syntax for the Location header is:

    Location       = "Location" ":" absoluteURI [ "#" fragment ]

There are circumstances in which a fragment identifier in a Location URL would not be appropriate:

At present, the behavior in the case where there was a fragment with the original URI, e.g.: http://host1.example.com/resource1#fragment1 where /resource1 redirects to http://host2.example.com/resource2#fragment2 is 'fragment1' discarded? Do you find fragment2 and then find fragment1 within it? We don't have fragment combination rules.

Editors Notes

[Archive Mail]

In the references [section 17], markers for the editors notes got left in; they are meaningless and can be safely ignored. They are:

[jg639] [jg640] [jg641] [jg642] [jg643] [jg644] [jg645] [jg646] [jg647]

Media Type Registrations

[Archive Mail]

In the description of Internet Media Types in [section 3.7], the wrong RFC is cited for the media type registration process. The text says:

Media-type values are registered with the Internet Assigned Number Authority (IANA [19]). The media type registration process is outlined in RFC 4288 [17]. Use of non-registered media types is discouraged.

But should be:

Media-type values are registered with the Internet Assigned Number Authority (IANA [19]). The media type registration process is outlined in RFC 2048 [17]. Use of non-registered media types is discouraged.

The cited Reference [section 17] is also incorrect; it is:

   [17] Postel, J., "Media Type Registration Procedure", RFC 1590,
        November 1996.

(oddly, the date cited is wrong for that RFC and correct for the right one) It should be:

   [17] Freed, N., Klensin, J., and Postel, J., "Mulitpurpose Internet Mail
        Extensions (MIME) Part Four: Registration Procedure", RFC 2048,
        November 1996.

Trailer

[Archive Mail]

In [section 13.5.1], which describes End-to-End and Hop-by-Hop headers, the text says:

   The following HTTP/1.1 headers are hop-by-hop headers:

      - Connection
      - Keep-Alive
      - Proxy-Authenticate
      - Proxy-Authorization
      - TE
      - Trailers
      - Transfer-Encoding
      - Upgrade

But the correct header name is 'Trailer' (no 's'):

   The following HTTP/1.1 headers are hop-by-hop headers:

      - Connection
      - Keep-Alive
      - Proxy-Authenticate
      - Proxy-Authorization
      - TE
      - Trailer
      - Transfer-Encoding
      - Upgrade

Safe Methods vs Redirection

[Archive Mail]

Section 10.3.2 (301 Moved Permanently) contains the paragraph

   If the 301 status code is received in response to a request other
   than GET or HEAD, the user agent MUST NOT automatically redirect the
   request unless it can be confirmed by the user, since this might
   change the conditions under which the request was issued.

which fails to consider that there are many other request methods that are safe to automatically redirect, and further that the user agent is able to make that determination based on the request method semantics. In particular, the OPTIONS method is always safe to automatically redirect. Unfortunately, the paragraph was written long before there was OPTIONS, and was never updated to reflect the extensibility of methods. The same problem paragraph is found in sections 10.3.3 and 10.3.8.

The above should be replaced with

   If the 301 status code is received in response to a request method
   that is known to be "safe", as defined in section 9.1.1, then the
   request MAY be automatically redirected by the user agent without
   confirmation.  Otherwise, the user agent MUST NOT automatically
   redirect the request unless it is confirmed by the user, since the
   new URI might change the conditions under which the request was issued.

along with similar changes for sections 10.3.3 and 10.3.8. It would also be helpful for each of the method definition sections to specifically define whether or not the method is safe. OPTIONS, GET, and HEAD are all safe in RFC 2616. HTTP extensions like WebDAV define additional safe methods.

URI includes query

[Archive Mail]

Section 5.1.2 defines a Request-URI as:

    Request-URI    = "*" | absoluteURI | abs_path | authority

where it gets abs_path by reference to RFC 2396; however, the abs_path in RFC 2396 doesn't include a possible query part:

    hier_part     = ( net_path | abs_path ) [ "?" query ]
    net_path      = "//" authority [ abs_path ]
    abs_path      = "/"  path_segments

The definition of Request-URI should be:

    Request-URI   = "*" | absoluteURI | abs_path [ "?" query ] | authority

Invalidation after Update or Delete

[Archive Mail]

There is some ambiguity in Section13.10 as to how the word 'only' binds here:

In order to prevent denial of service attacks, an invalidation based on the URI in a Location or Content-Location header MUST only be performed if the host part is the same as in the Request-URI.

The following clarification, along with separating the clause explaining the rationale for the rule, is suggested:

An invalidation based on the URI in a Location or Content-Location header MUST NOT be performed if the host part of that URI differs from the host part in the Request-URI. This helps prevent denial of service attacks.

Updated reference for language tags

RFC 1766, which is referenced by RFC 2616 section 3.10 as the source for its definition of language tags has a BNF has been updated by RFC3066 (a BCP).

RFC 3066 defines these as:

   Language-Tag = Primary-subtag *( "-" Subtag )
   Primary-subtag = 1*8ALPHA
   Subtag = 1*8(ALPHA / DIGIT)

HTTP/1.1 RFC 2616 defines these as:

language-tag  = primary-tag *( "-" subtag )
primary-tag   = 1*8ALPHA
subtag        = 1*8ALPHA

The HTTP BNF will be relaxed to remove the inconsistency.

Clarification regarding quoting of charset values

[Archive Mail]

In order to clarify when charset values may be quoted, the following is added to section 3.4:

HTTP uses charset in two contexts: within an Accept-Charset request header (in which the charset value is an unquoted token) and as the value of a parameter in a Content-type header (within a request or response), in which case the parameter value of the charset parameter may be quoted.

No close on 1xx responses

[Archive Mail]

Section 14.10 says:

HTTP/1.1 applications that do not support persistent connections MUST include the "close" connection option in every message.

it should say:

An HTTP/1.1 client that does not support persistent connections MUST include the "close" connection option in every request message.

An HTTP/1.1 server that does not support persistent connections MUST include the "close" connection option in every response message that does not have a 1xx (informational) status code.

Remove 'identity' token references

[Archive Mail]

The "identity" transfer coding was removed, but some references to it were not.

In section 3.6, remove reference to non-existant section

The Internet Assigned Numbers Authority (IANA) acts as a registry for transfer-coding value tokens. Initially, the registry contains the following tokens: "chunked" (section 3.6.1), "identity" (section 3.6.2), "gzip" (section 3.5), "compress" (section 3.5), and "deflate" (section 3.5).

The Internet Assigned Numbers Authority (IANA) acts as a registry for transfer-coding value tokens. Initially, the registry contains the following tokens: "chunked" (section 3.6.1), "gzip" (section 3.5), "compress" (section 3.5), and "deflate" (section 3.5).

In section 4.4 remove 'other than identity' for Transfer-Encoding case since identity is not a valid value.

2.If a Transfer-Encoding header field (section 14.41) is present and has any value other than "identity", then the transfer-length is defined by use of the "chunked" transfer-coding (section 3.6), unless the message is terminated by closing the connection.

2.If a Transfer-Encoding header field (section 14.41) is present, then the transfer-length is defined by use of the "chunked" transfer-coding (section 3.6), unless the message is terminated by closing the connection.

Messages MUST NOT include both a Content-Length header field and a non-identity transfer-coding. If the message does include a non- identity transfer-coding, the Content-Length MUST be ignored.

Messages MUST NOT include both a Content-Length header field and a transfer-coding. If the message does include a transfer-coding, the Content-Length MUST be ignored.

In section 19.4.5 remove 'identity' CTE

HTTP does not use the Content-Transfer-Encoding (CTE) field of RFC 2045. Proxies and gateways from MIME-compliant protocols to HTTP MUST remove any non-identity CTE ("quoted-printable" or "base64") encoding prior to delivering the response message to an HTTP client.

HTTP does not use the Content-Transfer-Encoding (CTE) field of RFC 2045. Proxies and gateways from MIME-compliant protocols to HTTP MUST remove any CTE encoding prior to delivering the response message to an HTTP client.

Revise description of the POST method

[Archive Mail]

The description of POST was broadened over time, and is not clear. It is clarified by the following changes in Section 9.5:

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.

The POST method is used to request that the origin server accept the entity enclosed in the request as data to be processed by the resource identified by the Request-URI in the Request-Line.

The actual function performed by the POST method is determined by the server and is usually dependent on the Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate to a database.

The actual function performed by the POST method is determined by the server and is usually dependent on the Request-URI.

Cache validators in 206 responses

[Archive Mail]

In Section 10.2.7 the spec implies that it may be ok to use a weak cache validator in a 206 response. The correct language is more restrictive.

If the 206 response is the result of an If-Range request that used a strong cache validator (see section 13.3.3), the response SHOULD NOT include other entity-headers. If the response is the result of an If-Range request that used a weak validator, the response MUST NOT include other entity-headers; this prevents inconsistencies between cached entity-bodies and updated headers. Otherwise, the response MUST include all of the entity-headers that would have been returned with a 200 (OK) response to the same request.

If the 206 response is the result of an If-Range request, the response SHOULD NOT include other entity-headers. Otherwise, the response MUST include all of the entity-headers that would have been returned with a 200 (OK) response to the same request.



RFC 2617: HTTP Authentication: Basic and Digest Access Authentication

ABNF for the Domain Attribute

[Archive Mail]

The domain attribute should be, as described in [section 3.2.1], "a quoted, space-separated list of URIs", but the ABNF given is:

    domain = "domain" "=" <"> URI ( 1*SP URI ) <">

That describes exactly two space-separated URIs. It should be:

    domain = "domain" "=" <"> URI *( 1*SP URI ) <">

H(A1) sample in md5-sess mode

[Archive Mail]

The sample implementation of the calculation for H(A1) in [section 5] is incorrect. It left out the step of converting the hash of "user:realm:password" to hex encoding before including it into the calculation of the session key hash. The text and ABNF are correct.

With the page break removed the incorrect code for the function DigestCalcHA1 is:

      /* calculate H(A1) as per spec */
      void DigestCalcHA1(
          IN char * pszAlg,
          IN char * pszUserName,
          IN char * pszRealm,
          IN char * pszPassword,
          IN char * pszNonce,
          IN char * pszCNonce,
          OUT HASHHEX SessionKey
          )
      {
            MD5_CTX Md5Ctx;
            HASH HA1;

            MD5Init(&Md5Ctx);
            MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName));
            MD5Update(&Md5Ctx, ":", 1);
            MD5Update(&Md5Ctx, pszRealm, strlen(pszRealm));
            MD5Update(&Md5Ctx, ":", 1);
            MD5Update(&Md5Ctx, pszPassword, strlen(pszPassword));
            MD5Final(HA1, &Md5Ctx);
            if (stricmp(pszAlg, "md5-sess") == 0) {
                  MD5Init(&Md5Ctx);
                  MD5Update(&Md5Ctx, HA1, HASHLEN);
                  MD5Update(&Md5Ctx, ":", 1);
                  MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce));
                  MD5Update(&Md5Ctx, ":", 1);
                  MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce));
                  MD5Final(HA1, &Md5Ctx);
            };
            CvtHex(HA1, SessionKey);
      };

it should be:

      /* calculate H(A1) as per spec */
      void DigestCalcHA1(
          IN char * pszAlg,
          IN char * pszUserName,
          IN char * pszRealm,
          IN char * pszPassword,
          IN char * pszNonce,
          IN char * pszCNonce,
          OUT HASHHEX SessionKey
          )
      {
            MD5_CTX Md5Ctx;
            HASH HA1;

            MD5Init(&Md5Ctx);
            MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName));
            MD5Update(&Md5Ctx, ":", 1);
            MD5Update(&Md5Ctx, pszRealm, strlen(pszRealm));
            MD5Update(&Md5Ctx, ":", 1);
            MD5Update(&Md5Ctx, pszPassword, strlen(pszPassword));
            MD5Final(HA1, &Md5Ctx);
            if (stricmp(pszAlg, "md5-sess") == 0) {
                  CvtHex(HA1, HA1Hex);
                  MD5Init(&Md5Ctx);
                  MD5Update(&Md5Ctx, HA1Hex, HASHHEXLEN);
                  MD5Update(&Md5Ctx, ":", 1);
                  MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce));
                  MD5Update(&Md5Ctx, ":", 1);
                  MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce));
                  MD5Final(HA1, &Md5Ctx);
            };
            CvtHex(HA1, SessionKey);
      };