diff -ru haproxy-1.3.15.7/doc/configuration.txt haproxy-1.3.15.7-cur/doc/configuration.txt
--- haproxy-1.3.15.7/doc/configuration.txt 2008-12-04 11:29:13.000000000 +0100
+++ haproxy-1.3.15.7-cur/doc/configuration.txt 2009-02-24 16:17:19.000000000 +0100
@@ -788,6 +788,19 @@
balance url_param [check_post []]
+ header The Http Header specified in argument will be looked up in
+ each HTTP request.
+
+ With the "Host" header name, an optionnal use_domain_only
+ parameter is available, for reducing the hash algorithm to
+ the main domain part, eg for "haproxy.1wt.eu", only "1wt"
+ will be taken into consideration.
+
+ Example :
+ balance header User-Agent
+ balance header Host
+ balance header Host use_domain_only
+
The definition of the load balancing algorithm is mandatory for a backend
and limited to one per backend.
@@ -795,6 +808,7 @@
balance roundrobin
balance url_param userid
balance url_param session_id check_post 64
+ balance header Host
Note: the following caveats and limitations on using the "check_post"
extension with "url_param" must be considered :
Seulement dans haproxy-1.3.15.7-cur/doc: configuration.txt~
diff -ru haproxy-1.3.15.7/include/types/backend.h haproxy-1.3.15.7-cur/include/types/backend.h
--- haproxy-1.3.15.7/include/types/backend.h 2008-12-04 11:29:13.000000000 +0100
+++ haproxy-1.3.15.7-cur/include/types/backend.h 2009-02-24 16:04:16.000000000 +0100
@@ -43,6 +43,7 @@
#define BE_LB_ALGO_UH (BE_LB_PROP_L7 | 0x03) /* balance on URI hash */
#define BE_LB_ALGO_PH (BE_LB_PROP_L7 | 0x04) /* balance on URL parameter hash */
#define BE_LB_ALGO_LC (BE_LB_PROP_DYN | 0x05) /* fast weighted round-robin mode (dynamic) */
+#define BE_LB_ALGO_HH (BE_LB_PROP_L7 | 0x06) /* balance on Http Header value */
/* various constants */
diff -ru haproxy-1.3.15.7/include/types/proxy.h haproxy-1.3.15.7-cur/include/types/proxy.h
--- haproxy-1.3.15.7/include/types/proxy.h 2008-12-04 11:29:13.000000000 +0100
+++ haproxy-1.3.15.7-cur/include/types/proxy.h 2009-02-24 16:04:16.000000000 +0100
@@ -166,6 +166,9 @@
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 */
+ char *header_name; /* name of the header parameter used for hashing */
+ int header_len; /* strlen(header_name), computed only once */
+ int header_match_domain; /* toggle use of special match function */
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 */
diff -ru haproxy-1.3.15.7/src/backend.c haproxy-1.3.15.7-cur/src/backend.c
--- haproxy-1.3.15.7/src/backend.c 2008-12-04 11:29:13.000000000 +0100
+++ haproxy-1.3.15.7-cur/src/backend.c 2009-02-24 16:04:16.000000000 +0100
@@ -1281,6 +1281,85 @@
return NULL;
}
+/*
+ * This function tries to find a running server for the proxy following
+ * the Header parameter hash method. It looks for a specific parameter in the
+ * URL and hashes it to compute the server ID. This is useful to optimize
+ * performance by avoiding bounces between servers in contexts where sessions
+ * are shared but cookies are not usable. If the parameter is not found, NULL
+ * is returned. If any server is found, it will be returned. If no valid server
+ * is found, NULL is returned.
+ */
+struct server *get_server_hh(struct session *s)
+{
+ unsigned long hash = 0;
+ struct http_txn *txn = &s->txn;
+ struct http_msg *msg = &txn->req;
+ struct proxy *px = s->be;
+ unsigned int plen = px->header_len;
+ unsigned long len;
+ struct hdr_ctx ctx;
+ const char *p;
+
+ /* tot_weight appears to mean srv_count */
+ if (px->lbprm.tot_weight == 0)
+ return NULL;
+
+ if (px->lbprm.map.state & PR_MAP_RECALC)
+ recalc_server_map(px);
+
+ ctx.idx = 0;
+
+ /* if the message is chunked, we skip the chunk size, but use the value as len */
+ http_find_header2(px->header_name, plen, msg->sol, &txn->hdr_idx, &ctx);
+ if ( ctx.idx ) {
+ /* Found a the header_name in the headers
+ we will compute the hash based on this value ctx.val */
+ len = ctx.vlen;
+ p = (char *)ctx.line + ctx.val;
+ fprintf (stderr, "Found value for %s: '%.*s', length %i\n",
+ px->header_name,
+ (int)len, p, (int)len
+ );
+
+ fprintf (stderr, "Hashing on: ");
+ if (!px->header_match_domain) {
+ while (len) {
+ fprintf (stderr, "%c",*p);
+ hash = *p + (hash << 6) + (hash << 16) - hash;
+ len--;
+ p++;
+ }
+ } else {
+ p += len - 1;
+ int dohash = 0;
+ /* special computation, use only main domain name, not tld/host
+ going back from the end of string, start hashing at first
+ dot stop at next.
+ This is only compatible with 'Host' header, need a special
+ option to activate this
+ */
+ while (len) {
+ if (*p == '.') {
+ if (!dohash) {dohash = 1;}
+ else { break; }
+ } else {
+ if (dohash) {
+ fprintf (stderr, "%c",*p);
+ hash = *p + (hash << 6) + (hash << 16) - hash;
+ }
+ }
+ len--;
+ p--;
+ }
+ }
+
+ fprintf (stderr, "\n");
+ return px->lbprm.map.srv[hash % px->lbprm.tot_weight];
+ }
+ return NULL;
+}
+
/*
* This function applies the load-balancing algorithm to the session, as
@@ -1400,6 +1479,19 @@
}
}
break;
+ case BE_LB_ALGO_HH:
+ /* Header Parameter hashing */
+ s->srv = get_server_hh(s);
+
+ if (!s->srv) {
+ /* parameter not found, fall back to round robin on the map */
+ s->srv = get_server_rr_with_conns(s->be, s->prev_srv);
+ if (!s->srv) {
+ err = SRV_STATUS_FULL;
+ goto out;
+ }
+ }
+ break;
default:
/* unknown balancing algorithm */
err = SRV_STATUS_INTERNAL;
@@ -2077,8 +2169,31 @@
curproxy->url_param_post_limit = 3; /* minimum example: S=3 or \r\nS=6& */
}
}
+ else if (!strcmp(args[0], "header")) {
+ if (!*args[1]) {
+ snprintf(err, errlen, "'balance header' requires an http header field name.");
+ return -1;
+ }
+ curproxy->lbprm.algo &= ~BE_LB_ALGO;
+ curproxy->lbprm.algo |= BE_LB_ALGO_HH;
+ if (curproxy->header_name)
+ free(curproxy->header_name);
+ curproxy->header_name = strdup(args[1]);
+ curproxy->header_len = strlen(args[1]);
+ curproxy->header_match_domain = 0;
+
+ if ( *args[2] ) {
+ if (strcmp(args[2], "use_domain_only") ||
+ strcmp(args[1], "Host")) {
+ snprintf(err, errlen, "'balance header Host' only accepts use_domain_only modifier.");
+ return -1;
+ }
+ curproxy->header_match_domain = 1;
+ }
+
+ }
else {
- snprintf(err, errlen, "'balance' only supports 'roundrobin', 'leastconn', 'source', 'uri' and 'url_param' options.");
+ snprintf(err, errlen, "'balance' only supports 'roundrobin', 'leastconn', 'source', 'uri', 'url_param' and 'header' options.");
return -1;
}
return 0;