]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http: have CURLOPT_FAILONERROR fail after all headers
authorDaniel Stenberg <daniel@haxx.se>
Mon, 4 Jan 2021 17:28:42 +0000 (18:28 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 6 Jan 2021 14:14:40 +0000 (15:14 +0100)
... so that Retry-After and other meta-content can still be used.

Added 1634 to verify. Adjusted test 194 and 281 since --fail now also
includes the header-terminating CRLF in the output before it exits.

Fixes #6408
Closes #6409

lib/http.c
tests/data/Makefile.inc
tests/data/test1634 [new file with mode: 0644]
tests/data/test194
tests/data/test281

index 5ab1522e82ff68aff18ffaf99b03a918985c1ccd..42aa84ec02d26685b61fa4d401c50458391ff301 100644 (file)
@@ -96,7 +96,7 @@
 
 static int http_getsock_do(struct connectdata *conn,
                            curl_socket_t *socks);
-static int http_should_fail(struct connectdata *conn);
+static bool http_should_fail(struct connectdata *conn);
 
 #ifndef CURL_DISABLE_PROXY
 static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
@@ -1046,11 +1046,11 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
  *
  * @param conn all information about the current connection
  *
- * @retval 0 communications should continue
+ * @retval FALSE communications should continue
  *
- * @retval 1 communications should not continue
+ * @retval TRUE communications should not continue
  */
-static int http_should_fail(struct connectdata *conn)
+static bool http_should_fail(struct connectdata *conn)
 {
   struct Curl_easy *data;
   int httpcode;
@@ -1066,20 +1066,20 @@ static int http_should_fail(struct connectdata *conn)
   ** don't fail.
   */
   if(!data->set.http_fail_on_error)
-    return 0;
+    return FALSE;
 
   /*
   ** Any code < 400 is never terminal.
   */
   if(httpcode < 400)
-    return 0;
+    return FALSE;
 
   /*
   ** Any code >= 400 that's not 401 or 407 is always
   ** a terminal error
   */
   if((httpcode != 401) && (httpcode != 407))
-    return 1;
+    return TRUE;
 
   /*
   ** All we have left to deal with is 401 and 407
@@ -3309,12 +3309,6 @@ checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
   return checkhttpprefix(data, s, len);
 }
 
-static void print_http_error(struct Curl_easy *data)
-{
-  struct SingleRequest *k = &data->req;
-  failf(data, "The requested URL returned error: %d", k->httpcode);
-}
-
 /*
  * Curl_http_header() parses a single response header.
  */
@@ -3646,16 +3640,6 @@ CURLcode Curl_http_statusline(struct Curl_easy *data,
        pretend this is no error */
     k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
   }
-  else if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
-          ((k->httpcode != 401) || !conn->bits.user_passwd)
-#ifndef CURL_DISABLE_PROXY
-          && ((k->httpcode != 407) || !conn->bits.proxy_user_passwd)
-#endif
-    ) {
-    /* serious error, go home! */
-    print_http_error(data);
-    return CURLE_HTTP_RETURNED_ERROR;
-  }
 
   if(conn->httpversion == 10) {
     /* Default action for HTTP/1.0 must be to close, unless
@@ -3928,15 +3912,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         conn->proxy_negotiate_state = GSS_AUTHSUCC;
       }
 #endif
-      /*
-       * When all the headers have been parsed, see if we should give
-       * up and return an error.
-       */
-      if(http_should_fail(conn)) {
-        failf(data, "The requested URL returned error: %d",
-              k->httpcode);
-        return CURLE_HTTP_RETURNED_ERROR;
-      }
 
       /* now, only output this if the header AND body are requested:
        */
@@ -3954,6 +3929,16 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
       data->info.header_size += (long)headerlen;
       data->req.headerbytecount += (long)headerlen;
 
+      /*
+       * When all the headers have been parsed, see if we should give
+       * up and return an error.
+       */
+      if(http_should_fail(conn)) {
+        failf(data, "The requested URL returned error: %d",
+              k->httpcode);
+        return CURLE_HTTP_RETURNED_ERROR;
+      }
+
       data->req.deductheadercount =
         (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
 
index 6aa871bbf235723774232e6328d79736b132f792..d0e6510b9ed7308b5dc8668eeac0cf960304e7cd 100644 (file)
@@ -196,7 +196,7 @@ test1608 test1609 test1610 test1611 test1612 \
 \
 test1620 test1621 \
 \
-test1630 test1631 test1632 test1633 \
+test1630 test1631 test1632 test1633 test1634 \
 \
 test1650 test1651 test1652 test1653 test1654 test1655 \
 test1660 \
diff --git a/tests/data/test1634 b/tests/data/test1634
new file mode 100644 (file)
index 0000000..5c05474
--- /dev/null
@@ -0,0 +1,70 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 429 too many requests swsbounce
+Retry-After: 1
+Content-Length: 4
+
+moo
+</data>
+<data1>
+HTTP/1.1 200 OK
+Content-Length: 4
+Connection: close
+
+hey
+</data1>
+
+<datacheck>
+HTTP/1.1 429 too many requests swsbounce
+Retry-After: 1
+Content-Length: 4
+
+HTTP/1.1 200 OK
+Content-Length: 4
+Connection: close
+
+hey
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+--retry with a 429 response and Retry-After: and --fail
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/1634 --retry 1  --fail
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /1634 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+\r
+GET /1634 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+\r
+</protocol>
+</verify>
+</testcase>
index 323ac0f38d48954797d669ea5aba75f24930d55d..8c2b863a031eb32c36d6a08734fb109677d7e262 100644 (file)
@@ -36,6 +36,7 @@ Content-Length: 4
 Content-Range: bytes */87\r
 Content-Type: image/gif\r
 Connection: close\r
+\r
 </datacheck>
 
 </reply>
index f78b0c1465559c4801f795cbd082851e271d6198..e865e94952ef4c5218f1f6cbb09781cb47491f57 100644 (file)
@@ -14,11 +14,8 @@ HTTP/1.1 401 Bad Auth swsclose
 Date: Thu, 09 Nov 2010 14:49:00 GMT
 WWW-Authenticate: Basic Realm=authenticate
 Server: test-server/fake
-</data>
-<datacheck>
-HTTP/1.1 100 Continue
 
-</datacheck>
+</data>
 
 </reply>