]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: lua: HTTP services must take care of body-less status codes
authorWilly Tarreau <w@1wt.eu>
Wed, 23 Aug 2017 07:10:38 +0000 (09:10 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 23 Aug 2017 14:11:38 +0000 (16:11 +0200)
The following Lua code causes emission of a final chunk after the body,
which is wrong :

core.register_service("send204", "http", function(applet)
   applet:set_status(204)
   applet:start_response()
end)

Indeed, responses with status codes 1xx, 204 and 304 do not contain any
body and the message ends immediately after the empty header (cf RFC7230)
so by emitting a 0<CR><LF> we're disturbing keep-alive responses. There's
a workaround against this for now which consists in always emitting
"Content-length: 0" but it may not be cool with 304 when clients use
the headers to update their cache.

This fix must be backported to stable versions back to 1.6.

src/hlua.c

index bd3674a5515a8ca7a2cfade1aa7fda4c4fa7ae5d..d12c80b131d7b7ea9732524a957b3a34b933c548 100644 (file)
@@ -4307,12 +4307,17 @@ __LJMP static int hlua_applet_http_start_response(lua_State *L)
        if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11 && !hdr_connection)
                chunk_appendf(tmp, "Connection: close\r\n");
 
-       /* If we dont have a content-length set, we must announce a transfer enconding
-        * chunked. This is required by haproxy for the keepalive compliance.
-        * If the applet annouce a transfer-encoding chunked itslef, don't
-        * do anything.
+       /* If we dont have a content-length set, and the HTTP version is 1.1
+        * and the status code implies the presence of a message body, we must
+        * announce a transfer encoding chunked. This is required by haproxy
+        * for the keepalive compliance. If the applet annouces a transfer-encoding
+        * chunked itslef, don't do anything.
         */
-       if (hdr_contentlength == -1 && hdr_chunked == 0) {
+       if (hdr_contentlength == -1 && hdr_chunked == 0 &&
+           (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11) &&
+           appctx->appctx->ctx.hlua_apphttp.status >= 200 &&
+           appctx->appctx->ctx.hlua_apphttp.status != 204 &&
+           appctx->appctx->ctx.hlua_apphttp.status != 304) {
                chunk_appendf(tmp, "Transfer-encoding: chunked\r\n");
                appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_CHUNKED;
        }