Запись данных POST из $request_body
У меня есть моя настройка конфигурации для обработки множества запросов GET, которые отображают пиксели, которые отлично работают для обработки аналитики и анализируют строки запроса для ведения журнала. С дополнительным потоком сторонних данных мне нужно обработать запрос POST на заданный URL-адрес, который имеет JSON в ожидаемом формате для регистрации внутри этого тела запроса. Я не хочу использовать вторичный сервер с proxy_pass
и просто хочу записать весь ответ в связанный файл журнала, как то, что он делает с запросами GET. Фрагмент кода, который я использую, выглядит следующим образом:
Запрос GET (который отлично работает):
location ^~ /rl.gif {
set $rl_lcid $arg_lcid;
if ($http_cookie ~* "lcid=(.*\S)")
{
set $rl_lcid $cookie_lcid;
}
empty_gif;
log_format my_tracking '{ "guid" : "$rl_lcid", "data" : "$arg__rlcdnsegs" }';
access_log /mnt/logs/nginx/my.access.log my_tracking;
rewrite ^(.*)$ http://my/url?id=$cookie_lcid? redirect;
}
Вот что я пытаюсь сделать:
Запрос POST (который не работает):
location /bk {
log_format bk_tracking $request_body;
access_log /mnt/logs/nginx/bk.access.log bk_tracking;
}
Керлинг curl http://myurl/bk -d name=example
дает мне 404 страницы, которые не найдены.
Затем я попытался:
location /bk.gif {
empty_gif;
log_format bk_tracking $request_body;
access_log /mnt/logs/nginx/bk.access.log bk_tracking;
}
Керлинг curl http://myurl/bk.gif -d name=example
дает мне 405 Not Allowed
.
Моя текущая версия nginx/0.7.62
. Любая помощь в правильном направлении очень ценится! Спасибо!
UPDATE
Итак, теперь мой пост выглядит следующим образом:
location /bk {
if ($request_method != POST) {
return 405;
}
proxy_pass $scheme://127.0.0.1:$server_port/dummy;
log_format my_tracking $request_body;
access_log /mnt/logs/nginx/my.access.log my_tracking;
}
location /dummy { set $test 0; }
Он правильно регистрирует данные сообщения, но возвращает 404 на конец запроса. Если я изменю приведенный выше код, чтобы вернуть 200 так:
location /bk {
if ($request_method != POST) {
return 405;
}
proxy_pass $scheme://127.0.0.1:$server_port/dummy;
log_format my_tracking $request_body;
access_log /mnt/logs/nginx/my.access.log my_tracking;
return 200;
}
location /dummy { set $test 0; }
Затем он вернет 200
правильно, но больше не записывает данные сообщения.
ДРУГОЕ ОБНОВЛЕНИЕ
Кинда нашел рабочее решение. Надеюсь, это может помочь другим на своем пути.
Ответы
Ответ 1
Это решение работает как шарм (обновлено в 2017 году, чтобы удостовериться, что log_format должен находиться в http-части конфигурации nginx):
log_format postdata $request_body;
server {
# (...)
location = /post.php {
access_log /var/log/nginx/postdata.log postdata;
fastcgi_pass php_cgi;
}
}
Я думаю, что трюк заставляет nginx полагать, что вы вызовете cgi script.
Ответ 2
Попробуйте echo_read_request_body.
" echo_read_request_body... Явно читает тело запроса, так что переменная $request_body всегда будет иметь непустые значения (если только тело настолько велика, что он был сохранен Nginx в локальном временном файле).
location /log {
log_format postdata $request_body;
access_log /mnt/logs/nginx/my_tracking.access.log postdata;
echo_read_request_body;
}
Ответ 3
Хорошо. Итак, наконец, я смог записать данные постов и вернуть 200. Это своего рода хакерское решение, которым я не слишком горжусь, которое в основном переопределяет естественное поведение для error_page, но мой неопытность по временным шкалам nginx plus привела меня к этому решению. :
location /bk {
if ($request_method != POST) {
return 405;
}
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_pass $scheme://127.0.0.1:$server_port/success;
log_format my_tracking $request_body;
access_log /mnt/logs/nginx/my_tracking.access.log my_tracking;
}
location /success {
return 200;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/nginx-default;
log_format my_tracking $request_body;
access_log /mnt/logs/nginx/my_tracking.access.log my_tracking_2;
}
Теперь, согласно этой конфигурации, может показаться, что проход прокси будет возвращать 200 все время. Иногда я получал 500, но когда я добавлял error_log, чтобы увидеть, что происходит, все мои данные request_body были там, и я не мог увидеть проблему. Я поймал это и написал в тот же журнал. Поскольку nginx не нравится одно и то же имя для переменной отслеживания, я просто использовал my_tracking_2 и записал в тот же журнал, что и при возврате 200. Определенно, это не самое элегантное решение, и я приветствую любое лучшее решение. Я видел модуль post, но в моем сценарии я не смог перекомпилировать из исходного кода.
Ответ 4
FWIW, эта конфигурация работала для меня:
location = /logpush.html {
if ($request_method = POST) {
access_log /var/log/nginx/push.log push_requests;
proxy_pass $scheme://127.0.0.1/logsink;
break;
}
return 200 $scheme://$host/serviceup.html;
}
#
location /logsink {
return 200;
}
Ответ 5
Формат журнала nginx
взят отсюда: http://nginx.org/en/docs/http/ngx_http_log_module.html
не нужно устанавливать ничего лишнего
работал на меня для запросов GET
и POST
:
upstream my_upstream {
server upstream_ip:upstream_port;
}
location / {
log_format postdata '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" "$request_body"';
access_log /path/to/nginx_access.log postdata;
proxy_set_header Host $http_host;
proxy_pass http://my_upstream;
}
}
просто измените upstream_ip
и upstream_port
Ответ 6
У меня была аналогичная проблема. Выполнены запросы GET, и их (пустые) запросы были записаны в файл журнала. Запросы POST не удались с 404. Попытавшись немного, я обнаружил, что все запросы POST не сработали. Я нашел сообщение в котором размещался вопрос о запросах POST, и решение для меня работало. Это решение? Добавьте строку proxy_header
прямо перед строкой proxy_pass
, точно так же, как в примере ниже.
server {
listen 192.168.0.1:45080;
server_name foo.example.org;
access_log /path/to/log/nginx/post_bodies.log post_bodies;
location / {
### add the following proxy_header line to get POSTs to work
proxy_set_header Host $http_host;
proxy_pass http://10.1.2.3;
}
}
(Это с nginx 1.2.1 для того, что стоит.)
Ответ 7
Приведенное ниже решение было лучшим форматом, который я нашел.
log_format postdata escape=json '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" "$request_body"';
server {
listen 80;
server_name api.some.com;
location / {
access_log /var/log/nginx/postdata.log postdata;
proxy_pass http://127.0.0.1:8080;
}
}
Для этого ввода
curl -d '{"key1":"value1", "key2":"value2"}' -H "Content-Type: application/json" -X POST http://api.deprod.com/postEndpoint
Создайте этот великолепный результат
201.23.89.149 - [22/Aug/2019:15:58:40 +0000] "POST /postEndpoint HTTP/1.1" 200 265 "" "curl/7.64.0" "{\"key1\":\"value1\", \"key2\":\"value2\"}"