Регистрация данных POST из тела $запроса
у меня есть настройка конфигурации для обработки группы запросов GET, которые отображают пиксели, которые отлично работают для обработки аналитики и анализа строк запроса для ведения журнала. С дополнительным потоком данных третьей стороны мне нужно обработать запрос POST на заданный url-адрес, который имеет JSON в ожидаемом формате loggable внутри его тела запроса. Я не хочу использовать вторичный сервер с 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. Любая помощь в правильном направлении очень ценится! Спасибо!
обновление
Так что теперь мой пост выглядит так:
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; }
он регистрирует данные post правильно, но возвращает 404 на конце requesters. Если я изменить приведенный выше код, чтобы вернуть 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 правильно, но больше не записывает данные post.
ЕЩЕ ОДНО ОБНОВЛЕНИЕ
Вроде как нашел рабочее решение. Надеюсь, это может помочь другим на их путь.
6 ответов:
Это решение работает как шарм (Обновлено в 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.
попробуйте 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; }
ОК. Поэтому, наконец, я смог зарегистрировать данные post и вернуть 200. Это своего рода хакерское решение, которым я не горжусь, которое в основном переопределяет естественное поведение для error_page, но моя неопытность в NGINX plus timelines приводит меня к этому решению:
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, но в моем сценарии я не мог перекомпилировать из источника.
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
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; }
у меня была похожая проблема. Получить запросы работали и их (пустые) тела запросов были записаны в файл журнала. Запросы POST не удалось выполнить с помощью 404. Экспериментируя немного, я обнаружил, что все запросы 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 за то, что он стоит.)
Comments