From 06c75fec1783f1641b11f627be06f7df26e9d282 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 23 Aug 2017 09:10:38 +0200 Subject: [PATCH] BUG/MEDIUM: lua: HTTP services must take care of body-less status codes 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 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 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/hlua.c b/src/hlua.c index bd3674a55..d12c80b13 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -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; }