Different rewrite rule redirect same url - nginx

rewrite ^/old-url /new-url permanent;
rewrite ^/old-url/old-url-sub /new-url/new-url-sub permanent;
2 urls are (/old-url and old-url/old-url-sub) redirected to same url (/new-url)
What is the problem ?

The problem is that the regular expression ^/old-url matches /old-url and /old-url/old-url-sub and /old-url/anything-else.
So the first rewrite statement is invoked for both URIs.
If you want a regular expression to match the entire string only, you need to use an anchor at the front and the back of the pattern. As you know, the ^ anchors the front of the pattern, whereas $ anchors the back of the pattern.
Try:
rewrite ^/old-url$ /new-url permanent;
If you were trying to redirect /old-url/xxx to /new-url/xxx where xxx is anything, you would use a single rewrite statement with a capture:
rewrite ^/old-url(/.*)?$ /new-url$1 permanent;
See this useful resource on regular expressions.

Related

Rewrite URLs with different domains and similar paths

I need to redirect all URLs formatted as http://www.example.org/dir/subdir/ to http://subdomain.example.org/subdir/. For example, http://www.example.org/dir/subdir/page would redirect to http://subdomain.example.org/subdir/page.
I tried rewrite ^(/dir/subdir.*) http://subdomain.example.org$1 permanent;, but this keeps the /dir/ part, which I want to omit.
Your rewrite rule is capturing the /dir/ part too.
Try this:
location /dir/subdir {
rewrite ^/dir(.*)$ http://subdomain.example.org$1 permanent;
}

Nginx Remove Trailing Question Mark

I'm trying to make a rewrite rule in Nginx to remove trialing question mark (?) from urls but i can't get it right. I've done that for trailing slashes like this:
#redirect all trailing slash URL's to the respective non trailing slash
rewrite ^/(.*)/$ /$1 permanent;
so I figured the same would work just replacing the slash with the question mark:
rewrite ^/(.*)?$ /$1 permanent;
but that didn't work, but it occurred to me that the question mark has some significance in the regex so i tried escaping it:
rewrite ^/(.*)\?$ /$1 permanent;
but that didn't work either, I tried also removing the first slash:
rewrite ^(.*)\?$ $1 permanent;
but that was also a bust, and yes i did restart the server in between tests.
Here's what I am trying to do:
www.mysite.com? should redirect to wwww.mysite.com
www.mysite.com/some/path? should redirect to wwww.mysite.com/some/path
www.mysite.com?some=vars should remain unchanged.
www.mysite.com/some/path?some=vars should remain unchanged.
so basically only removing the question mark if there is no query string.
How can i accomplish that?
I've checked other answers but they seem to want to remove the query string entirely, I only want to remove in the case that there is only a question mark and no parameters.
The ? marks the start of the query string and is not part of the normalized URI used by the rewrite or location directives. So you cannot remove it using a rewrite statement.
You will need to look at the original request which is in the $request_uri variable.
For example:
if ($request_uri ~ ^(.*)\?$) { return 301 $1; }
See this caution on the use of if.

Nginx remove trailing slash but not if query string is present

I'm trying to create a rewrite rule in Nginx to remove trailing slashes.
My rule so far is:
rewrite ^/(.*)/$ /$1;
I want to remove trailing slashes for all URL:s except those that has a query string directly after a trailing slash, how do you do that? I mean URLs that look like https://www.domain.tld/page/?query=xxx
When using rewrite, the query string is appended automatically
From http://wiki.nginx.org/HttpRewriteModule:
If in the line of replacement arguments are indicated, then the rest of the request arguments are appended to them. To avoid having them appended, place a question mark as the last character:
Just an FYI if you are using rewrite for a redirect it is not recommended but no one is going to stop you.
This rule removes trailing slash from url on both cases and worked fine for me; you can customize the the if logic by the way
location ~ (.*)/$ {
if ($query_string) {
return 301 $scheme://$host$1?$query_string;
}
return 301 $scheme://$host$1;
}

Nginx ignore part of the URL

I want nginx to ignore the first 4 characters of a URL. For example, I want /1234/test.html to be served by the file /test.html.
How can I do that with nginx?
This can be achieved with a rewrite, probably inside the server block.
The regular expression needs to be pretty specific to avoid a rewrite loop, so careful consideration of all URIs is necessary.
If the four character prefix is always digits, this may work for you:
rewrite "^/\d{4}/(.*)$" /$1 last;
Notice the "s around the regex because of the presence of {}s.

Nginx rewrite with conditional destination

I have a site with two RESTful URL schemes:
foo.com/model/id and
foo.com/model/id/action
The actual pages served by these URLs are in the form of
$model.php?id=$id and
$model_$action.php?id=$id respectively.
I have a single regular expression that will match both cases ^(\w+)s/([A-z0-9]+)(?:/(\w+))?/?$ and I'd like to use a single Nginx rule to rewrite for both types of URLs, but I'm not sure how to do this. In pseudocode I imagine the rule would look something like this
rewrite ^(\w+)s/([A-z0-9]+)(?:/(\w+))?/?$ /(($3) ? $1_$3.php?$id=$2 : $1.php?$id=2)
This isn't valid syntax (so far as I know), but can something like this be done in Nginx?
Rewrite the possible urls in turn starting with the longest to the shortest to that overlapping matching strings, "/model/id" in this case, would be matched in the longer url string first.
location / {
# For "/model/id/action" to "$model_$action.php?id=$id"
rewrite ^/(.+)/(.+)/(.+)(/?)$ $1_$3.php?id=$2 last;
# For "/model/id" to "$model.php?id=$id"
rewrite ^/(.+)/(.+)(/?)$ $1.php?id=$2 last;
}
location ~ .+\.php$ {
# Handle PHP
}
The "(/?)" is just in case the urls sometimes come with an ending slash. If they never do, it can be removed. In this case, it will probably be best to specifically always add a closing slash and have "(/?)" as "/".

Resources