[PATCH] Allowed nesting arbitrary prefix "location" in regex "location"

Maxim Dounin mdounin at mdounin.ru
Sun Sep 10 19:11:09 UTC 2023


Hello!

On Mon, Sep 04, 2023 at 10:11:47PM +0300, Valentin V. Bartenev wrote:

> # HG changeset patch
> # User Valentin Bartenev <vbart at wbsrv.ru>
> # Date 1693854233 -10800
> #      Mon Sep 04 22:03:53 2023 +0300
> # Node ID c706913db63c6862c13a0a540cdc37be0ccf0c81
> # Parent  daf8f5ba23d8e9955b22782d945f9c065f4b6baa
> Allowed nesting arbitrary prefix "location" in regex "location".
> 
> Previously, only prefix "location" blocks that literally matched the beginning
> of the regular expression were allowed inside.  This restriction makes no sense
> because regular expressions have different matching semantics.
> 
> diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
> --- a/src/http/ngx_http_core_module.c
> +++ b/src/http/ngx_http_core_module.c
> @@ -3202,6 +3202,7 @@ ngx_http_core_location(ngx_conf_t *cf, n
>  
>  #if (NGX_PCRE)
>          if (clcf->regex == NULL
> +            && pclcf->regex == NULL
>              && ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0)
>  #else
>          if (ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0)

Thank you for your patch.

Locations given by regular expressions are expected to be used as 
leaf locations to match a small subset of the requests.  Further, 
to make sure the configuration can be read and modified it is 
recommended to isolate regular expressions inside prefix 
locations, see here:

https://www.youtube.com/watch?v=YWRYbLKsS0I&t=630

The condition in question is indeed somewhat misleading, but the 
practical effect is that it prevents usage of prefix locations 
within regex locations, with the exception of regex locations 
misused as prefix ones, such as in:

    location ~ /foo/ {
        location /foo/bar {
            ...
        }
    }

While trying to create arbitrary prefix locations within a regex 
location might work, it will certainly complicate things a lot, 
making reading and modifying such configurations much harder.  
Consider:

    location / {
        location ~ \.php$ { ... }
    }

    location /foo/ {
        location ~ \.php$ { ... }
    }

    location ~ \.php$ {
        location /foo/ { ... }
    }

Which location is to be used for "/foo/file.php" request?  Within 
the existing logic, the answer is more or less obvious: the most 
specific configuration wins, so "location /foo/ { location ~ 
\.php$ { ... }}" will be used.

But with the "location ~ \.php$ { location /foo/ { ... }}", as 
allowed with the patch in question, things become more 
complicated.  Both "location /foo/ { location ~ \.php$ { ... }}" 
and "location ~ \.php$ { location /foo/ { ... }}" are equivalent, 
and there is no obvious answer.

Given the above, I tend to think that it would be better to 
preserve existing behaviour.

-- 
Maxim Dounin
http://mdounin.ru/


More information about the nginx-devel mailing list