The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



Индекс форумов
Составление сообщения

Исходное сообщение
"Выпуск сервера приложений NGINX Unit 1.11.0"
Отправлено Ilya Indigo, 27-Окт-19 21:40 
> Почтовики? STARTTLS? Вы случайно с NNTP/Usenet не попутали? В списках рассылки можно
> хоть из веб-интерефейса Gmail с двухфакторной авторизацией общаться.

Нет не попутал. Отправить баг в postfix и dovecot через их маиллисты мне не представляется возможным. В Гугле, Яндексе и прочих зондах читающих Вашу почту и разрешающие общение с почтовиками без STARTTLS, можно, но я же PHP-ник, я ими не пользуюсь и никому не доверяю свою почту кроме своих почтовых серверов.

> index.html и так подставляется при запросе директории.  А вот эмулировать поведение
> log_not_found off; с помощью try_files - это странно.

А зачем вообще тогда по умолчанию заносить каждую 404 в лог ошибок?
Я думал логика в том, что каждый отдаваемый nginx-ом должен проходить через try_files, и если он отдаёт каким-то иным способом то именно это должно отображаться в файлах ошибок, но Ваш ответ меня удивил.

> Обычно вся конфигурация сводится к следующим двум location-ам:
> Всё предельно просто: если файл есть на диске - мы его отдаем,
> а всё остальное отправляем в приложение. Приложение уже возьмет $_SERVER['REQUEST_URI']
> и распарсит как угодно.

Огромная Вам благодарность за этот пример!
Во-первых я хоть где-то увидел как используется именованный location, когда в документации упоминается только что он есть и он указывается через @.
Во-вторых мне и в голову раньше не приходило, что так вообще возможно. Не знаю, можно ли так в апаче было сделать?
Мой код теперь.


error_page 404 /en/error;
location = /index.php
{
    return 404;
}
location ^~ /.
{
    return 404;
}
location /
{
    try_files $uri @php;
}
location @php
{
    fastcgi_pass unix:/run/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root/index.php;
    include fastcgi_params;
}

А на стороне PHP

<?php if(strpos($_SERVER['REQUEST_URI'],'?') > 0)
{
    if(isset($_SERVER['REQUEST_URI'][59],$_GET['token'][19],$_GET['PayerID'][12]) && !isset($_SERVER['REQUEST_URI'][60]) && strpos($_SERVER['REQUEST_URI'],'/payment?') == 3)
        $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'],0,strpos($_SERVER['REQUEST_URI'],'?'));
    else
    {
        unset($_GET,$_REQUEST);
        $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'],0,4).'error';
    }
}
if(strpos($_SERVER['REQUEST_URI'],'/.') === false && strpos($_SERVER['REQUEST_URI'],'.php') === false)
{
    $arr = explode('/',substr($_SERVER['REQUEST_URI'],1));
    if(isset($arr[0][1]) && !isset($arr[0][2]))
    {
        $_GET['lang'] = $arr[0];
        if(isset($arr[1]))
        {
            $_GET['view'] = $arr[1];
            if(isset($arr[2]))
            {
                if($_GET['view'] == 'api')
                {
                    if(substr($arr[2],-6) == '=.html')
                    {
                        $_GET['data'] = substr($arr[2],0,$p=strpos($arr[2],'='));
                        $_GET['iv'] = substr($arr[2],++$p,-6);
                        unset($p);
                    }
                    else $_GET['view'] = 'error';
                }
                elseif(substr($arr[2],-5) == '.html')
                    $_GET['id'] = substr($arr[2],0,-5);
                else
                {
                    $_GET['tab'] = $arr[2];
                    if(isset($arr[3]) && substr($arr[3],-5) == '.html')
                        $_GET['id'] = substr($arr[3],0,-5);
                }
            }
        }
    }
    else $_GET['view'] = 'error';
    unset($arr);
}
else $_GET['view'] = 'error';

Я полностью избавился от регулярок и от дублирования, не считая повторяющийся return 404;
При этом на стороне PHP это делать проще и удобнее, причём для этого мне не нужны регулярки вообще!
Этим кодом я почти доволен.
Осталось только логи отформатировать, статус прикрутить и кеширование со сжатием добавить.

Вот только одна особенность nginx-а и try_files доставила мне проблем.
У Apache 403 всегда сопровождается заголовком Access Denied и означает только это.
У nginx 403 сопровождается заголовком Forbidden и может означать что угодно. :-(


location /
{
    index index.html;
    try_files $uri $uri/ @php;
}

По моей логике при $uri / или /static/js/lib_name/doc/ (в doc есть index.html) алгоритм должен быть такой (эмулирую то, что в Apache по умолчанию)
1 Проверяет если файл $uri Да - отдаёт Нет - идёт дальше.
2 Проверяет есть ли файл $uri/index.html Да - отдаёт Нет - идёт дальше
3 Если дошло до этого шга, то запрос отправляется в PHP.

Но каково было моё удивление и недоумение получить 403 Forbidden в этой конфигурации и далеко не сразу понять почему и где...
оказывается, если $uri/index.html не существует - то никакой передачи дальше в PHP не происходит а nginx тупо выдаёт 403 Forbidden
В итоге приходится не использовать индексирование и указывать полный путь к /static/js/lib_name/doc/index.html и подобным докам не приятно, но жить с этим можно.

Почему в nginx так и зачем так было сделано?
Можно ли как-то просто и универсально исправить проблему и привести к желаемому поведению?
И ещё интересный вопрос, можно ли как-нибудь ещё вызывать именованые location кроме как из try_files? Если да, приведите, пожалуйста, примеры

> Программисты на других ЯП всю дорогу так и делали и только PHP-шники
> извращаются.
> А ещё правильнее - это всю статику положить в отдельную директорию. Посмотрите,
> к примеру, насколько просто выглядит конфигурация nginx для типичного сайта на
> Django:
> https://uwsgi.readthedocs.io/en/latest/tutorials/Django_and_...

Видимо потому-что программисты на других языках, занимаются не web-сайтами, в их классическом понимании, а всякими CRM-ками, встроенными интерфейсами, например для управления IP-камерами и прочими вещами не предназначенными для всеобщего обозрения.
По этому им не нужна ни безопасность, ни ЧПУ, ни индексирование в поисковиках, ни вообще чтобы кто-то про них знал и их находил.

В конфигурации на Django всё, казалось бы красиво, но вот незадача, она совершенно не знает про /robots.txt и /sitemap.xml Эти файлы пойдут лесом. А ещё файлы авторизации различных СЕО-ников для разных систем аналитики, которые в корень кладутся...
Мне, как админу серверов, нужно для каждого из них правило в nginx прописывать и каждый раз сервер передёргивать?
Знаю про то что для последнего можно DNS использовать, но давать СЕО-никам доступ к DNS ещё хуже.

А более, на мой взгляд, главное, эта конфигурация не защищает от отдачи скрытых файлов!
Например .git, или даже .directory,
Слышал, в Яндексе как раз и было такое, что у них их /.git/ спокойно nginx раздавал.

Так что не вижу ничего плохого в том, чтобы класть index.php в DOCUMENT_ROOT и запрещать к нему доступ, как и доступ ко всем скрытым файлам и директориям хотя бы в DOCUMENT_ROOT.
Это и удобнее и безопаснее, тем более у меня ущё со времён апача в нём всего одна строчка <?php require dirname(__DIR__).'/init.php';

Ещё для меня одним неприятным открытием было, когда я убрал index.php из DOCUMENT_ROOT и вызывал сразу init.php, у меня перестал читаться .user.ini файл, даже после того, как я продублировал его за DOCUMENT_ROOT, видимо для его чтения он должен находится только в DOCUMENT_ROOT вместе с вызываемым скриптом (точкой входа).

Так что пользы от выноса index.php из DOCUMENT_ROOT я не вижу, а проблемы появляются достаточно.

> REQUEST_URI не обязан как-либо пересекаться с SCRIPT_FILENAME. Это в Apache с mod_php
> и .htaccess иначе сложно, там выполняемый файл эквивалентен запрашиваемому URI. С
> FastCGI не так и нет смысла тащить костыли от mod_php на
> FastCGI конфигурацию.

Я это уже понял. Для этого я и веду с Вами этот публичный диалог, чтобы работать с nginx правильно, а не так, как я привык работать с Apache.
А также чтобы это потом пригодилось не только мне, но у другим... PHP-никам.

> Можно наблюдать Max Early Data: 16384

Благодарю, значит работает! :-)

>> Хотелось бы если не формул, то инструкций по тому как узнать что
>> процессов не хватает или их в избытке. Понимаю что эта тема
>> не Ваша, буду разбираться с этим дальше.
> Посмотрите для начала сколько у вас один процесс занимает памяти. Настраивать их
> количество больше, чем имеющейся свободной памяти на сервере - точно не
> стоит.

На сервере же не один PHP работает. Там и MariaDB ей тоже ОЗУ нужна под всякие индексы.
Redis обитает, кеширующий ответы от MariaDB, и тоже будет рад лишней ОЗУ.
Но с redis я понимаю и знаю как определять и контролировать его расход ОЗУ и выдаю ему столько, сколько нужно, но чтобы без переизбытка.
И у php-fpm, наверно есть какой-то разумный предел кол-ва процессов, больше которого ресурсы потребляет, но выигрыш в производительности не приносит.
Или ему нужно отдавать все свободные ресурсы сервера?

 

Ваше сообщение
Имя*:
EMail:
Для отправки ответов на email укажите знак ! перед адресом, например, !user@host.ru (!! - не показывать email).
Более тонкая настройка отправки ответов производится в профиле зарегистрированного участника форума.
Заголовок*:
Сообщение*:
  Введите код, изображенный на картинке: КОД
 
При общении не допускается: неуважительное отношение к собеседнику, хамство, унизительное обращение, ненормативная лексика, переход на личности, агрессивное поведение, обесценивание собеседника, провоцирование флейма голословными и заведомо ложными заявлениями. Не отвечайте на сообщения, явно нарушающие правила - удаляются не только сами нарушения, но и все ответы на них. Лог модерирования.



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру