transfer: skip EOS read when download done

When we downloaded all we wanted, and we did not want a response body,
and no Trailer: has been announced, and the receive gives EAGAIN, do not
hang around unnecessarily.

Some servers are buggy in HEAD processing and fail to send the HTTP/2
EOS. Since we do not need any more data, end the request right there.
This will cause us to send a RST_STREAM to the server.

Fixes #14670
Reported-by: Gruber Glass
Closes #14685
This commit is contained in:
Stefan Eissing 2024-08-26 10:56:28 +02:00 committed by Daniel Stenberg
parent 1be704e17e
commit 29610e5f3d
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
3 changed files with 17 additions and 4 deletions

View File

@ -3154,6 +3154,11 @@ CURLcode Curl_http_header(struct Curl_easy *data,
}
return CURLE_OK;
}
v = HD_VAL(hd, hdlen, "Trailer:");
if(v) {
data->req.resp_trailer = TRUE;
return CURLE_OK;
}
break;
case 'w':
case 'W':

View File

@ -135,6 +135,7 @@ struct SingleRequest {
BIT(http_bodyless); /* HTTP response status code is between 100 and 199,
204 or 304 */
BIT(chunk); /* if set, this is a chunked transfer-encoding */
BIT(resp_trailer); /* response carried 'Trailer:' header field */
BIT(ignore_cl); /* ignore content-length */
BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding
on upload */

View File

@ -306,11 +306,18 @@ static CURLcode sendrecv_dl(struct Curl_easy *data,
nread = Curl_xfer_recv_resp(data, buf, bytestoread,
is_multiplex, &result);
if(nread < 0) {
if(CURLE_AGAIN == result) {
result = CURLE_OK;
break; /* get out of loop */
if(CURLE_AGAIN != result)
goto out; /* real error */
result = CURLE_OK;
if(data->req.download_done && data->req.no_body &&
!data->req.resp_trailer) {
DEBUGF(infof(data, "EAGAIN, download done, no trailer announced, "
"not waiting for EOS"));
nread = 0;
/* continue as if we read the EOS */
}
goto out; /* real error */
else
break; /* get out of loop */
}
/* We only get a 0-length read on EndOfStream */