Browse Source

[core] fix chunked decoding from backend (#3044, #3046)

fix edge case for initial chunked data
(bug introduced in lighttpd 1.4.56)

If chunked header received without data before response headers sent,
then initial chunked data might be sent to client without chunked header
if client made an HTTP/1.1 request and the response is Transfer-Encoding
chunked and lighttpd is configured to stream the response (non-zero
value for server.stream-response-body).  This might occur if lighttpd
backend is connected via a unix domain socket and the initial chunk is
large and coming from a temporary file.  It may be sent in a separate
packet since lighttpd does not use TCP_CORK on unix domain sockets.

x-ref:
  "Failure on second request in http proxy backend"
  https://redmine.lighttpd.net/issues/3046
  "Socket errors after update to version 1.4.56"
  https://redmine.lighttpd.net/issues/3044
master
Glenn Strauss 2 months ago
parent
commit
8e6dc4fe94
  1. 36
      src/response.c

36
src/response.c

@ -831,24 +831,32 @@ http_response_write_prepare(request_st * const r)
else if (r->http_version == HTTP_VERSION_1_1) {
off_t qlen = chunkqueue_length(&r->write_queue);
r->resp_send_chunked = 1;
if (qlen) {
/* create initial Transfer-Encoding: chunked segment */
buffer * const b =
chunkqueue_prepend_buffer_open(&r->write_queue);
if (r->resp_decode_chunked
&& 0 != r->gw_dechunk->gw_chunked) {
/*(reconstitute initial partially-decoded chunk)*/
off_t gw_chunked = r->gw_dechunk->gw_chunked;
if (gw_chunked > 2)
qlen += gw_chunked - 2;
else if (1 == gw_chunked)
if (r->resp_decode_chunked) {
/*(reconstitute initial partially-decoded chunk)*/
off_t gw_chunked = r->gw_dechunk->gw_chunked;
if (gw_chunked > 2)
qlen += gw_chunked - 2;
else if (1 == gw_chunked)
chunkqueue_append_mem(&r->write_queue,
CONST_STR_LEN("\r"));
else {
if (qlen)
chunkqueue_append_mem(&r->write_queue,
CONST_STR_LEN("\r"));
CONST_STR_LEN("\r\n"));
const buffer * const hdr = &r->gw_dechunk->b;
if (!buffer_is_blank(hdr)) /*(partial chunked header)*/
chunkqueue_append_mem(&r->write_queue,
BUF_PTR_LEN(hdr));
}
else {
}
else if (qlen) {
chunkqueue_append_mem(&r->write_queue,
CONST_STR_LEN("\r\n"));
}
}
if (qlen) {
/* create initial Transfer-Encoding: chunked segment */
buffer * const b =
chunkqueue_prepend_buffer_open(&r->write_queue);
buffer_append_uint_hex(b, (uintmax_t)qlen);
buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
chunkqueue_prepend_buffer_commit(&r->write_queue);

Loading…
Cancel
Save