Как вы правильно заметили, post_action
не задокументировано и всегда считалось неофициальной директивой.
Nginx предоставляет новый "зеркальный" модуль начиная с версии 1.13.4, описанный здесь в документации.Поэтому я советую вам попробовать.В вашем случае это выглядело бы так:
location /r/ {
rewrite /r/(.*)$ http://localhost:3000/sample/route1/$1 redirect;
mirror /stats;
}
location = /stats {
internal;
rewrite /sample/route1/(.*) /stats/$1;
proxy_pass http://127.0.0.1:3000;
}
Это не сработает!
Я создал тестовую конфигурацию и, к сожалению, это не сработает.Это не работает ни для rewrite
, ни для return
.Но это работает для proxy_pass
.
Почему
Объяснение следующее.HTTP-запрос последовательно проходит несколько «фаз» во время обработки в Nginx.Дело в том, что mirror
запускается на этапе PRECONNECT
, который происходит позже, чем на этапе REWRITE
, где rewrite
/ return
завершает обработку запроса.Таким образом, mirror
даже не запускается, потому что его обработка произойдет позже.
В случае подачи файлов с местоположения или прокси через proxy_pass
(или fastcgi_pass
и т. Д.) Обработка будет окончательно завершена.достигните REWRITE
фазы и mirror
будут выполнены.
Фазы описаны в документации Nginx здесь .
Временные решения
Я не вижулюбое хорошее решение без компромиссов.Вы можете создать дополнительное местоположение (возвращающее перенаправление) и прокси-запрос от /r/
, так что mirror
будет запущен.Примерно так, в зависимости от остальной части вашей конфигурации:
location /r/ {
# you may need setting Host to match `server_name` to make sure the
# request will be caught by this `server`.
# proxy_set_header Host $server_name;
proxy_pass http://<ip from listen>:<port from listen>/redirect/;
mirror /stats;
}
location = /redirect {
rewrite /redirect(.*)$ http://localhost:3000/sample/route1$1 redirect;
}
Конечно, это неоптимально и имеет дополнительный шаблон.