From: Daniel Dickinson <open...@daniel.thecshore.com> We prefer either a path match (e.g. interpreter extension match) then the longest matching prefix (e.g. /cgi-bin/luci handler is used except if a prefix matches a virtual url before the path matching logic is hit. Note that we now allow a handler to have both check_url and check_path to support this. Also note that if a handler has both a path match and a prefix match AND one of its prefixes is the most specific match for this url, then before path_lookup this code will return NULL (no match) to ensure that the path match has a chance to override the prefix.
Signed-off-by: Daniel Dickinson <l...@daniel.thecshore.com> --- NOTE: This is basically untested and is provided to solicit comments for something for which there may be no interest before spending more time on it. cgi.c | 11 ++++++++++- file.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- lua.c | 6 ++++-- proxy.c | 6 +++--- ubus.c | 6 ++++-- uhttpd.h | 2 +- 6 files changed, 73 insertions(+), 18 deletions(-) diff --git a/cgi.c b/cgi.c index dc302a9..b274e4c 100644 --- a/cgi.c +++ b/cgi.c @@ -84,6 +84,14 @@ static void cgi_handle_request(struct client *cl, char *url, struct path_info *p return; } +static const char *check_cgi_url(const char *url) +{ + if (uh_path_match(conf.cgi_docroot_path, url)) + return conf.cgi_docroot_path; + + return NULL; +} + static bool check_cgi_path(struct path_info *pi, const char *url) { struct interpreter *ip; @@ -104,11 +112,12 @@ static bool check_cgi_path(struct path_info *pi, const char *url) } pi->ip = NULL; - return uh_path_match(conf.cgi_docroot_path, pi->phys); + return false; } struct dispatch_handler cgi_dispatch = { .script = true, .check_path = check_cgi_path, + .check_url = check_cgi_url, .handle_request = cgi_handle_request, }; diff --git a/file.c b/file.c index 12aa130..6d7ff0c 100644 --- a/file.c +++ b/file.c @@ -38,6 +38,7 @@ static LIST_HEAD(index_files); static LIST_HEAD(dispatch_handlers); static LIST_HEAD(pending_requests); +static LIST_HEAD(matches); static int n_requests; struct deferred_request { @@ -654,27 +655,68 @@ void uh_dispatch_add(struct dispatch_handler *d) } static struct dispatch_handler * +dispatch_check_match(struct dispatch_handler *d, const char *url, size_t *max_len) { + const char *matching_path; + size_t len; + + if (d->check_url) + if ((matching_path = d->check_url(url))) { + len = strlen(matching_path); + if (len > *max_len) { + *max_len = len; + return d; + } + } + + return NULL; +} + +/* We prefer either a path match (e.g. interpreter extension match) + * then the longest matching prefix (e.g. /cgi-bin/luci handler is used + * except if a prefix matches a virtual url before the path matching + * logic is hit. + * Note that we now allow a handler to have both check_url and check_path + * to support this. + * Also note that if a handler has both a path match and a prefix match + * AND one of its prefixes is the most specific match for this url, + * then before path_lookup this code will return NULL (no match) + * to ensure that the path match has a chance to override the prefix. + */ +static struct dispatch_handler * dispatch_find(const char *url, struct path_info *pi) { struct dispatch_handler *d; + struct dispatch_handler *m = NULL; + size_t max_len = 0; list_for_each_entry(d, &dispatch_handlers, list) { if (pi) { - if (d->check_url) - continue; - + /* Prefer a path (e.g. interpreter extension) + * match to a prefix match + */ if (d->check_path(pi, url)) return d; - } else { - if (d->check_path) - continue; - if (d->check_url(url)) - return d; + if (dispatch_check_match(d, url, &max_len)) + m = d; + } else { + /* for handlers with both prefixes and path matches we + * want the path match to actually occur which means + * that we can't check prefixes until after path_lookup + * is done and we have the final path. + */ + + if (dispatch_check_match(d, url, &max_len)) { + if (d->check_path) { + m = NULL; + } else { + m = d; + } + } } } - return NULL; + return m; } static void diff --git a/lua.c b/lua.c index 2134904..e708778 100644 --- a/lua.c +++ b/lua.c @@ -275,9 +275,11 @@ static void lua_handle_request(struct client *cl, char *url, struct path_info *p } } -static bool check_lua_url(const char *url) +static const char *check_lua_url(const char *url) { - return ops->path_match(conf.lua_prefix, url); + if (ops->path_match(conf.lua_prefix, url)) + return conf.lua_prefix; + return NULL; } static struct dispatch_handler lua_dispatch = { diff --git a/proxy.c b/proxy.c index 27c856b..da22136 100644 --- a/proxy.c +++ b/proxy.c @@ -389,14 +389,14 @@ static void proxy_handle_request(struct client *cl, char *url, struct path_info } -static bool check_proxy_url(const char *url) +static const char *check_proxy_url(const char *url) { struct proxy_uri *p; if (!list_empty(&conf.proxies)) list_for_each_entry(p, &conf.proxies, list) if (uh_path_match(p->prefix, url)) - return true; - return false; + return p->prefix; + return NULL; } struct dispatch_handler proxy_dispatch = { diff --git a/ubus.c b/ubus.c index f7d1f11..ed70c50 100644 --- a/ubus.c +++ b/ubus.c @@ -640,10 +640,12 @@ static void uh_ubus_handle_request(struct client *cl, char *url, struct path_inf } } -static bool +static const char * uh_ubus_check_url(const char *url) { - return ops->path_match(conf.ubus_prefix, url); + if (ops->path_match(conf.ubus_prefix, url)) + return conf.ubus_prefix; + return NULL; } static int diff --git a/uhttpd.h b/uhttpd.h index d47b7b4..6569251 100644 --- a/uhttpd.h +++ b/uhttpd.h @@ -214,7 +214,7 @@ struct dispatch_handler { struct list_head list; bool script; - bool (*check_url)(const char *url); + const char * (*check_url)(const char *url); bool (*check_path)(struct path_info *pi, const char *url); void (*handle_request)(struct client *cl, char *url, struct path_info *pi); }; -- 1.9.1 _______________________________________________ Lede-dev mailing list Lede-dev@lists.infradead.org http://lists.infradead.org/mailman/listinfo/lede-dev