#nginx #nginx-reverse-proxy #nginx-config
#nginx #nginx-обратный прокси #nginx-config
Вопрос:
есть ли в nginx способ что-то сделать, основываясь на том, есть ли в теле запроса строка или нет? Я уверен, что смогу сделать это с помощью модуля Lua.. Я пытаюсь выяснить, есть ли способ использовать только nginx.
Я надеюсь, что сработает что-то вроде приведенного ниже.
location /students-api {
if ($request_body ~* "(.*)specialstudent(.*)" ) {
set $student_status 'special';
}
// and use student_status for some logic
}
Ответ №1:
Я думаю, что это должно сработать, однако его нужно протестировать. На практике я использовал $request_body
только для ведения журнала, не уверен, доступно ли оно на этапе перезаписи обработки запроса. Вот официальное описание, в котором говорится:
Значение переменной становится доступным в местах, обработанных директивами
proxy_pass
,fastcgi_pass
,uwsgi_pass
, иscgi_pass
, когда тело запроса считывалось в буфер памяти.
Кроме того, вам не нужны эти группы захвата для проверки переменной на наличие подстроки, если вы не используете их позже (на самом деле вы просто тратите ресурсы, чтобы сохранить их в памяти), просто if ($request_body ~* "specialstudent") { ... }
должно быть достаточно.
Обновить
Вот еще один подход, который имеет больше шансов на работу, поскольку proxy_add_header
директива определенно выполняется позже, чем этап перезаписи обработки запроса:
map $request_body $special {
~*"specialstudent" "special";
# otherwise '$special' variable value will be empty
}
server {
...
location /students-api {
...
proxy_set_header X-Student-Status $special;
...
}
}
Обновление 2
После тестирования всего этого я могу подтвердить, что if
подход не работает:
server {
...
location /students-api {
if ($request_body ~* "specialstudent") {
set $student_status "special";
}
proxy_set_header X-Student-Status $student_status;
...
}
}
Как и ожидалось, $request_body
переменная не инициализируется на этапе перезаписи обработки запроса. Однако map
подход работает так, как ожидалось:
map $request_body $student_status {
~*"specialstudent" "special";
# otherwise '$special' variable value will be empty
}
server {
...
location /students-api {
proxy_set_header X-Student-Status $student_status;
...
}
}
Что меня действительно удивляет, так это то, что в следующем примере не задается ни один из двух заголовков:
map $request_body $student_status {
~*"specialstudent" "special";
# otherwise '$special' variable value will be empty
}
server {
...
location /students-api {
if ($request_body ~* "specialstudent") {
set $student_special "special";
}
proxy_set_header X-Student-Status $student_status;
proxy_set_header X-Student-Special $student_special;
...
}
}
Каким-то образом доступ к $request_body
переменной на ранней стадии перезаписи обработки запроса приводит map
к тому, что перевод также перестает работать. На данный момент у меня не было объяснения такого поведения, и я был бы признателен, если бы кто-нибудь мог объяснить, что здесь произошло.
Обновление 3
Я думаю, что я, наконец, нашел объяснение того, что произошло с последним примером в руководствах по Nginx, написанных Ичунь Чжаном, автором известного lua-nginx-module и пакета OpenResty:
Некоторые переменные Nginx предпочитают использовать свои контейнеры значений в качестве кэша данных, когда настроен «обработчик получения». В этом параметре «обработчик получения» запускается только один раз, т. Е. При первом чтении переменной, что снижает накладные расходы, когда переменная считывается несколько раз в течение ее жизни.
Похоже $request_body
, что переменная ведет себя именно так, если к ней обращаются на ранней NGX_HTTP_REWRITE_PHASE
стадии (см. Описание этапов обработки запроса). Его значение, если оно считывается на этом этапе, кэшируется как пустое значение и становится бесполезным на более поздних этапах обработки запроса.
Комментарии:
1. Хм .. у меня есть логика, основанная на этом .. вот в чем причина.. Я попробовал это, если проверить; но не сработало
2. Разные директивы nginx обрабатываются на разных этапах обработки запроса. Может быть, вы могли бы показать еще немного этой конфигурации местоположения? Содержит ли это местоположение какой-либо запрос к серверной части (proxy / FCGI / WSGI)?
3. ДА.. затем он устанавливается в заголовок, и запрос проксируется… вся логика работает без этого If; теперь я хочу изолировать conidition и перейти в блок if
4. Что-то вроде
proxy_set_header X-Student-Status $special;
?5. Это будет работать именно так, если тело не будет содержать строку «specialstudent»,
$student_status
переменная будет иметь пустое значение, а заголовок вообще не будет установлен (поскольку мы передаем пустое значениеproxy_set_header
директиве).