]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool: Add option --retry-all-errors to retry on any error
authorJay Satiro <raysatiro@yahoo.com>
Sat, 4 Apr 2020 20:16:18 +0000 (16:16 -0400)
committerJay Satiro <raysatiro@yahoo.com>
Tue, 12 May 2020 07:00:15 +0000 (03:00 -0400)
The "sledgehammer" of retrying.

Closes https://github.com/curl/curl/pull/5185

docs/cmdline-opts/Makefile.inc
docs/cmdline-opts/retry-all-errors.d [new file with mode: 0644]
src/tool_cfgable.h
src/tool_getparam.c
src/tool_help.c
src/tool_operate.c
tests/data/Makefile.inc
tests/data/test1909 [new file with mode: 0644]

index 5b7439e4a48ddce04f7a9c0ad1b4873b21bdc253..6a7b953bc2ea74b3e47de25c6667d7b89403f648 100644 (file)
@@ -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 (file)
index 0000000..e0f6628
--- /dev/null
@@ -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.
index d7eebf59801442cdbc6317b7aa0e050990329711..c5b8c3071008d1aa42568828b350216280b40a43 100644 (file)
@@ -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 */
index 0252ee0290600a0552a71de3537d9824e6d32aab..c0ab67c3f3975a69fd99d4b10d75f39c2a8208a7 100644 (file)
@@ -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)
index 5afaf822ec8ab084f52454f0784365e2104ea6f9..92ccae3b91ac67f8d32cdf4dc0feeb9a6dd0da83 100644 (file)
@@ -399,6 +399,8 @@ static const struct helptxt helptext[] = {
    "Retry on connection refused (use with --retry)"},
   {"    --retry-delay <seconds>",
    "Wait time between retries"},
+  {"    --retry-all-errors",
+   "Retry all errors (use with --retry) (read manpage, don't use by default)"},
   {"    --retry-max-time <seconds>",
    "Retry only within this period"},
   {"    --sasl-authzid <identity> ",
index 66c6468bc3dddd9eb37e897e744844ee5e34940f..6d489aa30b7938e28e2e91d62a620d66fe552b8c 100644 (file)
@@ -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",
index 26faa954fe571e9a90ef466927bd90289db87b05..07ab2a974ca51b422e6ca295415484b1209d7793 100644 (file)
@@ -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 (file)
index 0000000..bde0e5e
--- /dev/null
@@ -0,0 +1,65 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+retry
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK swsclose swsbounce
+Content-Length: 5
+Connection: close
+
+bbb
+</data>
+<data1>
+HTTP/1.1 200 OK
+Content-Length: 5
+Connection: close
+
+data
+</data1>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP GET --retry-all-errors to overcome partial transfer
+ </name>
+ <command option="no-output,no-include">
+--retry 1 --retry-all-errors -o log/outfile1909 http://%HOSTIP:%HTTPPORT/1909
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1909 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+Accept: */*\r
+\r
+GET /1909 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+Accept: */*\r
+\r
+</protocol>
+
+<file1 name="log/outfile1909">
+data
+</file1>
+
+</verify>
+</testcase>