]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool_getparam: make --fail and --fail-with-body override each other
authorDaniel Stenberg <daniel@haxx.se>
Sun, 12 Oct 2025 13:58:43 +0000 (15:58 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 13 Oct 2025 08:38:10 +0000 (10:38 +0200)
This allows users to put one of them in their .curlrc and still easily
use the other one at will in command lines.

The --no-* versions disable both of them.

Reported-by: Mitchell Blank Jr
Fixes #19029
Closes #19034

src/config2setopts.c
src/tool_cfgable.h
src/tool_getparam.c
src/tool_operate.c
tests/data/test360

index 0a519ed048654361c72168f3e50c6e3825cc4c5f..c367959ccb3ee2573552ebd6e73a3eff5d1ad8b2 100644 (file)
@@ -851,7 +851,7 @@ CURLcode config2setopts(struct OperationConfig *config,
   if(result)
     return result;
 
-  my_setopt_long(curl, CURLOPT_FAILONERROR, config->failonerror);
+  my_setopt_long(curl, CURLOPT_FAILONERROR, config->fail == FAIL_WO_BODY);
   my_setopt_str(curl, CURLOPT_REQUEST_TARGET, config->request_target);
   my_setopt_long(curl, CURLOPT_UPLOAD, !!per->uploadfile);
   my_setopt_long(curl, CURLOPT_DIRLISTONLY, config->dirlistonly);
index 3c67695124e7a9849bb7904821a960e12d4d6760..630f23fd9654625a466214177e2f47221ca47ee3 100644 (file)
@@ -58,6 +58,10 @@ struct State {
   curl_off_t urlidx;    /* index for globbed URLs */
 };
 
+#define FAIL_NONE      0
+#define FAIL_WITH_BODY 1
+#define FAIL_WO_BODY   2
+
 struct OperationConfig {
   struct dynbuf postdata;
   char *useragent;
@@ -223,6 +227,7 @@ struct OperationConfig {
   unsigned short porttouse;
   unsigned char ssl_version;     /* 0 - 4, 0 being default */
   unsigned char ssl_version_max; /* 0 - 4, 0 being default */
+  unsigned char fail;            /* NONE, with body, without body */
   BIT(remote_name_all);   /* --remote-name-all */
   BIT(remote_time);
   BIT(cookiesession);       /* new session? */
@@ -241,8 +246,6 @@ struct OperationConfig {
   BIT(ftp_append);          /* APPE on ftp */
   BIT(use_ascii);           /* select ASCII or text transfer */
   BIT(autoreferer);         /* automatically set referer */
-  BIT(failonerror);         /* fail on (HTTP) errors */
-  BIT(failwithbody);        /* fail on (HTTP) errors but still store body */
   BIT(show_headers);        /* show headers to data output */
   BIT(no_body);             /* do not get the body */
   BIT(dirlistonly);         /* only get the FTP dir list */
index b533f41aa7dfa5bea734a230232018bef9392b66..0cff5b558d9b539f2087cfb28b1f5691d2017c5f 100644 (file)
@@ -2037,14 +2037,6 @@ static ParameterError opt_bool(struct OperationConfig *config,
   case C_MAIL_RCPT_ALLOWFAILS: /* --mail-rcpt-allowfails */
     config->mail_rcpt_allowfails = toggle;
     break;
-  case C_FAIL_WITH_BODY: /* --fail-with-body */
-    config->failwithbody = toggle;
-    if(config->failonerror && config->failwithbody) {
-      errorf("You must select either --fail or "
-             "--fail-with-body, not both.");
-      return PARAM_BAD_USE;
-    }
-    break;
   case C_REMOVE_ON_ERROR: /* --remove-on-error */
     if(config->use_resume && toggle) {
       errorf("--continue-at is mutually exclusive with --remove-on-error");
@@ -2052,13 +2044,15 @@ static ParameterError opt_bool(struct OperationConfig *config,
     }
     config->rm_partial = toggle;
     break;
-  case C_FAIL: /* --fail */
-    config->failonerror = toggle;
-    if(config->failonerror && config->failwithbody) {
-      errorf("You must select either --fail or "
-             "--fail-with-body, not both.");
-      return PARAM_BAD_USE;
-    }
+  case C_FAIL: /* --fail without body */
+    if(toggle && (config->fail == FAIL_WITH_BODY))
+      warnf("--fail deselects --fail-with-body here");
+    config->fail = toggle ? FAIL_WO_BODY : FAIL_NONE;
+    break;
+  case C_FAIL_WITH_BODY: /* --fail-with-body */
+    if(toggle && (config->fail == FAIL_WO_BODY))
+      warnf("--fail-with-body deselects --fail here");
+    config->fail = toggle ? FAIL_WITH_BODY : FAIL_NONE;
     break;
   case C_GLOBOFF: /* --globoff */
     config->globoff = toggle;
index 1901ab3ac1787e3df431b03758dda6fa2a2c2127..397b2159e198a7800ef26e0b6a50d44d7b435d8f 100644 (file)
@@ -393,8 +393,7 @@ static CURLcode retrycheck(struct OperationConfig *config,
       retry = RETRY_CONNREFUSED;
   }
   else if((CURLE_OK == result) ||
-          ((config->failonerror || config->failwithbody) &&
-           (CURLE_HTTP_RETURNED_ERROR == result))) {
+          (config->fail && (CURLE_HTTP_RETURNED_ERROR == result))) {
     /* If it returned OK. _or_ failonerror was enabled and it
        returned due to such an error, check for HTTP transient
        errors to retry on. */
@@ -659,7 +658,7 @@ static CURLcode post_per_transfer(struct per_transfer *per,
       if(result == CURLE_PEER_FAILED_VERIFICATION)
         fputs(CURL_CA_CERT_ERRORMSG, tool_stderr);
     }
-    else if(config->failwithbody) {
+    else if(config->fail == FAIL_WITH_BODY) {
       /* if HTTP response >= 400, return error */
       long code = 0;
       curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
index b7d570d7b6c4359766429a5624eb8d04e2cc6d0b..f98d03a036cce940817e7b59185ae4b0854dd660 100644 (file)
@@ -6,7 +6,23 @@
 </keywords>
 </info>
 
-# Client-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
 <client>
 <server>
 http
@@ -15,14 +31,14 @@ http
 Error on both --fail-with-body and --fail
 </name>
 <command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --fail-with-body --fail
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --fail-with-body --fail --no-progress-meter
 </command>
 </client>
 
 # Verify data after the test has been "shot"
 <verify>
-<errorcode>
-2
-</errorcode>
+<stderr mode="text">
+Warning: --fail deselects --fail-with-body here
+</stderr>
 </verify>
 </testcase>