MINOR: cfgparse/proxy: also support spelling fixes on options
Some are not always easy to spot with "chk" vs "check" or hyphens at some places and not at others. Now entering "option http-close" properly suggests "httpclose" and "option tcp-chk" suggests "tcp-check". There's no need to consider the proxy's capabilities, what matters is to figure what related word the user tried to spell, and there are not that many options anyway.
This commit is contained in:
parent
b12bc646d5
commit
31a3cea84f
|
@ -49,6 +49,7 @@ int stream_set_backend(struct stream *s, struct proxy *be);
|
|||
|
||||
const char *proxy_cap_str(int cap);
|
||||
const char *proxy_mode_str(int mode);
|
||||
const char *proxy_find_best_option(const char *word, const char **extra);
|
||||
void proxy_store_name(struct proxy *px);
|
||||
struct proxy *proxy_find_by_id(int id, int cap, int table);
|
||||
struct proxy *proxy_find_by_name(const char *name, int cap, int table);
|
||||
|
|
|
@ -54,6 +54,15 @@ static const char *common_kw_list[] = {
|
|||
NULL /* must be last */
|
||||
};
|
||||
|
||||
static const char *common_options[] = {
|
||||
"httpclose", "forceclose", "http-server-close", "http-keep-alive",
|
||||
"http-tunnel", "redispatch", "httplog", "tcplog", "tcpka", "httpchk",
|
||||
"ssl-hello-chk", "smtpchk", "pgsql-check", "redis-check",
|
||||
"mysql-check", "ldap-check", "spop-check", "tcp-check",
|
||||
"external-check", "forwardfor", "original-to",
|
||||
NULL /* must be last */
|
||||
};
|
||||
|
||||
/* Report a warning if a rule is placed after a 'tcp-request session' rule.
|
||||
* Return 1 if the warning has been emitted, otherwise 0.
|
||||
*/
|
||||
|
@ -2238,7 +2247,13 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||
} /* end while loop */
|
||||
}
|
||||
else {
|
||||
ha_alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
|
||||
const char *best = proxy_find_best_option(args[1], common_options);
|
||||
|
||||
if (best)
|
||||
ha_alert("parsing [%s:%d] : unknown option '%s'; did you mean '%s' maybe ?\n", file, linenum, args[1], best);
|
||||
else
|
||||
ha_alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
|
||||
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
49
src/proxy.c
49
src/proxy.c
|
@ -152,6 +152,55 @@ const char *proxy_mode_str(int mode) {
|
|||
return "unknown";
|
||||
}
|
||||
|
||||
/* try to find among known options the one 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.
|
||||
*/
|
||||
const char *proxy_find_best_option(const char *word, const char **extra)
|
||||
{
|
||||
uint8_t word_sig[1024];
|
||||
uint8_t list_sig[1024];
|
||||
const char *best_ptr = NULL;
|
||||
int dist, best_dist = INT_MAX;
|
||||
int index;
|
||||
|
||||
make_word_fingerprint(word_sig, word);
|
||||
|
||||
for (index = 0; cfg_opts[index].name; index++) {
|
||||
make_word_fingerprint(list_sig, cfg_opts[index].name);
|
||||
dist = word_fingerprint_distance(word_sig, list_sig);
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best_ptr = cfg_opts[index].name;
|
||||
}
|
||||
}
|
||||
|
||||
for (index = 0; cfg_opts2[index].name; index++) {
|
||||
make_word_fingerprint(list_sig, cfg_opts2[index].name);
|
||||
dist = word_fingerprint_distance(word_sig, list_sig);
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best_ptr = cfg_opts2[index].name;
|
||||
}
|
||||
}
|
||||
|
||||
while (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;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function scans the list of backends and servers to retrieve the first
|
||||
* backend and the first server with the given names, and sets them in both
|
||||
|
|
Loading…
Reference in New Issue