NGINX rewrite root url with language suffix - nginx

I am trying to add a simple rule to my NGINX configuration whereby the root url www.example.com is always rewritten with a language suffix www.example.com/en/. I have tried this:
server {
listen 80;
server_name www.example.com;
location / {
rewrite ^$ www.example.com/en/ permanent;
}
...
}
But no luck. Where am I going wrong? Also, is it possible to have a condition where NGINX checks if there is an/en/ suffix and if not, adds one?
EDIT
So I was only one character away from what I wanted initially:
server {
listen 80;
server_name www.example.com;
location / {
# needed the / in between the anchor tags
rewrite ^/$ www.example.com/en/ permanent;
}
...
}

There are two normal ways to deal with redirects:
Using a rewrite rule
server {
...
rewrite ^/$ /en/ permanent;
...
}
Note that rewrite rules do not need to be absolute urls, but if they are to be absolute urls they need to include the protocol rewrite /x https://example.com/y;.
There is no need to put rewrite rules like this in a location block.
Using a location block + return 30x
Using a location block requires using an exact match for the url:
server {
...
location = / {
return 301 /en/;
}
...
}
The use of = means the rule will only match requests for the root of the domain, otherwise the rules of location block precedence mean that the location block would be the default for all requests. Return is used to issue a 301 (permanent) redirect.

Related

Nginx Rewrite Encoded URI (with percent) Not Working

I have a WordPress site that needed to 301 redirect old post to new post.
Old post:
https://www.example.com/%e0%b8%aa%e0%b8%a7%e0%b8%b1%e0%b8%aa%e0%b8%94%e0%b8%b5/
New Post:
https://www.example.com/%e0%b8%a5%e0%b8%b2%e0%b8%81%e0%b9%88%e0%b8%ad%e0%b8%99/
I added this rule in nginx.conf for this domain here
server
{
listen 111.222.333.444:80;
server_name example.com www.example.com ;
return 301 https://www.example.com$request_uri;
}
server
{
rewrite_log on;
rewrite ^/%e0%b8%aa%e0%b8%a7%e0%b8%b1%e0%b8%aa%e0%b8%94%e0%b8%b5/$ https://www.example.com/%e0%b8%a5%e0%b8%b2%e0%b8%81%e0%b9%88%e0%b8%ad%e0%b8%99/ permanent;
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
(the rest of location blocks continue)
}
Restart Nginx.
However, the old URL still return 404 and not a 301.
https://www.example.com/%e0%b8%aa%e0%b8%a7%e0%b8%b1%e0%b8%aa%e0%b8%94%e0%b8%b5/
And I don't see neither old nor new URI in error log at all. What should I do? Thanks!
The percent encoded URL is available in the $request_uri variable. But by the time Nginx is processing rewrite and location statements, the URL has been decoded and normalised.
Use a rewrite or location statement with the decoded values. For example:
rewrite ^/สวัสดี/$ /ลาก่อน/ permanent;
Or:
location = /สวัสดี/ {
return 301 /ลาก่อน/;
}

Nginx redirect rule has no affect

Trying to do a simple redirect:
rewrite https://url.example.com(.*) https://example.com/plugins/url permanent;
Anytime url.example.com is hit, I want it to redirect to that specific path.
EDIT:
Will try to explain this better, as I'm trying to redirect to a specific domain from another.
server {
server_name example.com plugin.example.com;
root /home/www/example.com/public;
}
I see the location used for redirects such as:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
But not sure how to use it in my case, which is to change plugin.example.com to example.com/plugin.
For example:
http://plugin.example.com
https://plugin.example.com
https://plugin.example.com/blah
https://plugin.example.com/blah/more
All of these should redirect to:
https://example.com/plugin
If the original URL is https://url.example.com or https://url.example.com/ then the normalized URI used by the rewrite and location directives will be /. The scheme, host name and query string have all been removed.
To perform a permanent redirect to a URL with a different host name:
Using rewrite (see this document for details):
rewrite ^/$ https://example.com/foo permanent;
Or using location and return (see this document for details):
location = / {
return 301 https://example.com/foo;
}
The second solution is more efficient, as there are no regular expressions to process.
If the original URL includes a query string: The rewrite will append it automatically unless a trailing ? is added. The return will not, but can be added by appending $is_args$args.
If the scheme and host name are unchanged, then both statements can be simplified:
rewrite ^/$ /foo permanent;
Or:
location = / {
return 301 /foo;
}
Redirect from subdomain to subfolder on main site
Do you require a redirect from a subdomain to a subfolder on the main site?
This would be best accomplished by a separate server context, with the appropriate server_name specification.
Else, you could also do this with an if statement testing against $host.
As already pointed out elsewhere, rewrite directive operates based on $uri, which does not contain the hostname.
server_name-based matching (recommended):
Hardcoded redirect with a limited number of hostnames (recommended):
server {
server_name plugin.example.com;
return 301 $scheme://example.com/plugin$request_uri;
}
server {
server_name about.example.com;
return 301 $scheme://example.com/about$request_uri;
}
Regex-based redirect from any subdomain to the main domain:
server {
server_name ~^(?:www\.)?(?<subdomain>.*)\.example\.com$;
return 301 $scheme://example.com/$subdomain$request_uri;
}
Regex-based redirect from a limited number of subdomain to the main domain:
server {
server_name ~^(?:www\.)?(?<subdomain>plugin|about)\.example\.com$;
return 301 $scheme://example.com/$subdomain$request_uri;
}
if-based:
If-statement-based redirect with hardcoded hostnames:
server {
server_name .example.com;
…
if ($host = plugin.example.com) {
return 301 $scheme://example.com/plugin$request_uri;
}
if ($host = about.example.com) {
return 301 $scheme://example.com/about$request_uri;
}
…
}
If-statement-based redirect with a regex-based matching:
server {
server_name .example.com;
…
if ($host ~ ^(?:www\.)?(?<subdomain>plugin|about)\.example\.com$) {
return 301 $scheme://example.com/$subdomain$request_uri;
}
…
}
Please refer to http://nginx.org/r/server_name for more discussion of which option may be best for you.
You can create separate servers for example.com and plugin.example.com. And create redirect inside plugin.example.com server.
server {
server_name plugin.example.com;
return 301 https://example.com/plugin;
}
server {
server_name example.com;
root /home/www/example.com/public;
}

How to fix redirects in nginx after the front-slash in the end of the URL

We are changing our web from example.se to example.com and also changing a few categories from Swedish to English so I need to point the old URLs to new ones with new names.
I am trying to redirect example.se/something to example.com/anything-else
I've managed to accomplish the redirection from example.se > example.com but whenever I try to go to example.com/something > example.com/anything-else I get a 404.
Here's the nginx conf:
server {
listen 80;
listen 443;
server_name example.se www.example.se;
rewrite ^/(.*)$ http://.example.com/$1 permanent;
rewrite ^/something/$ /anything-else/ permanent;
}
What I've managed to accomplish is the redirection from example.se > example.com but whenever I try to go to example.com/something (which I'd like to point to example.com/anything-else) I get a 404.
In second redirect you should specify domain name: rewrite ^/something/$ http://example.com/anything-else/ permanent instead rewrite ^/something/$ /anything-else/ permanent
Or you could use if:
if ($request_uri = / ) {
rewrite (.*) http://example.com/ permanent;
}
if ($request_uri ~ ^/something) {
rewrite (.*) http://example.com/anything-else permanent;
}

Rewrite directory as parameter

I'm trying to redirect requests from
example.com/abc234 to
example.com/setup.html?s=abc234
So far, I've tried the following, but it seems to always end up either 1) not transmitting the parameter or 2) ending up in an infinite loop (or 404) because it also tries to redirect the redirected request? The request has to be visibly rewritten because I want to pick up the parameter with JS, not PHP.
server {
server_name example.com;
root /var/www/html;
rewrite ^(.*)$ /setup.html?s=$1 redirect;
}
I've also tried various combinations of location / { try_files ...; } or using the absolute URL within rewrite without success.
One technique is to rewrite only URIs that do not match a physical file.
For example:
server {
server_name example.com;
root /var/www/html;
location / {
try_files $uri $uri/ #rewrite;
}
location #rewrite {
return 302 /setup.html?s=$uri;
}
}
See this document for more.
rewrite ^(.*)$ /setup.html?s=$1 redirect;
}

Nginx return under location

I am currently facing a small problem using nginx to redirect to another host. I want to for example redirect https://service.company.com/new/test.html to https://new-service.company.com/test.html .
For now I have following configuration, which redirects me to https://new-service.company.com/new/test.html .
server {
# SSL
ssl_certificate /etc/nginx/cert/chained_star_company.com.crt;
ssl_certificate_key /etc/nginx/cert/star_company.com.key;
listen 443;
server_name service.company.com;
location /new/$1 {
return 301 $scheme://service-new.company.com/$1;
}
}
I also tried following with the same result:
return 301 $scheme://service-new.company.com/$request_uri
You want to rewrite the URI and redirect. You can achieve it using location and return directives, but a rewrite directive would be the simplest approach:
rewrite ^/new(.*)$ https://new-service.company.com$1 permanent;
See this document for more.
BTW, the problem with your location block solution, was the regular expression capture, wasn't. Use:
location ~ ^/new(.*)$ {
return 301 https://new-service.company.com$1$is_args$args;
}
See this document for more.

Resources