commit 49b73ba1ab4be9993532bdecaf14e74f45eca676 from: Omar Polo date: Wed Feb 10 16:37:08 2021 UTC fix "first location" bug reported by devel at datenbrei dot de. The first location would overwrite the default value for a server, triggering the "`foo' rule specified more than once" error. This also needed a small tweak on how we match locations to avoid breaking other tests. commit - 2898780aeac7ff0a456b6f380af2bc3a25a49d3b commit + 49b73ba1ab4be9993532bdecaf14e74f45eca676 blob - def74b07e441412b2fbe29a8ac4d5351394a87c9 blob + 968670d120f4be2cfeba4e71ef9f90a87843ac3e --- parse.y +++ parse.y @@ -44,6 +44,7 @@ int check_block_code(int); char *check_block_fmt(char*); int check_strip_no(int); int check_prefork_num(int); +void advance_loc(void); %} @@ -140,11 +141,11 @@ locations : /* empty */ | locations location ; -location : TLOCATION TSTRING '{' locopts '}' { - loc->match = $2; - if (++iloc == LOCLEN) - errx(1, "too much location rules defined"); - loc++; +location : TLOCATION { advance_loc(); } TSTRING '{' locopts '}' { + /* drop the starting '/' if any */ + if (*$3 == '/') + memmove($3, $3+1, strlen($3)); + loc->match = $3; } | error '}' ; @@ -301,3 +302,11 @@ check_prefork_num(int n) yyerror("invalid prefork number %d", n); return n; } + +void +advance_loc(void) +{ + if (++iloc == LOCLEN) + errx(1, "too much location rules defined"); + loc++; +} blob - a05184a5216b77d8bec05239db625a3121ec1c97 blob + 6b1708c229d2bd4835675498d0bed35666cc55bd --- regress/runtime +++ regress/runtime @@ -158,6 +158,11 @@ echo OK GET / with custom lang check "should be running" +# make sure we can use different lang in different location rules +config '' 'lang "it" location "/en/*" { lang "en" } location "/de/*" { lang "de" }' +checkconf +restart + # try with CGI scripts config '' 'cgi "*"' checkconf @@ -204,7 +209,7 @@ echo OK GET /dir/ with custom index check "should be running" -config '' 'location "/dir/" { default type "text/plain" index "hello" }' +config '' 'location "/dir/*" { default type "text/plain" index "hello" }' checkconf restart @@ -217,7 +222,7 @@ echo OK GET /dir/ with location and custom index check "should be running" -config '' 'location "/dir/" { auto index on }' +config '' 'location "/dir/*" { auto index on }' checkconf restart blob - 1dc0d9102a9d818b854019e1d7eb036f3a1d0d99 blob + 85207394592242a65a7b10db153d0d681b4ff8fe --- server.c +++ server.c @@ -43,6 +43,8 @@ struct server_events { int connected_clients; +static inline int matches(const char*, const char*); + static inline void reschedule_read(int, struct client*, statefn); static inline void reschedule_write(int, struct client*, statefn); @@ -72,6 +74,14 @@ static void close_conn(int, short, void*); static void do_accept(int, short, void*); static void handle_sighup(int, short, void*); +static inline int +matches(const char *pattern, const char *path) +{ + if (*path == '/') + path++; + return !fnmatch(pattern, path, 0); +} + static inline void reschedule_read(int fd, struct client *c, statefn fn) { @@ -94,7 +104,7 @@ vhost_lang(struct vhost *v, const char *path) for (loc = &v->locations[1]; loc->match != NULL; ++loc) { if (loc->lang != NULL) { - if (!fnmatch(loc->match, path, 0)) + if (matches(loc->match, path)) return loc->lang; } } @@ -113,7 +123,7 @@ vhost_default_mime(struct vhost *v, const char *path) for (loc = &v->locations[1]; loc->match != NULL; ++loc) { if (loc->default_mime != NULL) { - if (!fnmatch(loc->match, path, 0)) + if (matches(loc->match, path)) return loc->default_mime; } } @@ -134,7 +144,7 @@ vhost_index(struct vhost *v, const char *path) for (loc = &v->locations[1]; loc->match != NULL; ++loc) { if (loc->index != NULL) { - if (!fnmatch(loc->match, path, 0)) + if (matches(loc->match, path)) return loc->index; } } @@ -154,7 +164,7 @@ vhost_auto_index(struct vhost *v, const char *path) for (loc = &v->locations[1]; loc->match != NULL; ++loc) { if (loc->auto_index != 0) { - if (!fnmatch(loc->match, path, 0)) + if (matches(loc->match, path)) return loc->auto_index == 1; } } @@ -172,7 +182,7 @@ vhost_block_return(struct vhost *v, const char *path, for (loc = &v->locations[1]; loc->match != NULL; ++loc) { if (loc->block_code != 0) { - if (!fnmatch(loc->match, path, 0)) { + if (matches(loc->match, path)) { *code = loc->block_code; *fmt = loc->block_fmt; return 1; @@ -195,7 +205,7 @@ vhost_strip(struct vhost *v, const char *path) for (loc = &v->locations[1]; loc->match != NULL; ++loc) { if (loc->strip != 0) { - if (!fnmatch(loc->match, path, 0)) + if (matches(loc->match, path)) return loc->strip; } } @@ -213,7 +223,7 @@ vhost_require_ca(struct vhost *v, const char *path) for (loc = &v->locations[1]; loc->match != NULL; ++loc) { if (loc->reqca != NULL) { - if (!fnmatch(loc->match, path, 0)) + if (matches(loc->match, path)) return loc->reqca; } }