From 6016a593a32c4f3f27ed3e7892a1595d631fcbef Mon Sep 17 00:00:00 2001 From: Omar Polo Date: Sat, 30 Jan 2021 12:04:20 +0000 Subject: [PATCH] invert the location precedence: first match wins It's how httpd(8) does it, and it allows us to call fnmatch less time --- gmid.1 | 10 +++++----- gmid.h | 4 ++++ server.c | 31 ++++++++++++++++++------------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/gmid.1 b/gmid.1 index 781bf41..34a0591 100644 --- a/gmid.1 +++ b/gmid.1 @@ -223,15 +223,15 @@ The .Pa path argument will be matched against the request path with shell globbing rules. -In case of multiple location statements in the same context, the last -matching location will be put into effect. -Therefore is advisable to match for a generic paths first and for more -specific ones later on. +In case of multiple location statements in the same context, the first +matching location will be put into effect and the later ones ignored. +Therefore is advisable to match for more specific paths first and for +generic ones later on. A .Ic location section may include most of the server configuration rules except -.Ic cert , Ic key , Ic root , Ic location No and Ic CGI . +.Ic cert , Ic key , Ic root , Ic location No and Ic cgi . .El .Sh CGI When CGI scripts are enabled for a directory, a request for an diff --git a/gmid.h b/gmid.h index 2b6a1c8..fc9ec53 100644 --- a/gmid.h +++ b/gmid.h @@ -76,6 +76,10 @@ struct vhost { const char *dir; const char *cgi; int dirfd; + + /* the first location rule is always '*' and holds the default + * settings for the vhost, from locations[1] onwards there are + * the "real" location rules specified in the configuration. */ struct location locations[LOCLEN]; }; diff --git a/server.c b/server.c index 4ee62bc..2be6e68 100644 --- a/server.c +++ b/server.c @@ -33,19 +33,18 @@ const char * vhost_lang(struct vhost *v, const char *path) { struct location *loc; - const char *lang = NULL; if (v == NULL || path == NULL) - return lang; + return NULL; - for (loc = v->locations; loc->match != NULL; ++loc) { + for (loc = &v->locations[1]; loc->match != NULL; ++loc) { if (!fnmatch(loc->match, path, 0)) { if (loc->lang != NULL) - lang = loc->lang; + return loc->lang; } } - return lang; + return v->locations[0].lang; } const char * @@ -57,13 +56,15 @@ vhost_default_mime(struct vhost *v, const char *path) if (v == NULL || path == NULL) return default_mime; - for (loc = v->locations; loc->match != NULL; ++loc) { + for (loc = &v->locations[1]; loc->match != NULL; ++loc) { if (!fnmatch(loc->match, path, 0)) { if (loc->default_mime != NULL) - default_mime = loc->default_mime; + return loc->default_mime; } } + if (v->locations[0].default_mime != NULL) + return v->locations[0].default_mime; return default_mime; } @@ -76,13 +77,15 @@ vhost_index(struct vhost *v, const char *path) if (v == NULL || path == NULL) return index; - for (loc = v->locations; loc->match != NULL; ++loc) { + for (loc = &v->locations[1]; loc->match != NULL; ++loc) { if (!fnmatch(loc->match, path, 0)) { if (loc->index != NULL) - index = loc->index; + return loc->index; } } + if (v->locations[0].default_mime != NULL) + return v->locations[0].default_mime; return index; } @@ -90,16 +93,18 @@ int vhost_auto_index(struct vhost *v, const char *path) { struct location *loc; - int auto_index = 0; + + if (v == NULL || path == NULL) + return 0; for (loc = v->locations; loc->match != NULL; ++loc) { if (!fnmatch(loc->match, path, 0)) { - if (loc->auto_index) - auto_index = loc->auto_index; + if (loc->auto_index != 0) + return loc->auto_index == 1; } } - return auto_index == 1; + return v->locations[0].auto_index == 1; } int