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<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.
This commit is contained in:
Willy Tarreau 2017-08-23 09:10:38 +02:00
parent d958741886
commit 06c75fec17

View 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) if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11 && !hdr_connection)
chunk_appendf(tmp, "Connection: close\r\n"); chunk_appendf(tmp, "Connection: close\r\n");
/* If we dont have a content-length set, we must announce a transfer enconding /* If we dont have a content-length set, and the HTTP version is 1.1
* chunked. This is required by haproxy for the keepalive compliance. * and the status code implies the presence of a message body, we must
* If the applet annouce a transfer-encoding chunked itslef, don't * announce a transfer encoding chunked. This is required by haproxy
* do anything. * 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"); chunk_appendf(tmp, "Transfer-encoding: chunked\r\n");
appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_CHUNKED; appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_CHUNKED;
} }