]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: backend: add a new "path-only" option to "balance uri"
authorWilly Tarreau <w@1wt.eu>
Wed, 23 Sep 2020 06:56:29 +0000 (08:56 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 23 Sep 2020 06:56:29 +0000 (08:56 +0200)
Since we've fixed the way URIs are handled in 2.1, some users have started
to experience inconsistencies in "balance uri" between requests received
over H1 and the same ones received over H2. This is caused by the fact
that H1 rarely uses absolute URIs while H2 always uses them. Similar
issues were reported already around replace-uri etc, leading to "pathq"
recently being introduced, so this isn't new.

Here what this patch does is add a new option to "balance uri" to indicate
that the hashing should only start at the path and not cover the authority.
This makes H1 relative URIs and H2 absolute URI hashes equally again.

Some extra options could be added to normalize URIs by always hashing the
authority (or host) in front of them, which would make sure that both
absolute and relative requests provide the same hash. This is left for
later if needed.

doc/configuration.txt
src/backend.c

index 3757a50027db9026383ce167bd39f9bd177172cb..2304c45b3df787d47a57d183033561dc1daeb5fa 100644 (file)
@@ -3211,6 +3211,11 @@ balance url_param <param> [check_post]
                   slash in the request. If both parameters are specified, the
                   evaluation stops when either is reached.
 
+                  A "path-only" parameter indicates that the hashing key starts
+                  at the first '/' of the path. This can be used to ignore the
+                  authority part of absolute URIs, and to make sure that HTTP/1
+                  and HTTP/2 URIs will provide the same hash.
+
       url_param   The URL parameter specified in argument will be looked up in
                   the query string of each HTTP GET request.
 
index 445c73a9716b0fecb7eca207938e3ee10d6033bb..44cda1a28111ab5197d54a9ee2928dc1d3a0b255 100644 (file)
@@ -701,6 +701,11 @@ int assign_server(struct stream *s)
                                        struct ist uri;
 
                                        uri = htx_sl_req_uri(http_get_stline(htxbuf(&s->req.buf)));
+                                       if (s->be->lbprm.arg_opt1 & 2) {
+                                               uri = http_get_path(uri);
+                                               if (!uri.ptr)
+                                                       uri = ist("");
+                                       }
                                        srv = get_server_uh(s->be, uri.ptr, uri.len, prev_srv);
                                }
                                break;
@@ -2374,7 +2379,7 @@ int backend_parse_balance(const char **args, char **err, struct proxy *curproxy)
 
                curproxy->lbprm.algo &= ~BE_LB_ALGO;
                curproxy->lbprm.algo |= BE_LB_ALGO_UH;
-               curproxy->lbprm.arg_opt1 = 0; // "whole"
+               curproxy->lbprm.arg_opt1 = 0; // "whole", "path-only"
                curproxy->lbprm.arg_opt2 = 0; // "len"
                curproxy->lbprm.arg_opt3 = 0; // "depth"
 
@@ -2402,8 +2407,12 @@ int backend_parse_balance(const char **args, char **err, struct proxy *curproxy)
                                curproxy->lbprm.arg_opt1 |= 1;
                                arg += 1;
                        }
+                       else if (!strcmp(args[arg], "path-only")) {
+                               curproxy->lbprm.arg_opt1 |= 2;
+                               arg += 1;
+                       }
                        else {
-                               memprintf(err, "%s only accepts parameters 'len', 'depth', and 'whole' (got '%s').", args[0], args[arg]);
+                               memprintf(err, "%s only accepts parameters 'len', 'depth', 'path-only', and 'whole' (got '%s').", args[0], args[arg]);
                                return -1;
                        }
                }