Conversation
Replying to
Their statements about the if directive are problematic because they should be telling people what's safe and what isn't separately from documenting best practices for performance / style. It's fine to use it if it only contains return/rewrite directive. Other stuff is broken.
2
Replying to
Their best course of action would probably be to outright refuse to load a configuration that uses the unsafe directives in that context, honestly. But who knows if they'd actually do that. :/
1
Replying to
There are a few examples of completely correct and sensible usage of if directives in github.com/GrapheneOS/gra and our other nginx configurations.
#1 is safely removing double slashes in a single redirect which is important for SEO to avoid having multiple locations for content.
1
Has to be if directive since otherwise we'd have to stop using exact matches and high priority prefix matches.
#2 is serving SVG favicon based on accept header for /favicon.ico which we use for dark theme support. Unfortunately temporarily broken due to bugs.chromium.org/p/chromium/iss.
1
#3 is to efficiently redirect /path/ to /path if /path.html exists. We do that to deal with many cases of backlinks adding an incorrect trailing slash. It also handles all cases where we turned a leaf page into a directory without needing to hard-wire redirects for each forever.
1
We use /foo/baz/ for a directory and /foo/baz/bar for a page with redirects from /foo/baz/index.html, /foo/baz/index, /foo/baz/bar.html, /foo/baz/bar/, etc.
Current approach is very efficient and uses a mix of try_files and if to get exactly what we want very efficiently.
1
They make try_files seem far more awesome than it really is in their documentation. Even `try_files $uri.html =404` blocks the worker for a stat system call, and each entry is another stat system call. It usually doesn't block in practice since all directory nodes get cached.
1
If you aren't using try_files, nginx opens file directly and does a 404 if it fails. try_files adds overhead even for trivial case of simply changing name.
There are out-of-tree patches for async open for people with huge static file trees / caches but try_files still blocks.
1
Can see we use `rewrite ^(.*)/$ $1` as a workaround for `return 301 $uri` not working properly.
We have a location block using a ([^\s]*) capture passed to return which is safe but nginx isn't correctly following HTTP rules for it which we could fix redoing pattern with rewrite.
1
Pretty frustrating that you need to duplicate the same pattern you used if a location block or if directive using $uri rather $request_uri with rewrite since nginx isn't going to escape stuff for you, and using $request_uri means you're missing stuff that was unnecessary escaped.

