How to optimize these config / rewrite rules

Jonathan Matthews contact at
Wed Apr 18 16:51:30 UTC 2012

On 18 April 2012 16:48, rob <nginx-forum at> wrote:
> As I said Jonathan,  I've been told that the above rules can be
> optimised so that hitting any url in the path I mentioned would run just
> one rex rule instead of a minimum of 3 currently.  I have been told that
> by an nginx expert but what I have not been told is how to achieve it. I
> suspect it will be by nesting location {} constructs (is thsat possible)
> or by having more selective location {} constructs.
> I want to start with as optimised a set of rewrite rules as possible.
> Does this help any?

I still don't think you've defined the optimisation you're looking
for. Just to say "optimised" isn't specific enough IMHO. You optimise
/for/ a characteristic, almost always at the expense of other

It looks to me like you're trying to optimise for as few lines as
possible in your config file, at the expense of config file *clarity*
and runtime performance.
Also, just because you can technically combine multiple regular
expressions into a single one doesn't mean that the result will be any
faster than the multiple, simpler, regex route.

I can't personally be bothered to work out the complex regex that
would be required here for rewrites as it's *really* not something I'd
do with my nginx configs.
I want to understand them later and not worry if every minor change
might have some huge unintended impact - which is where I think you'll
end up if you carry on down this route.
However there are a few points I can give you, looking at what you've got.

1) Locations can be nested. This is valid:

location /foo {
  location /foo/bar {

AFAICT, the intended use of this construct is to have non-regex outer
locations, preventing the evaluation of inner regex locations until
they're necessary e.g.

location /foo/ {
  location ~ ^/foo/(bar|baz) {
  location ~ ^/foo/image(s)?/ {

2) If you're using brackets solely for alternation (i.e. one thing OR
the other, e.g. "(bar|baz)", above) then consider using (?:bar|baz)
instead, as this stops the regex engine from capturing the match for
later use, which might save you valuable microseconds ;-)

3) Regex *locations* are, as per, evaluated in order,
stopping after the first match. This probably isn't the case with
rewrites, which are cumulative I believe.

4) Here's how I'd structure what you're doing if my aim was to make it
forum-name agnostic. YMMV, 'cos it actually depends on the format
names of the forums. You may need to tweak it.
I wouldn't personally do this unless I *really* needed to make it
name-agnostic. It sacrifices readability for brevity.

location ~ ^/category-name-73/(?<forum>[^/]+)/$  {
   rewrite ^ /forums/$forum/ permanent;
location ~ ^/category-name-73/(<?forum>[^/]+)/index(?<number>[\d]+).html {
   rewrite  /forums/$forum/page-$number permanent;
# Now /you/ redo these as locations; to do so requires a bit more
detail about the URI structures than you've posted :-)
#rewrite [^/]+/([\d]+)-.+-([\d]+).html /showthread.php?t=$1&page=$2 last;
#rewrite [^/]+/([\d]+)-.+.html /threads/redirectme.$1/ permanent;

Jonathan Matthews
Oxford, London, UK

More information about the nginx mailing list