2

I have a set of URLs I'm doing 301 redirects for (using Nginx, which I think uses PCRE for its Regex engine). This is a simplified version of what's required:

  • /old/
    • redirects to /new/
  • /old/1234/
    • redirects to /new/1234/
  • /old/1234/foo/
    • redirects to /new/1234/foo/
  • /old/1234/bar/
    • redirects to /new/1234/bar/
  • /old/1234/expired/
    • redirects to /new/1234/

i.e. an over-simplification of this could be to say that /old/(.*) redirects to /new/$1, except for when the last part of the url is /[0-9]+/expired/, in which case it just goes up a level. (except I really need to keep it more specific with the foo, bar expired and 1234 parts matching the URL).

I want to cover all this in one regex if possible, rather than have multiple rules for each variation.

So my regex in the Nginx.conf so far is something like:

location ~* ^/old/(([0-9]+/)expired/)?|([0-9]+/(foo|bar/)?)?$ {
    return 301 /new/$1;
}

Obviously that's not right. In summary:

  • I want to get just the /[0-9]+/ part if the url ends with /expired/.
  • And the whole /[0-9]+/foo/ or /[0-9]+/bar/ part if it ends in foo or bar.
  • And just the /[0-9]+/ part if that's what it ends with.
  • And if it just ends in /old/ then simply redirect to /new/

1 Answer 1

7

As long as the slashes are okay, the regex below should work with PCRE.

 ^/old/([0-9]+/.*?)?(?:expired/)?$
  • ^/old/ -> match everything from the start to /old
  • ([0-9]+/.*?)? -> Optionally match digits/and any text after LAZILY. Obviouslly, matches more than just foo and bar.
  • (?:expired/)?$ -> Optionally match expired, with the lazy in the previous step the engine will keep checking char by char, and then if it is expired and the end of string is next, then expired will be removed from the capture group.

Results using /new/$1:

/new/
/new/1234/
/new/1234/foo/
/new/1234/bar/
/new/1234/
Sign up to request clarification or add additional context in comments.

2 Comments

That looks like it works, thanks! I'm testing it just now, and I might try changing the .*? to (foo|bar)? to see if I can make it more specific.
Yes, that worked, I had to do it like ` ^/old/([0-9]+/(foo/|bar/)?)?(?:expired/)?$`

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.