How can I make multi language config in Nginx? - redirect

I have following Nginx config default.conf:
map $http_accept_language $browser_lang {
default en;
~ru ru;
}
map $cookie_lang $lang {
default $browser_lang;
~en en;
~ru ru;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/log/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
How can I do following:
1) Pass all /* requests to /en/* or /ru/* depending of language?
2) Pass all /en/* to /usr/share/nginx/html/<request>?lang=en and /ru/* to /usr/share/nginx/html/<request>?lang=ru?
3) If language is not en and ru path to all /* requests to /en/*?

You need to apply two separate location blocks for root url and for your language sections like so:
location = / {
rewrite ^ $scheme://$host/$lang$uri$is_args$args break;
}
location ~ '^/(?<lang_code>[\w-]{2})' {
rewrite ^/(?<lang_code>[\w-]{2})/(.*)$ /$1?lang=$lang_code last;
...
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
...
}
First location block answers to you questions 1) and 3) where the root url will be rewritten with your $lang variable in it that comes from map section and the last one defines that you will be using en language as default.
Second location block is for your questions 2) where you accept your language param as two-char path and then rewrite your url to suit your needs.
This code may not be 100% working, but it should give you an idea.
UPDATE
Well, actually you can do this in one single pass:
location / {
if ($uri !~ '^/([a-z]{2})(/.*)?$') {
rewrite ^ $scheme://$host/$lang$uri permanent;
rewrite ^/([a-z]{2})(/.*)?$ /$2?lang=$1;
}
...
}

Related

Conditionally make Nginx redirects to index.html

how to redirect to index.html for all the url except when the url has one particular QueryString?
For example:
Redirect all other url with Query strings to index.html except when it has ngsw-cache-bust
example.com/ngsw.json?ngsw-cache-bust=0.24039143891136616
i tried the following code
server {
index index.html;
root /dist;
listen 80;
location / {
try_files $uri$args $uri$args/ /index.html;
}
}
what am i missing?
Perhaps you could try something like this
server {
index index.html;
root /dist;
listen 80;
location / {
if($arg_ngsw-cache-bust == "") {
rewrite ^(.*)$ /index.html last;
}
}
}

Nginx Exclude a query string url from being redirected

I am currently redirecting my root domain to a subfolder. However I want to exclude a query string url which is used for an ajax call (www.example.com/?act=12). I am however unsure of how to do this in nginx.
This is my current nginx config file
server {
listen 80;
server_name example.com;
return 301 http://www.example.com$request_uri;
}
server {
listen 80;
server_name www.example.com;
root /var/www/example.com/public;
index index.php index.html;
location = / {
return 301 http://www.example.com/it/;
}
location / {
proxy_pass http://localhost:8080;
include /etc/nginx/proxy_params;
}
location ~* \.(js|css|jpg|jpeg|gif|png|svg|ico|pdf|html|htm)$ {
expires 30d;
}
location ~ /\.ht {
deny all;
}
}
Any help will be appreciated.
That can be achieved by using the evil if block.
The query string arguments are presented as variables with a $arg_ prefix. If you just need to test that act is set, try this:
location = / {
if ($arg_act) {
rewrite ^ /my/ajax/call last;
}
return 301 http://www.example.com/it/;
}
If you need to test for a specific value of $arg_act use the = operator.
See this document for details.

Nginx redirect for some url (return 404)

How to create a redirect for url returned to 404 (in cms). Use nginx+php-fmp.
Example. There is a category /auto/ with 4 pages:
/auto.html,
/auto/page-2.html,
/auto/page-3.html,
/auto/page-4.html
How for the others urls (/auto/page-5.html ... /auto/page-200.html) return 301 to /auto.html?
This code, return 301 for all url (/auto/page-2.html, /auto/page-5.html ...). What is the error?
location ~* /(auto)/page-\d+\.html {
error_page 404 = #page;
}
location #page {
rewrite /(.*?)/page-\d+\.html http://site.ru/$1.html permanent;
}
error_page 404 =404 /404.html;
location ~* \.php$ {
include fastcgi_def;
}
location / {try_files $uri /index.php?$args;}
solution
error_page 404 =404 /404.html;
location ~* \.php$ {
include fastcgi_def;
include add/cachephp;
if ($request_uri ~ /(.+)/page-\d+\.html) {
error_page 404 = #page;
}
fastcgi_intercept_errors on;
}
location / {try_files $uri /index.php?$args;}
location #page {
if ($request_uri ~ /(.+)/page-\d+\.html) {return 301 /$1.html;}
return 410;
}

domain to www.domain redirection

I have an nginx server behind varnish and I am trying to do a domain to www.domain redirection .
I tried using these rules on nginx
rewrite ^(.*) http://www.domain.com$1 permanent;
return 301 ^ $scheme://www.domain.com$request_uri;
return 301 http://www.domain.com$request_uri;
But I get an error in chrome as website running into a redirection loop.
As the about solution did not work I tried an alternative writing rules in varnish
sub vcl_recv {
// ...
if ( req.http.host == "domain.com" ) {
error 750 "http://www." + req.http.host + req.url;
}
// ...
}
sub vcl_error {
// ...
if (obj.status == 750) {
set obj.http.Location = obj.response;
# Set HTTP 301 for permanent redirect
set obj.status = 301;
return(deliver);
}
// ...
}
I am using varnish 4 and I get an error that varnish can't compile the code.
Message from VCC-compiler:
Expected an action, 'if', '{' or '}'
('input' Line 29 Pos 3)
error 750 regsub(req.http.host, "^www\.(.*)", "http://\1");
--#####------------------------------------------------------------------------------------------------------------------------
Could some one please help me in fixing this?
My server block is a follows:
server {
listen 127.0.0.1:8080;
root /home/webadmin/html/livesite;
index index.php index.html index.htm;
server_name www.domain.com;
# rewrite ^(.*) http://www.domain.com$1 permanent;
# return 301 ^ $scheme://www.domain.com$request_uri;
# return 301 http://www.domain.com$request_uri;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
error_page 404 403 /error/eror.html;
location = /error/error.html {
root /home/webadmin/html/livesite;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /home/webadmin/html/livesite;
}
#pass the PHP scripts to FastCGI server listening on 127.0.0.1:9$
location ~ \.php$ {
#fastcgi_pass 127.0.0.1:9000;
# With php5-fpm:
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
This would be a correct way to do it while preserving the uri and the query string,
return 301 $scheme://www.domain.com$request_uri$is_args$query_string;
The problem isn't in this part, the problem is where you are redirecting to, probably redirecting to another locations that also does another redirect, I would guess you don't have another server block to handle the www server separately, so you keep redirecting to the same place over and over, wouldn't know for sure till you post the rest of the config.
EDIT:
The issue like I said is that you are redirecting the www to the www server, to avoid that you should create a new server that isn't with the www to do the redirection
server { # the redirecting server
listen 8080; # according to your config
server_name domain.com; #without www
return 301 $scheme://www.domain.com$request_uri$is_args$query_string;
}
server { # the actual serving server
listen 8080;
server_name www.domain.com;
# the rest of your actual settings
}
Use varnish for this instead, and skip the apache rewrites.
This example is to always redirect to https, but the semantics is the same..
In sub vcl_recv:
if ( req.http.host ~ "^(?i)domain.com" )
{
set req.http.X-Redir-Url = "https://domain.com" + req.url;
error 750 req.http.x-Redir-Url;
}
and then in sub vcl_error:
if (obj.status == 750) {
set obj.http.Location = obj.response;
set obj.status = 302;
return (deliver);
}

How do I force redirect all 404's (or every page, whether invalid or not) to the homepage?

Currently every invalid page is 500 (Internal Server Error) because I probably messed up with my server block configuration.
I decided to shut down my website a while ago and created a simple one-page, thank-you homepage. However old links and external sites are still trying to access other parts of the site, which no longer exists.
How do I force redirect all non-homepage (any invalid URL) to the homepage?
I tried with the following block, but it didn't work:
location / {
try_files $uri $uri/ $document_uri/index.html;
}
My current configuration is (I don't even serve PHP files right now, ie homepage is simple html):
server {
server_name www.example.com example.com;
access_log /srv/www/example.com/logs/access.log;
error_log /srv/www/example.com/logs/error.log;
root /srv/www/example.com/public_html;
index index.php index.html;
location / {
try_files $uri $uri/ $document_uri/index.html;
}
# Disable favicon.ico logging
location = /favicon.ico {
log_not_found off;
access_log off;
}
# Allow robots and disable logging
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Enable permalink structures
if (!-e $request_filename) {
rewrite . /index.php last;
}
# Handle php requests
location ~ \.php$ {
try_files $uri = 404;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_send_timeout 900;
fastcgi_read_timeout 900;
fastcgi_connect_timeout 900;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# Disable static content logging and set cache time to max
location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
access_log off;
log_not_found off;
expires max;
}
# Deny access to htaccess and htpasswd files
location ~ /\.ht {
deny all;
}
# Deny access to hidden files (beginning with a period)
location ~ /\. {
access_log off; log_not_found off; deny all;
}
}
Setting the error page to the home page like this
error_page 404 /index.html;
has a small problem, the status code of the home page will be "404 not found", if you want to load the home page with a "200 ok" status code you should do it like this
error_page 404 =200 /index.html;
This will convert the "404 not found" error code to a "200 ok" code, and load the home page
The second method which #jvperrin mentioned is good too,
try_files $uri $uri/ /index.html;
but you need to keep 1 thing in mind, since it's the location / any asset that doesn't match another location and is not found will also load the index.html, for example missing images, css, js files, but in your case I can see you already have another location that's matching the assets' extensions, so you shouldn't face this problem.
To get a true redirect you could do this:
in server block define the error-page you want to redirect like this:
# define error page
error_page 404 = #myownredirect;
error_page 500 = #myownredirect;
Then you define that location:
# error page location redirect 302
location #myownredirect {
return 302 /;
}
In this case errors 404 and 500 generates HTTP 302 (temporary redirect) to / (could of course be any URL)
If you use fast-cgi for php or other these blocks must have the following added to send the errors "upstrem" to server-block:
fastcgi_intercept_errors on;
This solution for nginx hosted site:
Edit your virtual hosting file
sudo nano /etc/nginx/sites-available/vishnuku.com
Add this snippet in the server block
# define error page
error_page 404 = #notfound;
# error page location redirect 301
location #notfound {
return 301 /;
}
In your php block put the fastcgi_intercept_errors set to on
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
# intercept errors for 404 redirect
fastcgi_intercept_errors on;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Final code will look like this
server {
listen 80;
server_name vishnuku.com;
root /var/www/nginx/vishnuku.com;
index index.php index.html;
access_log /var/log/nginx/vishnuku.com.log;
error_log /var/log/nginx/vishnuku.com.error.log;
location / {
try_files $uri $uri/ /index.php?$args /;
}
# define error page
error_page 404 = #notfound;
# error page location redirect 301
location #notfound {
return 301 /;
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
location = /nginx.conf {
deny all;
}
}
Try adding the following line after your index definition:
error_page 404 /index.html;
If that doesn't work, try changing your try_files call to the following instead:
try_files $uri $uri/ /index.html;
Hopefully one of those works for you, I haven't tested either yet.
Must use
"fastcgi_intercept_errors on;"
along with the custom redirect location like
error_page 404 =200 /index.html or
as above
location #myownredirect {
return 302 /;
}
Try this:
error_page 404 $scheme://$host/index.html;
Hi first there are a lot of different ways to redirect all the 404 to the home page
this helps you in SEO
make such u use
fastcgi_intercept_errors on;
than add this following to your config
error_page 404 =301 http://yourdomain.com/;
error_page 403 /error403.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/html;
}
Came here when I was looking to implement similar where I'm using Nginx as a reverse proxy to a self-hosted MinIO bucket, and none of the above answers have this. So, if you're using proxy_pass and are intercepting errors, you can also handle this logic to redirect to the index.html page.
Handling URLs such as:
http://localhost/ - 200 OK
http://localhost/index.html - 200 OK
http://localhost/non-existant/ - 404 Not Found
server {
listen 80;
server_name localhost;
location / {
rewrite ^/$ /static/index.html break;
proxy_intercept_errors on;
proxy_pass http://something-to-proxy/static/;
}
error_page 404 /index.html;
}
Another-correct way to redirect from error page to the home page. The setup example applies to the nginx server configuration file:
...
http {
...
server{
...
#Catch 40x errors:
error_page 400 401 402 403 404 = #RedirectToHome;
#Catch 50x errors:
error_page 500 501 502 503 504 = #RedirectToHome;
#We are now redirecting to the homepage of the site
location #RedirectToHome {
return 301 http://www.example.com;
#return 301 https://www.example.com;
#return 301 /;
}
...
}
}
You should avoid setting return 301 /; if port forwarding to the server was performed somewhere, because this nginx redirection will then be performed to the port on which the server is listening for incoming connections. Therefore, it is better to set the correct hostname(site name) in this configuration.