]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] add support for URI hash depth and length limits
authorMarek Majkowski <majek04@gmail.com>
Sun, 27 Apr 2008 21:25:55 +0000 (23:25 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 27 Apr 2008 22:43:55 +0000 (00:43 +0200)
This patch adds two optional arguments "len" and "depth" to
"balance uri". They are used to limit the length in characters
of the analysis, as well as the number of directory components
it applies to.

doc/configuration.txt
include/proto/backend.h
include/types/proxy.h
src/backend.c

index 3564ad8eb90913b941fe0a6a27fda85b286251ef..399bebb6d53a6dd592680ee75c73d9ec04777dc5 100644 (file)
@@ -745,6 +745,20 @@ balance url_param <param> [check_post [<max_wait>]]
                   that changing a server's weight on the fly will have no
                   effect.
 
+                  This algorithm support two optional parameters "len" and
+                  "depth", both followed by a positive integer number. These
+                  options may be helpful when it is needed to balance servers
+                  based on the beginning of the URI only. The "len" parameter
+                  indicates that the algorithm should only consider that many
+                  characters at the beginning of the URI to compute the hash.
+                  Note that having "len" set to 1 rarely makes sense since most
+                  URIs start with a leading "/".
+
+                  The "depth" parameter indicates the maximum directory depth
+                  to be used to compute the hash. One level is counted for each
+                  slash in the request. If both parameters are specified, the
+                  evaluation stops when either is reached.
+
       url_param   The URL parameter specified in argument will be looked up in
                   the query string of each HTTP GET request.
 
@@ -783,9 +797,10 @@ balance url_param <param> [check_post [<max_wait>]]
                   server's weight on the fly will have no effect.
 
     <arguments> is an optional list of arguments which may be needed by some
-                algorithms. Right now, only the "url_param" algorithm supports
-                an optional argument.
+                algorithms. Right now, only "url_param" and "uri" support an
+                optional argument.
 
+                balance uri [len <len>] [depth <depth>]
                 balance url_param <param> [check_post [<max_wait>]]
 
   The definition of the load balancing algorithm is mandatory for a backend
index 03fa518cae1b13341e66bdb0136a2ce8fc5d86cc..aa27654f39d7611826d13cdffecaca9b71316bfa 100644 (file)
@@ -159,6 +159,7 @@ static inline struct server *get_server_uh(struct proxy *px, char *uri, int uri_
 {
        unsigned long hash = 0;
        int c;
+       int slashes = 0;
 
        if (px->lbprm.tot_weight == 0)
                return NULL;
@@ -166,10 +167,19 @@ static inline struct server *get_server_uh(struct proxy *px, char *uri, int uri_
        if (px->lbprm.map.state & PR_MAP_RECALC)
                recalc_server_map(px);
 
+       if (px->uri_len_limit)
+               uri_len = MIN(uri_len, px->uri_len_limit);
+
        while (uri_len--) {
                c = *uri++;
-               if (c == '?')
+               if (c == '/') {
+                       slashes++;
+                       if (slashes == px->uri_dirs_depth1) /* depth+1 */
+                               break;
+               }
+               else if (c == '?')
                        break;
+
                hash = c + (hash << 6) + (hash << 16) - hash;
        }
 
index 091be57e2eb2e45b511d2ab851e2f9638152727f..fe69b08967471604b7276d0091ba787e71eebefc 100644 (file)
@@ -166,6 +166,8 @@ struct proxy {
        char *url_param_name;                   /* name of the URL parameter used for hashing */
        int  url_param_len;                     /* strlen(url_param_name), computed only once */
        unsigned url_param_post_limit;          /* if checking POST body for URI parameter, max body to wait for */
+       int  uri_len_limit;                     /* character limit for uri balancing algorithm */
+       int  uri_dirs_depth1;                   /* directories+1 (slashes) limit for uri balancing algorithm */
        char *appsession_name;                  /* name of the cookie to look for */
        int  appsession_name_len;               /* strlen(appsession_name), computed only once */
        int  appsession_len;                    /* length of the appsession cookie value to be used */
index 649756787252976927b03b2abfc72fb7d24da255..9ced724a467bc9fd2f57938ab49589ae0d5ec14e 100644 (file)
@@ -1973,8 +1973,36 @@ int backend_parse_balance(const char **args, char *err, int errlen, struct proxy
                curproxy->lbprm.algo |= BE_LB_ALGO_SH;
        }
        else if (!strcmp(args[0], "uri")) {
+               int arg = 1;
+
                curproxy->lbprm.algo &= ~BE_LB_ALGO;
                curproxy->lbprm.algo |= BE_LB_ALGO_UH;
+
+               while (*args[arg]) {
+                       if (!strcmp(args[arg], "len")) {
+                               if (!*args[arg+1] || (atoi(args[arg+1]) <= 0)) {
+                                       snprintf(err, errlen, "'balance uri len' expects a positive integer (got '%s').", args[arg+1]);
+                                       return -1;
+                               }
+                               curproxy->uri_len_limit = atoi(args[arg+1]);
+                               arg += 2;
+                       }
+                       else if (!strcmp(args[arg], "depth")) {
+                               if (!*args[arg+1] || (atoi(args[arg+1]) <= 0)) {
+                                       snprintf(err, errlen, "'balance uri depth' expects a positive integer (got '%s').", args[arg+1]);
+                                       return -1;
+                               }
+                               /* hint: we store the position of the ending '/' (depth+1) so
+                                * that we avoid a comparison while computing the hash.
+                                */
+                               curproxy->uri_dirs_depth1 = atoi(args[arg+1]) + 1;
+                               arg += 2;
+                       }
+                       else {
+                               snprintf(err, errlen, "'balance uri' only accepts parameters 'len' and 'depth' (got '%s').", args[arg]);
+                               return -1;
+                       }
+               }
        }
        else if (!strcmp(args[0], "url_param")) {
                if (!*args[1]) {
@@ -1987,7 +2015,7 @@ int backend_parse_balance(const char **args, char *err, int errlen, struct proxy
                        free(curproxy->url_param_name);
                curproxy->url_param_name = strdup(args[1]);
                curproxy->url_param_len = strlen(args[1]);
-               if ( *args[2] ) {
+               if (*args[2]) {
                        if (strcmp(args[2], "check_post")) {
                                snprintf(err, errlen, "'balance url_param' only accepts check_post modifier.");
                                return -1;