May be used in sections : defaults | frontend | listen | backend
no | no | yes | yes
Arguments :
- <server> is the name of a valid server in the same backend section.
+ <server> is the name of a valid server in the same backend section
+ or a "log-format" string resolving to a server name.
<condition> is a condition composed of ACLs, as described in section 7.
# all the rest is forwarded to this server
server default 192.168.0.2:443 check
+ When <server> is a simple name, it is checked against existing servers in the
+ configuration and an error is reported if the specified server does not exist.
+ If it is a log-format, no check is performed when parsing the configuration,
+ and if we can't resolve a valid server name at runtime but the use-server rule
+ was conditionned by an ACL returning true, no other use-server rule is applied
+ and we fall back to load balancing.
+
See also: "use_backend", section 5 about server and section 7 about ACLs.
ARGC_SRV, /* server line */
ARGC_SPOE, /* spoe message args */
ARGC_UBK, /* use_backend message */
+ ARGC_USRV, /* use-server message */
};
/* flags used when compiling and executing regex */
struct server_rule {
struct list list; /* list linked to from the proxy */
struct acl_cond *cond; /* acl condition to meet */
+ int dynamic;
union {
struct server *ptr; /* target server */
char *name; /* target server name during config parsing */
} srv;
+ struct list expr; /* logformat expression to use for dynamic rules */
+ char *file;
+ int line;
};
struct persist_rule {
rule = calloc(1, sizeof(*rule));
rule->cond = cond;
rule->srv.name = strdup(args[1]);
+ rule->line = linenum;
+ rule->file = strdup(file);
LIST_INIT(&rule->list);
LIST_ADDQ(&curproxy->server_rules, &rule->list);
curproxy->be_req_ana |= AN_REQ_SRV_RULES;
/* find the target server for 'use_server' rules */
list_for_each_entry(srule, &curproxy->server_rules, list) {
- struct server *target = findserver(curproxy, srule->srv.name);
+ struct server *target;
+ struct logformat_node *node;
+ char *server_name;
+
+ /* We try to parse the string as a log format expression. If the result of the parsing
+ * is only one entry containing a single string, then it's a standard string corresponding
+ * to a static rule, thus the parsing is cancelled and we fall back to setting srv.ptr.
+ */
+ server_name = srule->srv.name;
+ LIST_INIT(&srule->expr);
+ curproxy->conf.args.ctx = ARGC_USRV;
+ err = NULL;
+ if (!parse_logformat_string(server_name, curproxy, &srule->expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
+ ha_alert("Parsing [%s:%d]; use-server rule failed to parse log-format '%s' : %s.\n",
+ srule->file, srule->line, server_name, err);
+ free(err);
+ cfgerr++;
+ continue;
+ }
+ node = LIST_NEXT(&srule->expr, struct logformat_node *, list);
+
+ if (!LIST_ISEMPTY(&srule->expr)) {
+ if (node->type != LOG_FMT_TEXT || node->list.n != &srule->expr) {
+ srule->dynamic = 1;
+ free(server_name);
+ continue;
+ }
+ free(node->arg);
+ free(node);
+ }
+
+ srule->dynamic = 0;
+ srule->srv.name = server_name;
+ target = findserver(curproxy, srule->srv.name);
if (!target) {
ha_alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
ret = !ret;
if (ret) {
- struct server *srv = rule->srv.ptr;
+ struct server *srv;
+
+ if (rule->dynamic) {
+ struct buffer *tmp = get_trash_chunk();
+
+ if (!build_logline(s, tmp->area, tmp->size, &rule->expr))
+ break;
+
+ srv = findserver(s->be, tmp->area);
+ if (!srv)
+ break;
+ }
+ else
+ srv = rule->srv.ptr;
if ((srv->cur_state != SRV_ST_STOPPED) ||
(px->options & PR_O_PERSIST) ||