]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stream: Add level 7 retries on http error 401, 403
authorJulien Pivotto <roidelapluie@inuits.eu>
Thu, 12 Nov 2020 10:14:05 +0000 (11:14 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 23 Nov 2020 08:33:14 +0000 (09:33 +0100)
Level-7 retries are only possible with a restricted number of HTTP
return codes. While it is usually not safe to retry on 401 and 403, I
came up with an authentication backend which was not synchronizing
authentication of users. While not perfect, being allowed to also retry
on those return codes is really helpful and acts as a hotfix until we
can fix the backend.

Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
doc/configuration.txt
include/haproxy/proxy-t.h
include/haproxy/proxy.h
src/proxy.c

index d25b729156eeeee17894d1b14393738a9d85b98f..ab49c68a47bc3b16d6fe754ce695e926bde375c5 100644 (file)
@@ -9320,10 +9320,11 @@ retry-on [list of keywords]
                         rejected by the server. These requests are generally
                         considered to be safe to retry.
 
-      <status>          any HTTP status code among "404" (Not Found), "408"
-                        (Request Timeout), "425" (Too Early), "500" (Server
-                        Error), "501" (Not Implemented), "502" (Bad Gateway),
-                        "503" (Service Unavailable), "504" (Gateway Timeout).
+      <status>          any HTTP status code among "401" (Unauthorized), "403"
+                        (Forbidden), "404" (Not Found), "408" (Request Timeout),
+                        "425" (Too Early), "500" (Server Error), "501" (Not
+                        Implemented), "502" (Bad Gateway), "503" (Service
+                        Unavailable), "504" (Gateway Timeout).
 
       all-retryable-errors
                         retry request for any error that are considered
index 41aca9d39286cf8dc1fc05499361d4194dad70b0..998e210f69ce71a4d52750af3ce3cecaa8d48c99 100644 (file)
@@ -175,17 +175,20 @@ enum PR_SRV_STATE_FILE {
 #define PR_RE_CONN_FAILED         0x00000001 /* Retry if we failed to connect */
 #define PR_RE_DISCONNECTED        0x00000002 /* Retry if we got disconnected with no answer */
 #define PR_RE_TIMEOUT             0x00000004 /* Retry if we got a server timeout before we got any data */
-#define PR_RE_404                 0x00000008 /* Retry if we got a 404 */
-#define PR_RE_408                 0x00000010 /* Retry if we got a 408 */
-#define PR_RE_425                 0x00000020 /* Retry if we got a 425 */
-#define PR_RE_500                 0x00000040 /* Retry if we got a 500 */
-#define PR_RE_501                 0x00000080 /* Retry if we got a 501 */
-#define PR_RE_502                 0x00000100 /* Retry if we got a 502 */
-#define PR_RE_503                 0x00000200 /* Retry if we got a 503 */
-#define PR_RE_504                 0x00000400 /* Retry if we got a 504 */
-#define PR_RE_STATUS_MASK         (PR_RE_404 | PR_RE_408 | PR_RE_425 | \
-                                   PR_RE_425 | PR_RE_500 | PR_RE_501 | \
-                                   PR_RE_502 | PR_RE_503 | PR_RE_504)
+#define PR_RE_401                 0x00000008 /* Retry if we got a 401 */
+#define PR_RE_403                 0x00000010 /* Retry if we got a 403 */
+#define PR_RE_404                 0x00000020 /* Retry if we got a 404 */
+#define PR_RE_408                 0x00000040 /* Retry if we got a 408 */
+#define PR_RE_425                 0x00000080 /* Retry if we got a 425 */
+#define PR_RE_500                 0x00000100 /* Retry if we got a 500 */
+#define PR_RE_501                 0x00000200 /* Retry if we got a 501 */
+#define PR_RE_502                 0x00000400 /* Retry if we got a 502 */
+#define PR_RE_503                 0x00000800 /* Retry if we got a 503 */
+#define PR_RE_504                 0x00001000 /* Retry if we got a 504 */
+#define PR_RE_STATUS_MASK         (PR_RE_401 | PR_RE_403 | PR_RE_404 | \
+                                   PR_RE_408 | PR_RE_425 | PR_RE_500 | \
+                                   PR_RE_501 | PR_RE_502 | PR_RE_503 | \
+                                   PR_RE_504)
 /* 0x00000800, 0x00001000, 0x00002000, 0x00004000 and 0x00008000 unused,
  * reserved for eventual future status codes
  */
index fe253bf7fc9f9cbd0733c8c4e9c496f1361d35c2..f63f4a2cdb55cc2b0e5fecf7c0846a850558310b 100644 (file)
@@ -154,6 +154,10 @@ static inline int l7_status_match(struct proxy *p, int status)
                return 0;
 
        switch (status) {
+       case 401:
+               return (p->retry_type & PR_RE_401);
+       case 403:
+               return (p->retry_type & PR_RE_403);
        case 404:
                return (p->retry_type & PR_RE_404);
        case 408:
index 2393de50a0399ac9a120b4b091ec1cc15913188a..fb5c98c9ef51bbbb624470b4ca260ac0f2263a49 100644 (file)
@@ -528,6 +528,10 @@ proxy_parse_retry_on(char **args, int section, struct proxy *curpx,
                        curpx->retry_type |= PR_RE_DISCONNECTED;
                else if (!strcmp(args[i], "response-timeout"))
                        curpx->retry_type |= PR_RE_TIMEOUT;
+               else if (!strcmp(args[i], "401"))
+                       curpx->retry_type |= PR_RE_401;
+               else if (!strcmp(args[i], "403"))
+                       curpx->retry_type |= PR_RE_403;
                else if (!strcmp(args[i], "404"))
                        curpx->retry_type |= PR_RE_404;
                else if (!strcmp(args[i], "408"))