Pull to refresh
259
0
Alexander@simpleadmin

User

Send message

Этот пример я уже приводил выше.
Так и должно работать, так как директивы модуля работают в фазе REWRITE:

$ grep -rnF PHASE ../form-input-nginx-module-master/
../form-input-nginx-module-master/src/ngx_http_form_input_module.c:372:    h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);

Использование echo_read_request_body - абсолютно бесполезно, точнее просто вредно. Если пакет поднялся до фазы CONTENT, то для того чтобы выполнить if (значит попасть в фазу REWRITE) у него есть только один выход - выполнить проксирование. Но при использовании директивы proxy_pass переменная $request_body получит значение автоматически, то есть echo_read_request_body просто лишено смысла.

Хороший пример насколько модуль быстрее njs.

Скорее пример того насколько быстрее будет завершить обработку в REWRITE-фазе, чем в CONTENT

Маршруты пакета для обоих случаев:

$ cat /tmp/tree.txt | grep phase | awk '{print $3}' | uniq
ngx_http_core_generic_phase
ngx_http_core_rewrite_phase
ngx_http_core_find_config_phase
ngx_http_core_rewrite_phase

$ cat /tmp/tree_njs.txt | grep phase | awk '{print $3}' | uniq
ngx_http_core_generic_phase
ngx_http_core_rewrite_phase
ngx_http_core_find_config_phase
ngx_http_core_rewrite_phase
ngx_http_core_post_rewrite_phase
ngx_http_core_generic_phase
ngx_http_core_access_phase
ngx_http_core_post_access_phase
ngx_http_core_generic_phase
ngx_http_core_content_phase
server {
    root /www/example_com;
    listen *:80;
    server_name  .example.com;
        
    location /index.php {
        fastcgi_pass   unix:/var/run/php-fpm.sock;
        fastcgi_param  SCRIPT_FILENAME         $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}
<?php
if(!count($_REQUEST)) http_response_code(418);
die();

19691

js_import /scripts/nginx/js/check_body.js;
server {
    root /www/example_com;
    listen *:80;
    server_name  .example.com;
        
    location /index.php {
        fastcgi_pass   unix:/var/run/php-fpm.sock;
        fastcgi_param  SCRIPT_FILENAME         $document_root$fastcgi_script_name;
        include        fastcgi_params;
        
        js_content check_body.body_empty;
        #if ( $request_body = '' ) {
        #  return 418;
        #}
    }
}

12263

server {
    root /www/example_com;
    listen *:80;
    server_name  .example.com;
        
    location /index.php {
        fastcgi_pass   unix:/var/run/php-fpm.sock;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include fastcgi_params;
        
        set_form_input_multi $data;
        
        if ( $data = '' ) {
          return 418;
        }
    }
}

6009

Время в наносекундах от ngx_http_handler:entry до ngx_http_finalize_request:return

Усредненное для 100000 "пустых" POST-запросов.

echo-nginx-module работает в CONTENT-фазе, там мы можем получить $request_body и без сторонних модулей.

Как всё это поможет проверить переменную $request_body в REWRITE-фазе?

Как это поможет установить значение в переменной $request_body?

Скажем так - я не думаю, что njs станет узким местом.
Но и делать так я точно не стал бы - сопровождать такое никакого желания. Решение только на случай если "можно использовать только nginx".
Как вариант можно использовать https://github.com/calio/form-input-nginx-module:

    location /index.php {
        fastcgi_pass   unix:/var/run/php-fpm.sock;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include fastcgi_params;
        
        set_form_input_multi $data;
        
        if ( $data = '' ) {
          return 418;
        }
    }

Но, опять же, спорное решение и в плане поддержки и в плане производительности.

Прототип решения по ссылке на форум вполне хорош.
Нам нужно переместить обработку условия в CONTENT-фазу, njs вполне для этого подходит, применительно к примеру из статьи как-то так:

js_import check_body.js;
server {
    root /www/example_com;
    listen *:80;
    server_name  .example.com;
        
    location /index.php {
        fastcgi_pass   unix:/var/run/php-fpm.sock;
        fastcgi_param  SCRIPT_FILENAME         $document_root$fastcgi_script_name;
        include        fastcgi_params;
        
        js_content check_body.body_empty;
    }
}
function body_empty(r) {
  if (r.method == "POST" && (typeof(r.requestBody) == "undefined" || r.requestBody === null)) {
    r.return(418, "Empty\n");
  } else {
    r.return(200, "ret:[" + r.requestBody + "]\n");
  }
}

export default {body_empty};
$ curl -w "HTTP CODE: %{http_code}\n" -d "key1=value1" -X POST "example.com/index.php" \
ret:[key1=value1]
HTTP CODE: 200
$ curl -w "HTTP CODE: %{http_code}\n" -X POST "example.com/index.php"
Empty
HTTP CODE: 418

По map есть отличная статья, но а данном случае он также не поможет.

К сожалению, я не смог воспроизвести проблему (да и просто уже не помню деталей), с которой столкнулся в 2017-м, но общую идею изложил здесь.
Тут помимо сказанного есть ещё и второй момент.
Если не делать дальнейшую постобработку 503-х, то данное решение может быть даже во вред. По сути здесь мы (частично) заменили отдачу 402-х на отдачу 503-х.
При этом 402-е мы отдавали в четвертой фазе, а 503-е будем отдавать сначала поднявшись до 9-й, опустившись до 4-й и снова поднявшись до 6-й. Да, это микросекунды, но решение получается абсурдным если отдача 402-х не предполагает существенно большего контента чем 503-е или если дальше не делать анализ логов на наличие 503-х, с перманентной блокировкой ботов и т.п.
Откуда смелое предположение что такого каталога не существует?/blockquote>

Почему предположение? Мы намеренно создаём рабочую для нас конфигурацию с отдачей контента на этапе NGX_HTTP_SERVER_REWRITE_PHASE. Каталоги/файлы для этого нам не нужны. Задача ведь в том, чтобы отдать контент как можно раньше, не дергая fpm, базу и т.д.

Я возможно заблуждаюсь, но при наличии оного вся эта изящная схема работает несколько не так как предполагается?

При наличии каталога данная схема и не должна работать, но наличие каталога "/pay" (в соответствующем «root») говорит о том, что мы хотим формировать контент «задействовав» данную директорию. То есть речь идёт о фазе NGX_HTTP_CONTENT_PHASE, следовательно описанная проблема уже и так не возникает, так как мы перешагнули этап NGX_HTTP_PREACCESS_PHASE.
Встречный вопрос: «Почему он должен быть?»
Описание местоположения не подразумевает создание каталога или файла.
Возможно, этот момент стоило указать явно, но в данном случае отдача контента осуществляется директивой return, поэтому наличие каталога не требуется (а точнее, наоборот, вредит).
Документация устарела. По факту сейчас (для версии 1.21):
$ grep -rnF 'ngx_string("try_files")' ./nginx-1.21.0/src/
./nginx-1.21.0/src/http/modules/ngx_http_try_files_module.c:36:    { ngx_string("try_files"),

Для старых версий действительно:
$ grep -rnF 'ngx_string("try_files")' ./nginx-1.11.5/src/
./nginx-1.11.5/src/http/ngx_http_core_module.c:637:    { ngx_string("try_files"),
Да, я про то что надо было поставить камеру.
С птичками, в целом, у меня не складывается — каждый год достаю гнездо из вентиляции.
В этом году решил-таки залезть на крышу, заделать сеткой все труб вентиляции.
Ух, у меня в можжевельнике неизвестные птички завелись, а я не знал, что делать:
Заголовок спойлера

упс, был уверен, что они в белом блистере.
Нашёл свой и прослезился…
image
Когда ещё в Икею попаду…
Увидев заглавное фото, зашел возмутиться «где Икея?!», но, оказалось, в этом и была замануха.
SBG-3 обещают запустить.
Гарантированно умер только SBG-2.

Information

Rating
Does not participate
Registered
Activity