Misunderstood regex location

Hi,

I understood that prefix location was read, then regex location and it
stops
on a ^~ match

Why with this config

  location / {
      location ~ .+\.(js|css|ico|png|gif|jpg|jpeg|pdf|zip|html|htm)$ 

{
expires 25h;
}
}

  location ^~ /banniere_rotative/.+\.(js|css)$ {
          expires 30d;
  }

https://ssl.sesamath.net/banniere_rotative/_writable/slides_20140503c.min.css
match the first one prefix location and not the second regex one ?

After deeper tests, I saw that

    location /banniere_rotative/ {
        location ~ \.(js|css)$ {
                expires 30d;
        }
    }

match but

location ^~ “/banniere_rotative/.*.css$” {

doesn’t (inside prefix location or not)

What’s the obvious mistake I made in my regex ?

Thanks

Posted at Nginx Forum:

On Mon, May 05, 2014 at 06:38:45PM -0400, dcaillibaud wrote:

Hi there,

location ^~ “/banniere_rotative/.*.css$” {

doesn’t (inside prefix location or not)

What’s the obvious mistake I made in my regex ?

^~ is a prefix match, not a regex match.

http://nginx.org/r/location

f

Francis D. [email protected]

On May 6, 2014, at 2:38 , dcaillibaud wrote:

     }

doesn’t (inside prefix location or not)

What’s the obvious mistake I made in my regex ?

As Francis has already mentioned regex location is

location ~ ^/banniere…

But this will not work as you expect.
First nginx will match “location /”, then it will search regex
location inside this location and finally “location ~ .+.(js|”
will be used. Your solution:

location /banniere_rotative/ {

is right.


Igor S.

I understand my mistake, thanks to both of you.

May I suggest to insist on this in
Module ngx_http_core_module, with a
remark on the fact that ^~ is not usable with a regex, for example with

syntax:
location [ = | ^~ ] uri { … }
location ~ | ~* regexUri { … }
location @name { … }

and adding there Igor advice (repeated many times in this forum like in
Re: Proxy pass location inheritance or
Re: Nested Locations Better???), that it’s a
better practice to have a prefix location list at first level then put
regex
location within

Reviewing all my server definitions, I’m starting to imagine what a
nightmare could be, with on the first level a mix of standard prefix
location, ^~ and ~ ^/ :wink:

I was also wondering wich has precedence for /images/foo.jpeg in these
case,

  1. (I guess D, because ^/ before prefix shortcut regex)

location ^~ /images/ {
location ~* .(gif|jpg|jpeg)$ {
[ configuration D ]
}
}

location ~* .(gif|jpg|jpeg)$ {
[ configuration E ]
}

  1. (I guess E but I’m not so sure), this can also be a pitfall example
    (how
    complicating things can lead to unexpected behaviour)

location /images/ {
location ~* .(gif|jpg|jpeg)$ {
[ configuration D ]
}
}

location ~* .(gif|jpg|jpeg)$ {
[ configuration E ]
}

2bis) this makes 2) understandable (more predictable)

location /images/ {
location ~* .(gif|jpg|jpeg)$ {
[ configuration D ]
}
location ~* .svg$ {
[ configuration D2 ]
}
}

location / {
location ~* .(gif|jpg|jpeg|svg|pdf)$ {
// static stuff not in /images/
[ configuration E ]
}
}

PS: is there a way to preserve space in this forum to make code easier
to
read ? (I tried

,  and [code])

Posted at Nginx Forum:

location ~* .(gif|jpg|jpeg)$ {
[ configuration E ]
}

The request processing stops on the first matching regex.

Which is ?

I guess E, but I’m not sure since the doc doesn’t say if the inner regex
is
read before or after the next 1st level one. I understand that all first
level are evaluated to see if one branch need to be explored deeper, but
it’s not so obvious.

Anyway, this example is more a school case, it should be avoid in real
life,
so answer is not so important. If I need to answer such a question then
I’m
probably in the wrong way.

Posted at Nginx Forum:

On Tue, May 6, 2014 at 5:03 PM, dcaillibaud [email protected]
wrote:

and adding there Igor advice (repeated many times in this forum like in
Re: Proxy pass location inheritance or
Re: Nested Locations Better???), that it’s a
better practice to have a prefix location list at first level then put
regex
location within

​The $docs must stay as concise as possible, so I do not think Igorf
advice
should be there, even irf it is very interesting information, should be
there.
A ‘best practice/performance enhancement’ page could host it though.

That wriktten, I think that yes, the docs could be clearer, by
inserting:
"If the longest matching prefix location has the “^~” modifier then
regular
expressions are not checked. "
inside the third para​graph, which takes the process step-by-step but is
incomplete (one could understand every request processes regexes).
This sentence, isolated at the end of the section, produces a leap
backward
in the reasoning flow and loses the reader in his attempt to understand
how
things work. Definitely not user-friendly.

location ^~ /images/ {
location ~* .(gif|jpg|jpeg)$ {
[ configuration D ]
}
}

location ~* .(gif|jpg|jpeg)$ {
[ configuration E ]
}

​​Right​. That is however exactly the example provided by the docs.
"If the longest matching prefix location has the “^~” modifier then
regular
expressions are not checked."​
The regex is not even checked against the input request string.

[ configuration E ]

}

“Among [prefix locations], the location with the longest matching prefix
is
selected and remembered. Then regular expressions are checked, in the
order
of their appearance in the configuration file.”
​The prefix string matches, it is remembered, but then the regex is
checked
and also matches.
“The search of regular expressions terminates on the first match, and
the
corresponding configuration is used.”
The request processing stops on the first matching regex.

location / {
location ~* .(gif|jpg|jpeg|svg|pdf)$ {
// static stuff not in /images/
[ configuration E ]
}
}

​Right IMHO.

B. R.

this sentence is not so clear…

I understand
that all first level are evaluated to see if one branch need to be
explored deeper, but it’s not so obvious.

…I mean :

I understand that all first level selectors are compared to see which
block
need to be evaluated deeper, but it’s not so obvious.

Posted at Nginx Forum:

On Tue, May 6, 2014 at 8:39 PM, dcaillibaud [email protected]
wrote:

location ~* .(gif|jpg|jpeg)$ {
[ configuration E ]
}

The request processing stops on the first matching regex.

Which is ?

​Every request is processed through one location block at the same
level​.
Said otherwise, every time there is a choice to be made between several
location blocks, only one is picked up and entered. That process is
recursive.

In the provided example, there is only one regex at the root of the
tree.
Since the docs I quoted in my last message say that regexes have higher
precedence, then E will be taken over D if both match. The regex inside
the
prefix location ‘/images/’ has no impact/use in the current case since
it
is on the 2nd level of the tree, not its root, which was being
considered.
One step at a time :o)

Since regexes have higher precedence, and since it is prefered to use
prefix locations (because they are more ‘natural’ and efficient,
speaking
about performance), it is then advised either:

  • to avoid mixing prefix and regex locations on the same level, thus
    encapsulating regex locations inside prefix ones first.
  • to use the ^~ operator to force prefix locations being taken over the
    regex ones

B. R.