13

I am trying to match all paths that begin with /newsletter/ except one (/newsletter/one) with a regex. What I have so far:

   location ~ ^/newsletter/(.*)$ {
// configuration here
}

This matches all the paths that begin with /newsletter/.

How do I make an exception for the path /newsletter/one ?

dasj19
  • 393
  • 1
  • 2
  • 11
  • If you're googling this for Let's Encrypt, [here's how to set it up](https://github.com/letsencrypt/acme-spec/issues/221#issuecomment-168683597) – mehov Oct 15 '19 at 08:43

4 Answers4

16

I ended up using the following solution:

location ~ ^/newsletter/(.*)$ {
    location ~ /newsletter/one(.*) {
           // logic here
    }
    // logic here
}

This matches all the paths under /newsletter/* and then I match all the paths that begin with /newsletter/one and apply the configuration for the newsletter/one in the inner configuration block while I keep the rest of the configuration in the outer configuration block.

dasj19
  • 393
  • 1
  • 2
  • 11
12

This works but has one flaw. It will also not match on "one" followed by any characters.

location ~ ^/newsletter/(?!one).*$ {
    //configuration here
}

Although, this may be better:

location = /newsletter/one {
    // do something (not serve an index.html page)
}

location ~ ^/newsletter/.*$ {
    // do something else
}

This works because when Nginx finds an exact match with an = it uses that location to serve the request. One problem is that this will not match if you are using an index page because the request is rewritten internally and so will match the second location "better" and use that. See the following: https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms#matching-location-blocks

There is a section which explains how Nginx chooses which location to use.

Tim
  • 443
  • 2
  • 10
2

To clarify on varlogtim's solution the following would work, allowing you to match on /newsletter/one-time but still skip /newsletter/one

location ~ ^/newsletter/(?!one$).*$

Also, if you want ignore case in your match, use the ~* modifier in place of ~

cbedrosian
  • 121
  • 1
0

Here's the one:

^/newsletter(/&/[^o][^n][^e])$
Jonas Bjork
  • 376
  • 1
  • 4