Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
170 views
in Technique[技术] by (71.8m points)

Nginx Server: How do I remove the folder path from the URL?

I recently created two folders containing index files with the respective language of the folders, pt (Brazil) & en (English).

When the user accesses the page, I use a control structure to check the user's browser language, if the browser language is pt, then I redirect the user to https://mywebsite.com/pt/index, otherwise, I redirect the user to https://mywebsite.com/en/index.

Maybe this idea that I had to translate, is not so professional, but okay, the point is that I would like to remove the path from the URL folders of the website, that is, I want it to appear https://mywebsite.com/index regardless if I redirected the user, do you understand? That is, if I redirect the user to https://mywebsite.com/en/index, I don't want /pt to be displayed, just /index.

Is it possible to do this using Nginx?

EDIT

Tree ( /var/www)

├── mywebsite.com
│?? └── html
│??     ├── 404.html
│??     ├── css
│??     │?? ├── bootstrap.css
│??     │?? └── style.css
│??     ├── index.php
│??     ├── jquery
│??     │?? └── jquery.js
│??     ├── js
│??     │?? ├── bootstrap.js
│??     │?? └── vue.js
│??     ├── logout.php
│??     ├── pt
│??     │?? ├── index.php
│??     │?? ├── logout.php
│??     │?? ├── signin.php
│??     │?? └── signup.php
│??     ├── signin.php
│??     ├── signup.php
└── html
    ├── index.html
    └── index.nginx-debian.html

index.php

<?php

$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);

if($lang == 'pt') {
    header('Location: pt/');
    return;
}

?>

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>English</title>
    </head>
    <body>
        <h1>Welcome! You're browsing the website with the English language.</h1>
    </body>
    </html>

pt/index.php

<?php


$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);

if(!$lang == 'pt') {
    header('Location: https://mywebsite.com');
    return;
}

?>


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Português</title>
</head>
<body>
    <h1>Bem vindo! Você está navegando no website com o idioma Português.</h1>
</body>
</html>

Nginx ( /etc/nginx/sites-available/mywebsite )

server {

        root /var/www/mywebsite.com/html;
        try_files $uri $uri/ @extensionless-php;
        index index.php;

        server_name mywebsite.com www.mywebsite.com;

        error_page 403      http://mywebsite.com/forbidden.html;
        error_page 404 =301 http://mywebsite.com/404.html;

        location ~ .php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.4-fpm.sock;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                internal;
        }

        location @extensionless-php {
                rewrite ^(.*)$ $1.php last;
        }


    listen 443;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    access_log /var/log/wss-access-ssl.log;
    error_log /var/log/wss-error-ssl.log;


}

server {
    if ($host = www.mywebsite.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = mywebsite.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

        listen 80;
        listen [::]:80;

        server_name mywebsite.com www.mywebsite.com;
   return 404;  # managed by Certbot

The control structure I said is now visible in the code. Really, this is working, but I don't know if what I did is appropriate, if it is professional or not, if there are risks ...

So judging by the information now available, when the user enters the page, the script will check the language of the user's browser and if it is pt, it will redirect to the page in Portuguese, and how that page in Portuguese is inside a folder with the name pt, soon the name of this folder will appear in the URL

I would like to know if there is a way to hide the name of the folder?

Note:

Richard Smith said: The user needs the ability to choose/change the language. Before I did this to translate into the user's language, I used a Google Translate button that could translate the page into the language the user chose, however, I didn't think it was that cool, it was making the website slow to load, and most users in Brazil haven't even used that. So I thought about how to automatically translate the page into the user's browser language, and I did what is in the code above but I really don't know if it's the best one to do

Ivan Shatsky said: choose one of two different root folders at nginx config. I didn't quite understand what that means. Should I create another configuration file in /etc/nginx/sites-available?

question from:https://stackoverflow.com/questions/65908345/nginx-server-how-do-i-remove-the-folder-path-from-the-url

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

No, it doesn't mean you need the second configuration file in any way.

First of all, your way of checking the Accept-Language HTTP header (documented in RFC 7231) is far from perfect. For example, it can be equal to de;q=0.9,pt;q=0.8,en;q=0.7. The first two characters is de, but the user still prefer Portuguese over the English. With PHP you have an ability to check all the preferred languages list and additionally check the weight of each language, but the nginx config isn't a programming language, so lets simplify things assuming the preferred languages list is sorted by the weights as most of modern browsers does. Assume the following tree structure:

mywebsite.com
└── html
    ├── 404.html
    ├── css
    │   ├── bootstrap.css
    │   └── style.css
    ├── jquery
    │   └── jquery.js
    ├── js
    │   ├── bootstrap.js
    │   └── vue.js
    ├── en
    │   ├── index.php
    │   ├── logout.php
    │   ├── signin.php
    │   └── signup.php
    └── pt
        ├── index.php
        ├── logout.php
        ├── signin.php
        └── signup.php

Now you can use a different root folder for the PHP files the following way:

map $http_accept_language $used_language {
    ~en.*pt(*SKIP)(*F)|pt  pt; # when "pt" substring present and not preceded with "en"
    ~pt.*en(*SKIP)(*F)|en  en; # when "en" substring present and not preceded with "pt"
    default                en; # or use "pt" if you want the Portuguese to be default
}

server {

        root /var/www/mywebsite.com/html;
        ...

        location ~ .php$ {
                root /var/www/mywebsite.com/html/$used_language; # override root folder
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.4-fpm.sock;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                internal;
        }

        ...
}

(Regex provided by Wiktor Stribi?ew)

The map block can be simplified to

map $http_accept_language $used_language {
    ~en.*pt(*SKIP)(*F)|pt  pt; # when "pt" substring present and not preceded with "en"
    default                en;
}

or

map $http_accept_language $used_language {
    ~pt.*en(*SKIP)(*F)|en  en; # when "en" substring present and not preceded with "pt"
    default                pt;
}

You can duplicate the whole tree structure (css, js, etc.) to the both en and pt folders and use dynamic root folder as global site root with the only one root directive, but if you have the localized content only within the PHP files, I don't think it makes sense.

An important caveat

Since now you are providing different content via same URLs, you should specify the Vary header to notify any caching layer between your server and visiting user that your content can vary upon the Accept-Language HTTP header value:

        location ~ .php$ {
                add_header Vary "Accept-Language";
                ...
        }

Cookies

Now to the Richard Smith's suggestion. I'm completely agree that the user should be able to switch the language. Here is an example combined with the previous answer:

nginx config

map $http_accept_language $language_by_header {
    ~en.*pt(*SKIP)(*F)|pt  pt; # when "pt" substring present and not preceded with "en"
    ~pt.*en(*SKIP)(*F)|en  en; # when "en" substring present and not preceded with "pt"
    default                en; # or use "pt" if you want the Portuguese to be default
}

map $cookie_language $used_language {
    pt                     pt;
    en                     en;
    # detect language from "Accept-Language" header when no "language" cookie present
    default                $language_by_header;
}

server {

        root /var/www/mywebsite.com/html;
        ...

        location ~ .php$ {
                root /var/www/mywebsite.com/html/$used_language; # override root folder
                add_header Vary "Accept-Language";
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.4-fpm.sock;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                internal;
        }

        ...
}

en/index.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>English</title>
    <script type='text/javascript' src='/js/functions.js'></script>
</head>
<body>
    <h1>Welcome! You're browsing the website with the English language.</h1>
    <a onclick="setCookie('pt');" href="<?php echo $_SERVER['REQUEST_URI']; ?>">pt</a>
</body>
</html>

pt/index.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Português</title>
    <script type='text/javascript' src='/js/functions.js'></script>
</head>
<body>
    <h1>Bem vindo! Você está navegando no website com o idioma Português.</h1>
    <a onclick="setCookie('en');" href="<?php echo $_SERVER['REQUEST_URI']; ?>">en</a>
</body>
</html>

js/functions.js

function setCookie(lc) {
    var today = new Date();
    // cookie expiry date - plus 30 days from today
    var expiry = new Date(today.getTime() + 30 * 24 * 3600 * 1000);
    document.cookie = 'language=' + lc + '; path=/; expires=' + expiry.toGMTString();
}

Of course this example needs some explanation, like the previous nginx config, but writing long explanations is a very time-consuming task for a non-native English speakers like me, and I really have a lack of time right now, try to understand whatever you can yourself, and if you'll need some additional explanations, ask me a question(s) in comments.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...