3

In the code below, the index directive adds page1.htm to / requests. So I would expect an exact match for http://DOMAIN to be matched by the 2nd location block and not the first.

index page1.htm;

location = /
    {
    rewrite / /page2.htm;
    }

location = /page1.htm
    {
    rewrite /page1.htm /page3.htm;
    }

But it's the first location that matches. http://DOMAIN gives me page2.htm and http://DOMAIN/page1.htm gives me page3.htm.

What kind of exact match does the = prefix enable?

I've browsed lots of docs but it's not clear to me what is happening here. If the first location is removed then http://DOMAIN gives me page3.htm so it seems it is using the index before attempting location matches. So in the above case, why is location = / matching when after the index is applied the uri has become /page1.htm?

Are the locations tested without the index applied first and then only if there is no match, are they tested again with index applied?

poby
  • 1,572
  • 15
  • 39
  • What you think `http://DOMAIN` request, actually is `http://DOMAIN/` request. That's how HTTP protocol works, path part cannot be empty, it's always one slash (`/`) at least. – Alexey Ten Feb 10 '16 at 07:23
  • yes I know that. Still doesn't explain how the index is applied with an exact match as detailed above. – poby Feb 10 '16 at 07:27

3 Answers3

4

I'm posting the answer in case anyone else is researching this rather obscure question. Further testing reveals the following:

  1. When a uri arrives to a server block, it is parsed through the locations without any index directive being applied.

  2. If the resulting path resolves to a valid directory, and an index directive exists, the filenames in the index are sequentially appended to the path and tested to see if a valid file exists.

  3. If step 2 causes the path to change (by adding an index filename that exists), the locations are parsed again with the new path.

poby
  • 1,572
  • 15
  • 39
-1

URLs http://example.com and http://example.com/ are actually absolutely the same for HTTP. Both would be send as

GET / HTTP/1.1
Host: example.com
... other headers

meaning that path part never empty and always starts with a slash /. And in that case it's quite obvious, that your request to http://example.com ends up in page2.htm.

In steps:

  1. Nginx found exact match / and rewrote request to /page2.htm
  2. No location matched /page2.htm so nginx just served static file.

You could see that index never used here.

Alexey Ten
  • 13,794
  • 6
  • 44
  • 54
  • I think you missed the point of the question. I know already everything you just wrote but that doesn't answer the problem. The question is when does the index directive get applied? Read my question again. If the first location is removed, then page3 is sent even though the path is only '/'. So in this case the index is applied to the path before it is location parsed. The only thing that makes sense seems to be that the locations are parsed first without the index directive and if no match, parsed again with the index directive. Is that how it works? – poby Feb 10 '16 at 07:55
  • index works when nginx find out that your request end up in a directory. So if you request for `/some/dir/`, you have directory `$document_root/some/dir/` then nginx will try to append filenames from `index` and look for files. If the file found nginx will add that file name to request (would be `/some/dir/index.htm`) and make an internal redirect. – Alexey Ten Feb 10 '16 at 08:00
  • So in other words, if the path is a directory, then the locations are parsed first without the index applied and then if no match, parsed again with the index applied? – poby Feb 10 '16 at 08:06
-1

The nginx documentation is pretty clear on that:

A location can either be defined by a prefix string, or by a regular expression. Regular expressions are specified with the preceding “~*” modifier (for case-insensitive matching), or the “~” modifier (for case-sensitive matching). To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, 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 search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then the configuration of the prefix location remembered earlier is used.

...

Also, using the “=” modifier it is possible to define an exact match of URI and location. If an exact match is found, the search terminates.

Community
  • 1
  • 1
funky-future
  • 3,716
  • 1
  • 30
  • 43