NGINX - Почему я получаю 403 Forbidden для root локации? - PullRequest
0 голосов
/ 12 июля 2020

Я разработал проект со следующей структурой:

api.my-domain.com: API Restfull, встроенный в Symfony 5. app.my-domain.com: Приложение Angular. www.my-domain.com: простой, но красивый HTML / CSS / JS целевая страница.

Эта структура обслуживается с использованием NGINX на сервере Ubuntu. Файлы конфигурации для сайтов api и app работают нормально. Здесь нечего делать.

Для landing у меня есть некоторые особые требования:

  • Мне нужно перенаправить на сайт app запрос, содержащий «логин» или « pm - ".
  • Мне нужно поддерживать многоязычный сайт, поэтому:
    • Когда кто-то обращается к www.my-domain.com/** es **, сервер должен показывать index_ es . html
    • Когда кто-то обращается к www.my-domain.com/** en **, сервер должен отображать index_ en . html
    • Когда кто-то обращается к www.my-domain.com/** ca **, сервер должен отображать index_ ca . html
  • Когда кто-то обращается к www.my-domain.com, сервер должен вернуть index_es. html; но он также должен разрешать доступ к другим файлам c на сервере (изображения, шрифты, стили ...), чтобы лендинги работали.

Эти требования уже выполняются с использованием следующий NGINX сайт конфигурации сайта:

server {
    server_name www.my-domain.com my-domain.com;
    root /var/www/my-project/;

    location = /es {
      try_files /index_es.html /index.html;
    }

    location = /en {
      try_files /index_en.html /index.html;
    }

    location = /ca {
      try_files /index_ca.html /index.html;
    }

    location = / {
      try_files /index_es.html /index.html;
    }

    location ~ ^/(login|pm-) {
      return 301 $scheme://app.my-project.com$request_uri;
    }
    
    location / {
      try_files $uri $uri/ /index_es.html;
    }

    error_log /var/log/nginx/my-project-error.log;
    access_log /var/log/nginx/my-project-access.log;



    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/my-project.com-0001/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/my-project.com-0001/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




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


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

    server_name www.my-project.com my-project.com;
    listen 80;
    return 404; # managed by Certbot

}

Дело в том, что при первой попытке заставить его работать я не поместил следующий фрагмент кода:

location = / {
  try_files /index_es.html /index.html;
}

Потому что я думал, что достаточно указать это:

location / {
  try_files $uri $uri/ /index_es.html;
}

Но когда я попытался получить доступ к www.my-domain.com, я получил 403 Запрещенную страницу из NGINX. Итак, вопросы:

  • Почему мне в настоящее время нужно вставить фрагмент кода location = /, чтобы он заработал?
  • Как я могу оптимизировать конфигурацию, чтобы удалить фрагмент кода location = /?

Заранее спасибо.

1 Ответ

0 голосов
/ 12 июля 2020

Ваша конфигурация была бы намного чище, если бы вы прибегли к простым rewrite s непосредственно в контексте server:

server {
    server_name www.my-domain.com my-domain.com;
    root /var/www/my-project/;

    rewrite ^/(es|en|ca)$ /index_$1.html;
    
    location = / {
        index index_es.html; 
    }
    # ...
}

Для веб-сайта stati c я бы рекомендовал полностью исключить try_files. Это имеет смысл только для динамических c веб-сайтов, а может быть злым .

Почему мне сейчас нужно поместить location = / кусок кода чтобы заставить его работать?

Потому что в вашей опубликованной конфигурации, если вы удалите его, тогда для URI /, NGINX выберет блок location / {, который будет пытаться (из-за $uri/) файлы, определенные как index, по умолчанию - index.html. Таким образом, он попытается проверить, существует ли он, преуспеть в этом и использовать его для обслуживания запроса.

После того, как вы определите location = /, NGINX будет использовать его для обслуживания, потому что тип точного соответствия (=) всегда имеет приоритет в NGINX по сравнению с другими типами местоположения.

Как я могу оптимизировать конфигурацию, чтобы удалить location = / piece of code?

Вам действительно не нужно удалять location = / (см. Измененную конфигурацию выше). Во всяком случае, предпочтительнее точный тип соответствия, так как это приведет к наиболее быстрому сопоставлению. (если вы не можете справиться с этим, удалив проверки существования файлов, см. ниже).

Кто-то может возразить, будет ли:

location = /es {
    try_files /index_es.html /index.html;
}

location = /en {
    try_files /index_en.html /index.html;
}

location = /ca {
    try_files /index_ca.html /index.html;
}

... быстрее, чем предложенный rewrite. Это не будет быстро из-за try_files, что замедляет работу. Причина в том, что try_files сначала проверяет файл на наличие, а затем принимает решение, переходить ли к следующему файлу или обслуживать.

Принимая во внимание, что rewrite принимает безусловное решение о том, какой файл для обслуживания. (конечно, если у вас нет других директив, влияющих на это).

Вы также можете попытаться оптимизировать еще больше, не используя index и используя rewrite для домашней страницы. (помните, что index также несет потери производительности проверки существования файла, как и try_files).

Таким образом:

server {
    server_name www.my-domain.com my-domain.com;
    root /var/www/my-project/;

    rewrite ^/(es|en|ca)$ /index_$1.html;
    rewrite ^/$ /index_es.html; 
    # ...
}
...