Prevent both --fail and --fail-with-body on the same command line.
Verify with test 349, 360 and 361.
Closes #6449
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
dump-header.d \
egd-file.d \
engine.d \
- etag-compare.d \
- etag-save.d \
+ etag-compare.d \
+ etag-save.d \
expect100-timeout.d \
fail-early.d \
+ fail-with-body.d \
fail.d \
false-start.d \
form-string.d \
--- /dev/null
+Long: fail-with-body
+Protocols: HTTP
+Help: Fail on HTTP errors but save the body
+Category: http output
+Added: 7.76.0
+See-also: fail
+---
+
+Return an error on server errors where the HTTP response code is 400 or
+greater). In normal cases when an HTTP server fails to deliver a document, it
+returns an HTML document stating so (which often also describes why and
+more). This flag will still allow curl to outputting and save that content but
+also to return error 22.
+
+This is an alternative option to --fail which makes curl fail for the same
+circumstances but without saving the content.
Short: f
Protocols: HTTP
Help: Fail silently (no output at all) on HTTP errors
+See-also: fail-with-body
Category: important http
---
Fail silently (no output at all) on server errors. This is mostly done to
--expect100-timeout 7.47.0
--fail (-f) 4.0
--fail-early 7.52.0
+--fail-with-body 7.76.0
--false-start 7.42.0
--form (-F) 5.0
--form-string 7.13.2
bool use_ascii; /* select ascii or text transfer */
bool autoreferer; /* automatically set referer */
bool failonerror; /* fail on (HTTP) errors */
+ bool failwithbody; /* fail on (HTTP) errors but still store body */
bool show_headers; /* show headers to data output */
bool no_body; /* don't get the body */
bool dirlistonly; /* only get the FTP dir list */
{"fa", "fail-early", ARG_BOOL},
{"fb", "styled-output", ARG_BOOL},
{"fc", "mail-rcpt-allowfails", ARG_BOOL},
+ {"fd", "fail-with-body", ARG_BOOL},
{"F", "form", ARG_STRING},
{"Fs", "form-string", ARG_STRING},
{"g", "globoff", ARG_BOOL},
case 'c': /* --mail-rcpt-allowfails */
config->mail_rcpt_allowfails = toggle;
break;
+ case 'd': /* --fail-with-body */
+ config->failwithbody = toggle;
+ break;
default: /* --fail (hard on errors) */
config->failonerror = toggle;
+ break;
+ }
+ if(config->failonerror && config->failwithbody) {
+ errorf(config->global, "You must select either --fail or "
+ "--fail-with-body, not both.\n");
+ return PARAM_BAD_USE;
}
break;
case 'F':
{" --fail-early",
"Fail on first transfer error, do not continue",
CURLHELP_CURL},
+ {" --fail-with-body",
+ "Fail on HTTP errors but save the body",
+ CURLHELP_HTTP | CURLHELP_OUTPUT},
{" --false-start",
"Enable TLS False Start",
CURLHELP_TLS},
if(result == CURLE_PEER_FAILED_VERIFICATION)
fputs(CURL_CA_CERT_ERRORMSG, global->errors);
}
-
+ else if(config->failwithbody) {
+ /* if HTTP response >= 400, return error */
+ long code = 0;
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
+ if(code >= 400) {
+ if(global->showerror)
+ fprintf(global->errors,
+ "curl: (%d) The requested URL returned error: %ld\n",
+ CURLE_HTTP_RETURNED_ERROR, code);
+ result = CURLE_HTTP_RETURNED_ERROR;
+ }
+ }
/* Set file extended attributes */
if(!result && config->xattr && outs->fopened && outs->stream) {
int rc = fwrite_xattr(curl, fileno(outs->stream));
free(per->outfile);
free(per->uploadfile);
- return CURLE_OK;
+ return result;
}
static void single_transfer_cleanup(struct OperationConfig *config)
#endif
result = curl_easy_perform(per->curl);
- /* store the result of the actual transfer */
- returncode = result;
-
- result = post_per_transfer(global, per, result, &retry, &delay);
+ returncode = post_per_transfer(global, per, result, &retry, &delay);
if(retry) {
tool_go_sleep(delay);
continue;
}
/* Bail out upon critical errors or --fail-early */
- if(result || is_fatal_error(returncode) ||
- (returncode && global->fail_early))
+ if(is_fatal_error(returncode) || (returncode && global->fail_early))
bailout = TRUE;
else {
/* setup the next one just before we delete this */
test316 test317 test318 test319 test320 test321 test322 test323 test324 \
test325 test326 test327 test328 test329 test330 test331 test332 test333 \
test334 test335 test336 test337 test338 test339 test340 test341 test342 \
-test343 test344 test345 test346 test347 test348 \
-test350 test351 test352 test353 test354 test355 test356 test357 test358 \
-test359 \
+test343 test344 test345 test346 test347 test348 test349 test350 test351 \
+test352 test353 test354 test355 test356 test357 test358 test359 test360 \
+test361 \
+\
test393 test394 test395 test396 test397 \
\
test400 test401 test402 test403 test404 test405 test406 test407 test408 \
<keywords>
HTTP
HTTP GET
+--fail
</keywords>
</info>
# Server-side
--- /dev/null
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+--fail-with-body
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+HTTP/1.0 404 BAD BOY swsclose
+Content-Type: text/html
+
+This silly page doesn't reaaaaaly exist so you should not get it.
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP GET --fail-with-body on HTTP error return
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/349 --fail-with-body
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /349 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+\r
+</protocol>
+<errorcode>
+22
+</errorcode>
+</verify>
+</testcase>
--- /dev/null
+<testcase>
+<info>
+<keywords>
+--fail
+--fail-with-body
+</keywords>
+</info>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+Error on both --fail-with-body and --fail
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/360 --fail-with-body --fail
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+2
+</errorcode>
+</verify>
+</testcase>
--- /dev/null
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+--fail-with-body
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+HTTP/1.0 404 BAD BOY swsclose
+Content-Type: text/html
+
+This silly page doesn't reaaaaaly exist so you should not get it.
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP GET --fail-with-body on HTTP error return - twice
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/361 http://%HOSTIP:%HTTPPORT/361 --fail-with-body
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /361 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+\r
+GET /361 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+\r
+</protocol>
+<errorcode>
+22
+</errorcode>
+</verify>
+</testcase>