]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Compliance: remove Content-Length header if Transfer-Encoding is present.
authorAlex Rousskov <rousskov@measurement-factory.com>
Tue, 24 Aug 2010 04:18:51 +0000 (22:18 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Tue, 24 Aug 2010 04:18:51 +0000 (22:18 -0600)
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 ffd9fbaaba1352bb4231211a1cbe47ab77a79b55..0f597654a17f070352970f63c06752ad99ad91d6 100644 (file)
@@ -254,6 +254,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 */
@@ -279,4 +280,11 @@ SQUIDCEXTERN int httpHeaderHasByNameListMember(const HttpHeader * hdr, const cha
 SQUIDCEXTERN void httpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh, const HttpHeaderMask * denied_mask);
 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 8a5950a92a474949dd297b6f297516f1a06bf5a7..5c55886cb73d8ceb7faa252fca85a34dc3672b7b 100644 (file)
@@ -541,7 +541,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 d79704ba3d7cf84f0e860879cdd5a0cd4e78421f..de1e5229dc689cc74c05f59b0409f3d19605b732 100644 (file)
@@ -498,7 +498,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;
@@ -506,7 +506,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 921ff931dae6755437254bbed3026bfb7e8300d4..ee33f79ceeb5962e35a1117a970f307be247d773 100644 (file)
@@ -1988,8 +1988,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 82c5c0b2b1f29a815a49ea724defb272ea44b08d..3d1d8bdc788845d01941e6698fcddb855f4a72d9 100644 (file)
@@ -726,7 +726,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;
     }