Home > other >  Nginx redirect https to http based on browser language
Nginx redirect https to http based on browser language

Time:11-12

Since my server is far away, I'd like to redirect https to http when browser language is Chinese (zh). Following code work well in Apache:

RewriteEngine On
RewriteCond %{HTTPS} on
RewriteCond %{HTTP:Accept-Language} ^zh [NC]
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

But I cannot figure out its Nginx equivalent on my new VPS server. Current nginx.conf is as follows:

server
{
    listen 80;
    listen 443 ssl http2;
        listen 88;
    server_name mysite.com www.mysite.com;
    index index.php index.html index.htm default.php default.htm default.html;
    root /www/wwwroot/mysite.com;

    #SSL-START SSL related configuration, do NOT delete or modify the next line of commented-out 404 rules
    #error_page 404/404.html;
    ssl_certificate    /www/server/panel/vhost/cert/mysite.com/fullchain.pem;
    ssl_certificate_key    /www/server/panel/vhost/cert/mysite.com/privkey.pem;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers EECDH CHACHA20:EECDH CHACHA20-draft:EECDH AES128:RSA AES128:EECDH AES256:RSA AES256:EECDH 3DES:RSA 3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    add_header Strict-Transport-Security "max-age=0";
    error_page 497  https://$host$request_uri;
    #SSL-END

    ......
}

CodePudding user response:

It would be simpler if you split the config into two server blocks. One with listen 80; and one with listen 443 ssl;. That would satisfy the RewriteCond %{HTTPS} on condition.

The remaining condition can be implemented with an if block.

For example:

index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/mysite.com;

server
{
    listen 80;
    listen 88;
    server_name example.com www.example.com;

    ......
}
server
{
    listen 443 ssl http2;
    server_name example.com www.example.com;

    #SSL-START
    ... 
    #SSL-END

    if ($http_accept_language ~* ^zh) {
        return 301 http://$host$request_uri;
    }

    ......
}

To avoid duplicated code, some directives which are common to all server blocks, can be moved into the outer block. Other common code can be placed into a separate file and included into both server blocks using an include statement.

CodePudding user response:

It works great. Thank you, Richard.
At the same time, following instruction on https://gist.github.com/jrom/1760790 I tried to add following code below #SSL-END without splitting server:

if ($scheme = https) { 
    set $test A; 
}
if ($http_accept_language ~* ^zh) { 
    set $test "${test}B"; 
}
if ($test = AB) {
    return 301 http://$server_name$request_uri;
    break;
}

It also works and seems simpler, but I'm not sure if there exist any negative impact?

  • Related