]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Author: Alex Rousskov <rousskov@measurement-factory.com>
authorAmos Jeffries <amosjeffries@squid-cache.org>
Fri, 27 Aug 2010 16:46:02 +0000 (10:46 -0600)
committerAmos Jeffries <amosjeffries@squid-cache.org>
Fri, 27 Aug 2010 16:46:02 +0000 (10:46 -0600)
HTTP Compliance: remove Content-Length header if Transfer-Encoding is present.

If after HTTP header parsing we have both "Transfer-Encoding: chunked"
and Content-Length headers, remove the Content-Length entry. The
adjusted behavior follows httpbis recommendations (ticket #95, part 2).

The old client-side code forwarded the original Content-Length header
which did not match the [dechunked] response, resulting in a malformed
response.

HttpHeader::chunked() method added to check if HTTP headers contain
chunked Transfer-Encoding header. Use this method in code that checks
for chunked encoding.

Co-Advisor test cases: test_case/rfc2616/chunked-1p0-badClen-toClt
                       test_case/rfc2616/chunked-1p1-badClen-toClt

src/HttpHeader.cc
src/HttpHeader.h
src/HttpReply.cc
src/HttpRequest.cc
src/client_side.cc
src/http.cc

index b1f7f6e390986f781651e875da7e47ec51ecb63f..38807f4d8b6f2d7be3c4494af54000e8108fa213 100644 (file)
@@ -647,6 +647,11 @@ HttpHeader::parse(const char *header_start, const char *header_end)
         addEntry(e);
     }
 
+    if (chunked()) {
+        // RFC 2616 section 4.4: ignore Content-Length with Transfer-Encoding
+        delById(HDR_CONTENT_LENGTH);
+    }
+
     PROF_stop(HttpHeaderParse);
     return 1;                  /* even if no fields where found, it is a valid header */
 reset:
index e7a26a38131d7b33ff712b6ab79301d96c420111..d37ad2920024123378033973f6490770adb3dc27 100644 (file)
@@ -255,6 +255,7 @@ public:
     int hasListMember(http_hdr_type id, const char *member, const char separator) const;
     int hasByNameListMember(const char *name, const char *member, const char separator) const;
     void removeHopByHopEntries();
+    inline bool chunked() const; ///< whether message uses chunked Transfer-Encoding
 
     /* protected, do not use these, use interface functions instead */
     Vector<HttpHeaderEntry *> entries;         /**< parsed fields in raw format */
@@ -282,4 +283,11 @@ int httpMsgIsPersistent(HttpVersion const &http_ver, const HttpHeader * hdr);
 
 SQUIDCEXTERN void httpHeaderCalcMask(HttpHeaderMask * mask, http_hdr_type http_hdr_type_enums[], size_t count);
 
+inline bool
+HttpHeader::chunked() const
+{
+    return has(HDR_TRANSFER_ENCODING) &&
+               hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',');
+}
+
 #endif /* SQUID_HTTPHEADER_H */
index f82a1bd803714d757d0113877e8ef608c7499d5a..6110a2b2a3375283516e09990f76a92c0a0bdbc5 100644 (file)
@@ -540,7 +540,7 @@ HttpReply::expectingBody(const HttpRequestMethod& req_method, int64_t& theSize)
         expectBody = true;
 
     if (expectBody) {
-        if (header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ','))
+        if (header.chunked())
             theSize = -1;
         else if (content_length >= 0)
             theSize = content_length;
index 006583d53b8d870efc8b31d7635519987b758611..ca1637e0aee17e2171adbf9578155870106e099c 100644 (file)
@@ -492,7 +492,7 @@ HttpRequest::expectingBody(const HttpRequestMethod& unused, int64_t& theSize) co
         expectBody = Config.onoff.request_entities ? true : false;
     else if (method == METHOD_PUT || method == METHOD_POST)
         expectBody = true;
-    else if (header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ','))
+    else if (header.chunked())
         expectBody = true;
     else if (content_length >= 0)
         expectBody = true;
@@ -500,7 +500,7 @@ HttpRequest::expectingBody(const HttpRequestMethod& unused, int64_t& theSize) co
         expectBody = false;
 
     if (expectBody) {
-        if (header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ','))
+        if (header.chunked())
             theSize = -1;
         else if (content_length >= 0)
             theSize = content_length;
index 315ac0f9b76b4a3f162721ff8a476792f635bc0b..b3e342bbb6470ffddcde8b2aa47e376077ebbceb 100644 (file)
@@ -1935,8 +1935,7 @@ isChunkedRequest(const HttpParser *hp)
     if (!request.parseHeader(HttpParserHdrBuf(hp), HttpParserHdrSz(hp)))
         return false;
 
-    return request.header.has(HDR_TRANSFER_ENCODING) &&
-           request.header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',');
+    return request.header.chunked();
 }
 
 
index 2906a3808de5450711c81dc6100c3dd0653e0dd4..7956a8ab6cf7351998082186deedc2bd164db9e2 100644 (file)
@@ -729,7 +729,7 @@ HttpStateData::processReplyHeader()
     }
 
     flags.chunked = 0;
-    if (newrep->sline.protocol == PROTO_HTTP && newrep->header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',')) {
+    if (newrep->sline.protocol == PROTO_HTTP && newrep->header.chunked()) {
         flags.chunked = 1;
         httpChunkDecoder = new ChunkedCodingParser;
     }