]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
transfer: skip EOS read when download done
authorStefan Eissing <stefan@eissing.org>
Mon, 26 Aug 2024 08:56:28 +0000 (10:56 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 28 Aug 2024 11:54:38 +0000 (13:54 +0200)
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

lib/http.c
lib/request.h
lib/transfer.c

index 15ca8fca840bd8f3245267b04653449241ebb730..e748aa55b0c5e1fcbf1a258363313c94bfb5ff6d 100644 (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':
index c1cf5f21fc4903fb2816b864fad9366b115b87e0..aba56be714f9e4f26b4ffe951b8bef9f38b2975f 100644 (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 */
index 360dfd887ea9e3ffaa0e68cb2be236c897b2e4d4..4c1cba1d21cd5bfdeb4abff548ddbc384978c192 100644 (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 */