From b995bb58cbd976280b132ee2148376fadd071063 Mon Sep 17 00:00:00 2001 From: Jay Satiro Date: Sat, 4 Apr 2020 16:16:18 -0400 Subject: tool: Add option --retry-all-errors to retry on any error The "sledgehammer" of retrying. Closes https://github.com/curl/curl/pull/5185 --- docs/cmdline-opts/Makefile.inc | 1 + docs/cmdline-opts/retry-all-errors.d | 19 +++++++++++ src/tool_cfgable.h | 1 + src/tool_getparam.c | 4 +++ src/tool_help.c | 2 ++ src/tool_operate.c | 5 +++ tests/data/Makefile.inc | 2 +- tests/data/test1909 | 65 ++++++++++++++++++++++++++++++++++++ 8 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 docs/cmdline-opts/retry-all-errors.d create mode 100644 tests/data/test1909 diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc index 5b7439e4a..6a7b953bc 100644 --- a/docs/cmdline-opts/Makefile.inc +++ b/docs/cmdline-opts/Makefile.inc @@ -180,6 +180,7 @@ DPAGES = \ request-target.d \ request.d \ resolve.d \ + retry-all-errors.d \ retry-connrefused.d \ retry-delay.d \ retry-max-time.d \ diff --git a/docs/cmdline-opts/retry-all-errors.d b/docs/cmdline-opts/retry-all-errors.d new file mode 100644 index 000000000..e0f662819 --- /dev/null +++ b/docs/cmdline-opts/retry-all-errors.d @@ -0,0 +1,19 @@ +Long: retry-all-errors +Help: Retry all errors (use with --retry) (read manpage, don't use by default) +Added: 7.71.0 +--- +Retry on any error. This option is used together with --retry. + +This option is the "sledgehammer" of retrying. Do not use this option by +default (eg in curlrc), there may be unintended consequences such as sending or +receiving duplicate data. Do not use with redirected input or output. You'd be +much better off handling your unique problems in shell script. Please read the +example below. + +Warning: For server compatibility curl attempts to retry failed flaky transfers +as close as possible to how they were started, but this is not possible with +redirected input or output. For example, before retrying it removes output data +from a failed partial transfer that was written to an output file. However this +is not true of data redirected to a | pipe or > file, which are not reset. We +strongly suggest don't parse or record output via redirect in combination with +this option, since you may receive duplicate data. diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index d7eebf598..c5b8c3071 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -223,6 +223,7 @@ struct OperationConfig { bool tcp_nodelay; bool tcp_fastopen; long req_retry; /* number of retries */ + bool retry_all_errors; /* retry on any error */ bool retry_connrefused; /* set connection refused as a transient error */ long retry_delay; /* delay between retries (in seconds) */ long retry_maxtime; /* maximum time to keep retrying */ diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 0252ee029..c0ab67c3f 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -197,6 +197,7 @@ static const struct LongShort aliases[]= { {"$Y", "suppress-connect-headers", ARG_BOOL}, {"$Z", "compressed-ssh", ARG_BOOL}, {"$~", "happy-eyeballs-timeout-ms", ARG_STRING}, + {"$!", "retry-all-errors", ARG_BOOL}, {"0", "http1.0", ARG_NONE}, {"01", "http1.1", ARG_NONE}, {"02", "http2", ARG_NONE}, @@ -927,6 +928,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ if(err) return err; break; + case '!': /* --retry-all-errors */ + config->retry_all_errors = toggle; + break; case 'k': /* --proxy-negotiate */ if(curlinfo->features & CURL_VERSION_SPNEGO) diff --git a/src/tool_help.c b/src/tool_help.c index 5afaf822e..92ccae3b9 100644 --- a/src/tool_help.c +++ b/src/tool_help.c @@ -399,6 +399,8 @@ static const struct helptxt helptext[] = { "Retry on connection refused (use with --retry)"}, {" --retry-delay ", "Wait time between retries"}, + {" --retry-all-errors", + "Retry all errors (use with --retry) (read manpage, don't use by default)"}, {" --retry-max-time ", "Retry only within this period"}, {" --sasl-authzid ", diff --git a/src/tool_operate.c b/src/tool_operate.c index 66c6468bc..6d489aa30 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -437,6 +437,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global, config->retry_maxtime*1000L)) ) { enum { RETRY_NO, + RETRY_ALL_ERRORS, RETRY_TIMEOUT, RETRY_CONNREFUSED, RETRY_HTTP, @@ -506,11 +507,15 @@ static CURLcode post_per_transfer(struct GlobalConfig *global, retry = RETRY_FTP; } + if(result && !retry && config->retry_all_errors) + retry = RETRY_ALL_ERRORS; + if(retry) { long sleeptime = 0; curl_off_t retry_after = 0; static const char * const m[]={ NULL, + "(retrying all errors)", "timeout", "connection refused", "HTTP error", diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index 26faa954f..07ab2a974 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -201,7 +201,7 @@ test1700 test1701 test1702 \ test1800 test1801 \ \ test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 \ -test1908 \ +test1908 test1909 \ \ test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \ test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \ diff --git a/tests/data/test1909 b/tests/data/test1909 new file mode 100644 index 000000000..bde0e5e0f --- /dev/null +++ b/tests/data/test1909 @@ -0,0 +1,65 @@ + + + +HTTP +HTTP GET +retry + + + +# +# Server-side + + +HTTP/1.1 200 OK swsclose swsbounce +Content-Length: 5 +Connection: close + +bbb + + +HTTP/1.1 200 OK +Content-Length: 5 +Connection: close + +data + + + +# +# Client-side + + +http + + +HTTP GET --retry-all-errors to overcome partial transfer + + +--retry 1 --retry-all-errors -o log/outfile1909 http://%HOSTIP:%HTTPPORT/1909 + + + +# +# Verify data after the test has been "shot" + + +^User-Agent:.* + + +GET /1909 HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +Accept: */* + +GET /1909 HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +Accept: */* + + + + +data + + + + -- cgit v1.2.3