mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 13:51:26 +02:00
[MEDIUM] Implement and use generic findproxy and relax duplicated proxy check
This patch: - adds proxy_mode_str() similar to proxy_type_str() - adds a generic findproxy function used with default_backend/setbe/use_backed - rewrite default_backend/senbe/use_backed to use introduced findproxy() - relaxes duplicated proxy check - changes capabilities displaying from "%X" to "%s" with a call to proxy_type_str()
This commit is contained in:
parent
2ee30416af
commit
6eb730ded9
@ -32,8 +32,10 @@ void soft_stop(void);
|
||||
void pause_proxy(struct proxy *p);
|
||||
void pause_proxies(void);
|
||||
void listen_proxies(void);
|
||||
const char *proxy_type_str(struct proxy *proxy);
|
||||
|
||||
const char *proxy_type_str(struct proxy *proxy);
|
||||
const char *proxy_mode_str(int mode);
|
||||
struct proxy *findproxy(const char *name, int mode, int cap);
|
||||
|
||||
#endif /* _PROTO_PROXY_H */
|
||||
|
||||
|
@ -539,9 +539,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
|
||||
if (!strcmp(curproxy->id, args[1]) &&
|
||||
(rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
|
||||
(rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
|
||||
Alert("parsing %s: duplicated proxy %s with conflicting capabilities: %X/%X!\n",
|
||||
file, args[1], curproxy->cap, rc);
|
||||
return -1;
|
||||
Warning("Parsing [%s:%d]: duplicated proxy '%s' with conflicting capabilities: %s/%s!\n",
|
||||
file, linenum, args[1], proxy_type_str(curproxy), args[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2529,21 +2528,14 @@ int readcfgfile(const char *file)
|
||||
if (curproxy->defbe.name) {
|
||||
struct proxy *target;
|
||||
|
||||
for (target = proxy; target != NULL; target = target->next) {
|
||||
if ((target->cap & PR_CAP_BE) && !strcmp(target->id, curproxy->defbe.name))
|
||||
break;
|
||||
}
|
||||
if (target == NULL) {
|
||||
Alert("parsing %s: default proxy '%s' with backend capability in HTTP %s '%s' was not found!\n",
|
||||
file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
|
||||
target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
|
||||
if (!target) {
|
||||
Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
|
||||
curproxy->id, curproxy->defbe.name);
|
||||
cfgerr++;
|
||||
} else if (target == curproxy) {
|
||||
Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
|
||||
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++;
|
||||
Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
|
||||
curproxy->id, curproxy->defbe.name);
|
||||
} else {
|
||||
free(curproxy->defbe.name);
|
||||
curproxy->defbe.be = target;
|
||||
@ -2554,24 +2546,20 @@ int readcfgfile(const char *file)
|
||||
if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
|
||||
/* map jump target for ACT_SETBE in req_rep chain */
|
||||
struct hdr_exp *exp;
|
||||
struct proxy *target;
|
||||
for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
|
||||
struct proxy *target;
|
||||
|
||||
if (exp->action != ACT_SETBE)
|
||||
continue;
|
||||
for (target = proxy; target != NULL; target = target->next) {
|
||||
if ((target->cap & PR_CAP_BE) && !strcmp(target->id, exp->replace))
|
||||
break;
|
||||
}
|
||||
if (target == NULL) {
|
||||
Alert("parsing %s: proxy '%s' with backend capability in HTTP %s '%s' was not found!\n",
|
||||
file, exp->replace, proxy_type_str(curproxy), curproxy->id);
|
||||
|
||||
target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
|
||||
if (!target) {
|
||||
Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
|
||||
curproxy->id, exp->replace);
|
||||
cfgerr++;
|
||||
} else if (target == curproxy) {
|
||||
Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
|
||||
cfgerr++;
|
||||
} else if (target->mode != PR_MODE_HTTP) {
|
||||
Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
|
||||
file, exp->replace, proxy_type_str(curproxy), curproxy->id);
|
||||
Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
|
||||
curproxy->id, exp->replace);
|
||||
cfgerr++;
|
||||
} else {
|
||||
free((void *)exp->replace);
|
||||
@ -2582,24 +2570,17 @@ int readcfgfile(const char *file)
|
||||
|
||||
/* find the target proxy for 'use_backend' rules */
|
||||
list_for_each_entry(rule, &curproxy->switching_rules, list) {
|
||||
/* map jump target for ACT_SETBE in req_rep chain */
|
||||
struct proxy *target;
|
||||
|
||||
for (target = proxy; target != NULL; target = target->next) {
|
||||
if ((target->cap & PR_CAP_BE) && !strcmp(target->id, rule->be.name))
|
||||
break;
|
||||
}
|
||||
target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
|
||||
|
||||
if (target == NULL) {
|
||||
Alert("parsing %s: proxy '%s' with backend capability in HTTP %s '%s' was not found!\n",
|
||||
file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
|
||||
if (!target) {
|
||||
Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
|
||||
curproxy->id, rule->be.name);
|
||||
cfgerr++;
|
||||
} else if (target == curproxy) {
|
||||
Alert("parsing %s : loop detected for backend %s !\n", file, rule->be.name);
|
||||
cfgerr++;
|
||||
} else if (target->mode != curproxy->mode) {
|
||||
Alert("parsing %s : backend '%s' referenced in %s '%s' is of different mode !\n",
|
||||
file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
|
||||
Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
|
||||
curproxy->id, rule->be.name);
|
||||
cfgerr++;
|
||||
} else {
|
||||
free((void *)rule->be.name);
|
||||
|
51
src/proxy.c
51
src/proxy.c
@ -55,6 +55,57 @@ const char *proxy_type_str(struct proxy *proxy)
|
||||
return "proxy";
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns a string containing the mode of the proxy in a format
|
||||
* suitable for error messages.
|
||||
*/
|
||||
|
||||
const char *proxy_mode_str(int mode) {
|
||||
|
||||
if (mode == PR_MODE_TCP)
|
||||
return "tcp";
|
||||
else if (mode == PR_MODE_HTTP)
|
||||
return "http";
|
||||
else if (mode == PR_MODE_HEALTH)
|
||||
return "health";
|
||||
else
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/*
|
||||
* This function finds a proxy with matching name, mode and with satisfying
|
||||
* capabilities. It also checks if there are more matching proxies with
|
||||
* requested name as this often leads into unexpected situations.
|
||||
*/
|
||||
|
||||
struct proxy *findproxy(const char *name, int mode, int cap) {
|
||||
|
||||
struct proxy *curproxy, *target=NULL;
|
||||
|
||||
for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
|
||||
if ((curproxy->cap & cap)!=cap || strcmp(curproxy->id, name))
|
||||
continue;
|
||||
|
||||
if (curproxy->mode != mode) {
|
||||
Alert("Unable to use proxy '%s' with wrong mode, required: %s, has: %s.\n",
|
||||
name, proxy_mode_str(mode), proxy_mode_str(curproxy->mode));
|
||||
Alert("You may want to use 'mode %s'.\n", proxy_mode_str(mode));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!target) {
|
||||
target = curproxy;
|
||||
continue;
|
||||
}
|
||||
|
||||
Alert("Refusing to use duplicated proxy '%s' with conflicting capabilities: %s/%s!\n",
|
||||
name, proxy_type_str(curproxy), proxy_type_str(target));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function creates all proxy sockets. It should be done very early,
|
||||
|
Loading…
x
Reference in New Issue
Block a user