MINOR: stream: Add level 7 retries on http error 401, 403

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>
This commit is contained in:
Julien Pivotto 2020-11-12 11:14:05 +01:00 committed by Christopher Faulet
parent 9fee7e02d1
commit 2de240a676
4 changed files with 27 additions and 15 deletions

View File

@ -9320,10 +9320,11 @@ retry-on [list of keywords]
rejected by the server. These requests are generally rejected by the server. These requests are generally
considered to be safe to retry. considered to be safe to retry.
<status> any HTTP status code among "404" (Not Found), "408" <status> any HTTP status code among "401" (Unauthorized), "403"
(Request Timeout), "425" (Too Early), "500" (Server (Forbidden), "404" (Not Found), "408" (Request Timeout),
Error), "501" (Not Implemented), "502" (Bad Gateway), "425" (Too Early), "500" (Server Error), "501" (Not
"503" (Service Unavailable), "504" (Gateway Timeout). Implemented), "502" (Bad Gateway), "503" (Service
Unavailable), "504" (Gateway Timeout).
all-retryable-errors all-retryable-errors
retry request for any error that are considered retry request for any error that are considered

View 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_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_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_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_401 0x00000008 /* Retry if we got a 401 */
#define PR_RE_408 0x00000010 /* Retry if we got a 408 */ #define PR_RE_403 0x00000010 /* Retry if we got a 403 */
#define PR_RE_425 0x00000020 /* Retry if we got a 425 */ #define PR_RE_404 0x00000020 /* Retry if we got a 404 */
#define PR_RE_500 0x00000040 /* Retry if we got a 500 */ #define PR_RE_408 0x00000040 /* Retry if we got a 408 */
#define PR_RE_501 0x00000080 /* Retry if we got a 501 */ #define PR_RE_425 0x00000080 /* Retry if we got a 425 */
#define PR_RE_502 0x00000100 /* Retry if we got a 502 */ #define PR_RE_500 0x00000100 /* Retry if we got a 500 */
#define PR_RE_503 0x00000200 /* Retry if we got a 503 */ #define PR_RE_501 0x00000200 /* Retry if we got a 501 */
#define PR_RE_504 0x00000400 /* Retry if we got a 504 */ #define PR_RE_502 0x00000400 /* Retry if we got a 502 */
#define PR_RE_STATUS_MASK (PR_RE_404 | PR_RE_408 | PR_RE_425 | \ #define PR_RE_503 0x00000800 /* Retry if we got a 503 */
PR_RE_425 | PR_RE_500 | PR_RE_501 | \ #define PR_RE_504 0x00001000 /* Retry if we got a 504 */
PR_RE_502 | PR_RE_503 | PR_RE_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, /* 0x00000800, 0x00001000, 0x00002000, 0x00004000 and 0x00008000 unused,
* reserved for eventual future status codes * reserved for eventual future status codes
*/ */

View File

@ -154,6 +154,10 @@ static inline int l7_status_match(struct proxy *p, int status)
return 0; return 0;
switch (status) { switch (status) {
case 401:
return (p->retry_type & PR_RE_401);
case 403:
return (p->retry_type & PR_RE_403);
case 404: case 404:
return (p->retry_type & PR_RE_404); return (p->retry_type & PR_RE_404);
case 408: case 408:

View File

@ -528,6 +528,10 @@ proxy_parse_retry_on(char **args, int section, struct proxy *curpx,
curpx->retry_type |= PR_RE_DISCONNECTED; curpx->retry_type |= PR_RE_DISCONNECTED;
else if (!strcmp(args[i], "response-timeout")) else if (!strcmp(args[i], "response-timeout"))
curpx->retry_type |= PR_RE_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")) else if (!strcmp(args[i], "404"))
curpx->retry_type |= PR_RE_404; curpx->retry_type |= PR_RE_404;
else if (!strcmp(args[i], "408")) else if (!strcmp(args[i], "408"))