75

I'm sure this has been asked before, but I can't find a solution that works.

A website has switched CMS services, but has the same domain, how do I set up an nginx rewrite for a single page?

E.g.

Old Page

http://sitedomain.co.uk/content/unique-page-name

New page

http://sitedomain.co.uk/new-name/unique-page-name

Please note, I don't want everything within the content page to be redirected, but literally just the url mentioned above. I have about 9 redirects to set up, non of which fit in a pattern.

Thanks!

Edit: I found this solution, which seems to be working, except for the fact that it redirects without a slash:

if ( $request_filename ~ content/unique-page-name/ ) {
   rewrite ^ http://sitedomain.co.uk/new-name/unique-page-name/? permanent;
}

But this redirects to:

http://sitedomain.co.uknew-name/unique-page-name/

SteveEdson
  • 1,479
  • 3
  • 12
  • 23

5 Answers5

119

Direct quote from Pitfalls and Common Mistakes: Taxing Rewrites:

By using the return directive we can completely avoid evaluation of regular expression.

Please use return instead of rewrite for permanent redirects. Here's my approach to this use-case...

location = /content/unique-page-name {
  return 301 /new-name/unique-page-name;
}
techraf
  • 4,163
  • 8
  • 27
  • 44
Pothi Kalimuthu
  • 5,734
  • 2
  • 24
  • 37
  • 3
    It's definitely more readable. Will this also retain any queries that were on the original URL? – SteveEdson Oct 25 '13 at 09:56
  • 1
    Am I right in thinking that using `if` statements in nginx is bad? Would this still be better practice than using the rewrite method? – SteveEdson Oct 25 '13 at 10:10
  • 1
    Using `if` along with return directive is perfectly fine. See http://wiki.nginx.org/IfIsEvil . Yes, IMO, it's better than using rewrite. – Pothi Kalimuthu Oct 25 '13 at 10:22
  • Why `return ...` instead of `rewrite ... ... permanent;` for the permanent redirects? Is there a reason why that that should be preferred? In that current answer there's no longer a `if` statement, was that why? – luckydonald Aug 05 '20 at 11:30
  • Please see the quoted text in the answer. – Pothi Kalimuthu Aug 06 '20 at 01:23
  • This would be valuable if nginx would internally change the path, not informing web browser about 301. – pbies Dec 30 '21 at 14:58
27

Ideally you shouldn't use if statements if you can avoid it. Something like this could work (untested).

location ~ /content/(.*)$ {
    rewrite ^ /new-name/$1?$args permanent;
} 
Gevious
  • 445
  • 4
  • 9
  • 1
    Wouldn't that catch everything within the content directory? I only want to redirect the individual item. For example, I have another item in the content directory, but I need it redirecting to .../another-new-name/unique-page-name2 – SteveEdson Oct 25 '13 at 09:20
  • 1
    I've solved it. Turns out it redirecting correctly, but the script is was hitting was mangling the URL after. – SteveEdson Oct 25 '13 at 09:31
  • 1
    Ah, I misunderstood the question. I thought you wanted only the content part to change. The principle remains the same. I'm glad its working for you. – Gevious Oct 25 '13 at 09:37
  • 1
    No problem, thanks for the help though, I'll definitely need to use that in the future. – SteveEdson Oct 25 '13 at 09:54
  • This answer worked the best for me, thanks! – Arian Faurtosh Oct 05 '21 at 01:01
17

I used the following solution:

rewrite ^(/content/unique-page-name)(.*)$   http://sitedomain.co.uk/new-name/unique-page-name/$2 permanent;

Works a treat.

SteveEdson
  • 1,479
  • 3
  • 12
  • 23
13

For me it worked without the equals sign like this:

location /old-url {
  return 301 /new-url;
}
primetimejas
  • 231
  • 2
  • 5
  • 2
    You don't need the location block at all. Just use `rewrite`. See @SteveEdison's answer. – PKHunter Feb 26 '17 at 00:46
  • 4
    @PKHunter According to NGINX best practices actually return 301 is the best approach to follow. https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#taxing-rewrites – Cristian E. Oct 21 '20 at 09:39
0

it works for me.

server {
  listen 80;

  location = /content/unique-page-name {
    return 301 http://sitedomain.co.uk/new-name/unique-page-name;
  }
}