[git commit] httpd: When sending gzipped content use content-length header

Denys Vlasenko vda.linux at googlemail.com
Wed Apr 17 09:34:49 UTC 2019


commit: https://git.busybox.net/busybox/commit/?id=210b52476c86fb8411f6b0fd12d4e76875c474e5
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

Today for gzipped content httpd is using a header with name
Transfer-Length. However I can't find a header with that name in the
standards. Instead use Content-Length.

function                                             old     new   delta
.rodata                                           157940  157936      -4
send_headers                                         980     939     -41
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-45)             Total: -45 bytes

Signed-off-by: Alexander Vickberg <wickbergster at gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/httpd.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/networking/httpd.c b/networking/httpd.c
index 2b0acd7dc..0f4f22669 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -1150,18 +1150,61 @@ static void send_headers(unsigned responseNum)
 			file_size = range_end - range_start + 1;
 		}
 #endif
+
+//RFC 2616 4.4 Message Length
+// The transfer-length of a message is the length of the message-body as
+// it appears in the message; that is, after any transfer-codings have
+// been applied. When a message-body is included with a message, the
+// transfer-length of that body is determined by one of the following
+// (in order of precedence):
+// 1.Any response message which "MUST NOT" include a message-body (such
+//   as the 1xx, 204, and 304 responses and any response to a HEAD
+//   request) is always terminated by the first empty line after the
+//   header fields, regardless of the entity-header fields present in
+//   the message.
+// 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.
+// 3.If a Content-Length header field (section 14.13) is present, its
+//   decimal value in OCTETs represents both the entity-length and the
+//   transfer-length. The Content-Length header field MUST NOT be sent
+//   if these two lengths are different (i.e., if a Transfer-Encoding
+//   header field is present). If a message is received with both a
+//   Transfer-Encoding header field and a Content-Length header field,
+//   the latter MUST be ignored.
+// 4.If the message uses the media type "multipart/byteranges" ...
+// 5.By the server closing the connection.
+//
+// (NB: standards do not define "Transfer-Length:" _header_,
+// transfer-length above is just a concept).
+
 		len += sprintf(iobuf + len,
 #if ENABLE_FEATURE_HTTPD_RANGES
 			"Accept-Ranges: bytes\r\n"
 #endif
 			"Last-Modified: %s\r\n"
-			"%s-Length: %"OFF_FMT"u\r\n",
+	/* Because of 4.4 (5), we can forgo sending of "Content-Length"
+	 * since we close connection afterwards, but it helps clients
+	 * to e.g. estimate download times, show progress bars etc.
+	 * Theoretically we should not send it if page is compressed,
+	 * but de-facto standard is to send it (see comment below).
+	 */
+			"Content-Length: %"OFF_FMT"u\r\n",
 				date_str,
-				content_gzip ? "Transfer" : "Content",
 				file_size
 		);
 	}
 
+	/* This should be "Transfer-Encoding", not "Content-Encoding":
+	 * "data is compressed for transfer", not "data is an archive".
+	 * But many clients were not handling "Transfer-Encoding" correctly
+	 * (they were not uncompressing gzipped pages, tried to show
+	 * raw compressed data), and servers worked around it by using
+	 * "Content-Encoding" instead... and this become de-facto standard.
+	 * https://bugzilla.mozilla.org/show_bug.cgi?id=68517
+	 * https://bugs.chromium.org/p/chromium/issues/detail?id=94730
+	 */
 	if (content_gzip)
 		len += sprintf(iobuf + len, "Content-Encoding: gzip\r\n");
 


More information about the busybox-cvs mailing list