mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 15:47:01 +02:00
MINOR: cfgparse/server: try to fix spelling mistakes on server lines
Let's apply the fuzzy match to server keywords so that we can avoid dumping the huge list of supported keywords each time there is a spelling mistake, and suggest proper spelling instead: $ printf "listen f\nserver s 0 sendpx-v2\n" | ./haproxy -c -f /dev/stdin [NOTICE] 070/095718 (24152) : haproxy version is 2.4-dev11-caa6e3-25 [NOTICE] 070/095718 (24152) : path to executable is ./haproxy [ALERT] 070/095718 (24152) : parsing [/dev/stdin:2] : 'server s' unknown keyword 'sendpx-v2'; did you mean 'send-proxy-v2' maybe ? [ALERT] 070/095718 (24152) : Error(s) found in configuration file : /dev/stdin [ALERT] 070/095718 (24152) : Fatal errors found in configuration.
This commit is contained in:
parent
a0e8eb8caa
commit
49c2b45c1d
78
src/server.c
78
src/server.c
@ -50,6 +50,19 @@ static void srv_update_status(struct server *s);
|
||||
static int srv_apply_lastaddr(struct server *srv, int *err_code);
|
||||
static void srv_cleanup_connections(struct server *srv);
|
||||
|
||||
/* some keywords that are still being parsed using strcmp() and are not
|
||||
* registered anywhere. They are used as suggestions for mistyped words.
|
||||
*/
|
||||
static const char *common_kw_list[] = {
|
||||
"init-addr", "resolvers", "resolve-opts", "resolve-prefer", "ipv4",
|
||||
"ipv6", "resolve-net", "weight", "log-proto", "legacy", "octet-count",
|
||||
"minconn", "maxconn", "maxqueue", "slowstart", "on-error", "fastinter",
|
||||
"fail-check", "sudden-death", "mark-down", "on-marked-down",
|
||||
"shutdown-sessions", "on-marked-up", "shutdown-backup-sessions",
|
||||
"error-limit", "usesrc",
|
||||
NULL /* must be last */
|
||||
};
|
||||
|
||||
/* List head of all known server keywords */
|
||||
static struct srv_kw_list srv_keywords = {
|
||||
.list = LIST_HEAD_INIT(srv_keywords.list)
|
||||
@ -287,6 +300,50 @@ void srv_dump_kws(char **out)
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to find in srv_keyword the word that looks closest to <word> by counting
|
||||
* transitions between letters, digits and other characters. Will return the
|
||||
* best matching word if found, otherwise NULL. An optional array of extra
|
||||
* words to compare may be passed in <extra>, but it must then be terminated
|
||||
* by a NULL entry. If unused it may be NULL.
|
||||
*/
|
||||
static const char *srv_find_best_kw(const char *word)
|
||||
{
|
||||
uint8_t word_sig[1024];
|
||||
uint8_t list_sig[1024];
|
||||
const struct srv_kw_list *kwl;
|
||||
const char *best_ptr = NULL;
|
||||
int dist, best_dist = INT_MAX;
|
||||
const char **extra;
|
||||
int index;
|
||||
|
||||
make_word_fingerprint(word_sig, word);
|
||||
list_for_each_entry(kwl, &srv_keywords.list, list) {
|
||||
for (index = 0; kwl->kw[index].kw != NULL; index++) {
|
||||
make_word_fingerprint(list_sig, kwl->kw[index].kw);
|
||||
dist = word_fingerprint_distance(word_sig, list_sig);
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best_ptr = kwl->kw[index].kw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (extra = common_kw_list; *extra; extra++) {
|
||||
make_word_fingerprint(list_sig, *extra);
|
||||
dist = word_fingerprint_distance(word_sig, list_sig);
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best_ptr = *extra;
|
||||
}
|
||||
extra++;
|
||||
}
|
||||
|
||||
if (best_dist > 2 * strlen(word) || (best_ptr && best_dist > 2 * strlen(best_ptr)))
|
||||
best_ptr = NULL;
|
||||
|
||||
return best_ptr;
|
||||
}
|
||||
|
||||
/* Parse the "backup" server keyword */
|
||||
static int srv_parse_backup(char **args, int *cur_arg,
|
||||
struct proxy *curproxy, struct server *newsrv, char **err)
|
||||
@ -2394,9 +2451,8 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
static int srv_dumped;
|
||||
struct srv_kw *kw;
|
||||
char *err;
|
||||
const char *best;
|
||||
|
||||
kw = srv_find_kw(args[cur_arg]);
|
||||
if (kw) {
|
||||
@ -2439,17 +2495,13 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
|
||||
continue;
|
||||
}
|
||||
|
||||
err = NULL;
|
||||
if (!srv_dumped) {
|
||||
srv_dump_kws(&err);
|
||||
indent_msg(&err, 4);
|
||||
srv_dumped = 1;
|
||||
}
|
||||
|
||||
ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
|
||||
file, linenum, args[0], args[1], args[cur_arg],
|
||||
err ? " Registered keywords :" : "", err ? err : "");
|
||||
free(err);
|
||||
best = srv_find_best_kw(args[cur_arg]);
|
||||
if (best)
|
||||
ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'; did you mean '%s' maybe ?\n",
|
||||
file, linenum, args[0], args[1], args[cur_arg], best);
|
||||
else
|
||||
ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.\n",
|
||||
file, linenum, args[0], args[1], args[cur_arg]);
|
||||
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
|
Loading…
Reference in New Issue
Block a user