[MEDIUM] implemented the "default_backend" keyword
The "default_backend" keyword used in a frontend sets the
default backend which will be used if no setbe rule matches.
diff --git a/include/types/proxy.h b/include/types/proxy.h
index d710be8..71f0f5c 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -76,6 +76,10 @@
int state; /* proxy state */
struct sockaddr_in dispatch_addr; /* the default address to connect to */
struct proxy *fiprm, *beprm; /* proxy we find filter and backend params from (default: self) */
+ union {
+ struct proxy *be; /* default backend, or NULL if none set */
+ char *name; /* default backend name during config parse */
+ } defbe;
struct server *srv; /* known servers */
int srv_act, srv_bck; /* # of running servers */
int tot_wact, tot_wbck; /* total weights of active and backup servers */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 9589841..38d894a 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -501,6 +501,8 @@
if (defproxy.monitor_uri)
curproxy->monitor_uri = strdup(defproxy.monitor_uri);
curproxy->monitor_uri_len = defproxy.monitor_uri_len;
+ if (defproxy.defbe.name)
+ curproxy->defbe.name = strdup(defproxy.defbe.name);
}
if (curproxy->cap & PR_CAP_BE) {
@@ -522,10 +524,14 @@
}
else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
/* some variables may have already been initialized earlier */
+ /* FIXME-20070101: we should do this too at the end of the
+ * config parsing to free all default values.
+ */
if (defproxy.check_req) free(defproxy.check_req);
if (defproxy.cookie_name) free(defproxy.cookie_name);
if (defproxy.capture_name) free(defproxy.capture_name);
if (defproxy.monitor_uri) free(defproxy.monitor_uri);
+ if (defproxy.defbe.name) free(defproxy.defbe.name);
for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
if (defproxy.errmsg[rc].len)
@@ -981,6 +987,18 @@
}
return 0;
}
+ else if (!strcmp(args[0], "default_backend")) {
+ if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
+ return 0;
+
+ if (*(args[1]) == 0) {
+ Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
+ return -1;
+ }
+ if (curproxy->defbe.name)
+ free(curproxy->defbe.name);
+ curproxy->defbe.name = strdup(args[1]);
+ }
else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
return 0;
@@ -2100,9 +2118,39 @@
Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
file, curproxy->id);
cfgerr++;
+ }
+ }
+
+ /* if a default backend was specified, let's find it */
+ if (curproxy->defbe.name) {
+ struct proxy *target;
+
+ for (target = proxy; target != NULL; target = target->next) {
+ if (strcmp(target->id, curproxy->defbe.name) == 0)
+ break;
+ }
+ if (target == NULL) {
+ Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
+ file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
+ cfgerr++;
+ } else if (target == curproxy) {
+ Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
+ cfgerr++;
+ } else if (!(target->cap & PR_CAP_BE)) {
+ Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
+ file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
+ cfgerr++;
+ } else if (target->mode != curproxy->mode) {
+ Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
+ file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
+ cfgerr++;
+ } else {
+ free(curproxy->defbe.name);
+ curproxy->defbe.be = target;
}
}
+ /* find the target proxy in setbe */
if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
/* map jump target for ACT_SETBE in req_rep chain */
struct hdr_exp *exp;
diff --git a/src/proto_http.c b/src/proto_http.c
index 75fd152..0202ba2 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1087,7 +1087,19 @@
return 1;
}
- } while (cur_proxy != t->be); /* we loop only if t->be has changed */
+ if (!(t->flags & SN_BE_ASSIGNED) && cur_proxy->defbe.be) {
+ /* No backend was set, but there was a default
+ * backend set in the frontend, so we use it and
+ * loop again.
+ */
+ t->be = cur_proxy->defbe.be;
+ t->be->beprm->beconn++;
+ if (t->be->beprm->beconn > t->be->beprm->beconn_max)
+ t->be->beprm->beconn_max = t->be->beprm->beconn;
+ t->be->beprm->cum_beconn++;
+ t->flags |= SN_BE_ASSIGNED;
+ }
+ } while (t->be != cur_proxy); /* we loop only if t->be has changed */
if (!(t->flags & SN_BE_ASSIGNED)) {