allow/deny and return

Gena Makhomed gmm at csdoc.com
Sun Oct 20 13:25:42 UTC 2013


On 18.10.2013 16:50, Maxim Dounin wrote:

>> если же посмотреть со стороны пользователей - в большинстве случаев
>> написание конфигурации стало проще, удобнее и безглючнее, потому что
>> вместо фигурного выпиливания лобзиком работающей конфигурации
>> на основе директив if + return + error_page
>> + recursive_error_pages + proxy_intercept_errors
>> + fastcgi_intercept_errors + scgi_intercept_errors
>> + uwsgi_intercept_errors + ...
>> можно взять директиву try_files с простой и понятной логикой работы,
>> которая подходит для большинства наиболее частоиспользуемых случаев.
>
> Проблема в том, что "выпиливание лобзиком" - как было, так и
> осталось. Только к списку директив добавилась ещё парочка,
> за которыми нужно следить - try_files и alias.

Ошибки работы try_files в location с alias ведь можно исправить?

Почти всегда конфиг с директивой try_files будет проще и понятнее,
чем при использовании комбинации директив if + return + error_page

Ведь директива error_page предназначена для обработки ошибок,
когда Файл точно должен был быть, но его там вдруг не оказалось.

Исключительная ситуация, о которой записывается информация в лог
и показывается соответствующая страница с сообщением про ошибку.

try_files - это ведь директива _выбора_ location для обработки запросов,
если файл существует - используется этот location. если нет - тогда тот.

Например, что будет проще и удобнее:

   location ~ \.php$ {
     error_page 404 = @virtual;
     log_not_found off;
     if (!-f $request_filename) {
         return 404;
     }
     fastcgi_pass ...;
   }

или

   location ~ \.php$ {
     try_files $uri @virtual;
     fastcgi_pass ...;
   }

?

> Отдельно печалит, что в результате конфигурации с error_page 404
> @fallback - практически исчезли, хотя аналог на try_files -
> гарантированно хуже.

Аналог на try_files будет "гарантированно хуже" только в том случае,
когда для обработки запросов используется модуль static. Если другой
content handler (fastcgi_pass, proxy_pass и т.п.) - try_files лучше.

Даже в том случае, когда content handler`ом будет модуль static:

С точки зрения производительности - да, это будет чуть-чуть хуже,
один лишний syscall и маловероятная возможность "race condition".

Но с точки зрения простоты написания / сопровождения конфига -
директива try_files и в этом случае будет лучше чем error_page.

"Programs must be written for people to read,
and only incidentally for machines to execute" - Hal Abelson

- по сути nginx.conf - это программа для интерпретатора /usr/sbin/nginx

"Предпочтение простоте заложено в нашей ДНК и это вряд ли изменится
в течение нескольких миллиардов лет. ...при наличие выбора, человек 
всегда выберет более простой путь." - цитата из книги  Кена Сигалла
"Безумно просто. Вдохновляющие примеры Apple".

потому и пропали конфигурации с error_page 404 @fallback,
- появился более простой и более удобный вариант try_files.

P.S.

Кстати, при желании можно устранить все недостатки try_files.

try_files - это синтаксический сахар для if, return и error_page -
следовательно в процессе парсинга конфига можно транслировать директиву
try_files "высокого уровня" в набор директив "низкого уровня", которые
и будут реально исполняться nginx через ngx_http_core_try_files_phase.

например, такой фрагмент конфига:

location ... {
   error_page 404 /404.html;
   try_files $uri @virtual;
   # static module handler;
}

всегда будет игнорировать "лишнюю" директиву error_page 404,
поэтому try_files можно развернуть в error_page 404 = @virtual;
и log_not_found off; вообще без ngx_http_core_try_files_phase.

фрагмент конфига

   location ~ \.php$ {
     try_files $uri @virtual;
     fastcgi_pass ...;
   }

можно развернуть в

   location ~ \.php$ {
     if (!-f $request_filename) {
       internal_redirect @virtual; # это на уровне байт-кода rewrite
     }
     fastcgi_pass ...;
   }

поскольку сгенерированная из try_files и невидимая пользователю
директива if будет работать на NGX_HTTP_TRY_FILES_PHASE, после access
- поведение конфига 100% соответствовать существующей сейчас
документации на директиву try_files.

Если я ничего не путаю, любую директиву try_files
можно транслировать в произвольную комбинацию директив
if + return + error_page, возможно с дополнительными location`ами.

Тогда нельзя будет сказать с точки зрения реализации,
что "аналог на try_files - гарантированно хуже", потому что
try_files будет идентичен аналогу на if, и даже будет лучше if,
потому что try_files работает после прохождения access-проверок.

А с точки зрения пользователя - try_files практически всегда
будет лучше, потому что это более простая и понятная директива.

-- 
Best regards,
  Gena



Подробная информация о списке рассылки nginx-ru