Logging POST data from $request_body
Try echo_read_request_body.
"echo_read_request_body ... Explicitly reads request body so that the $request_body variable will always have non-empty values (unless the body is so big that it has been saved by Nginx to a local temporary file)."
location /log {
log_format postdata $request_body;
access_log /mnt/logs/nginx/my_tracking.access.log postdata;
echo_read_request_body;
}
Ok. So finally I was able to log the post data and return a 200. It's kind of a hacky solution that I'm not too proud of which basically overrides the natural behavior for error_page, but my inexperience of nginx plus timelines lead me to this solution:
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;
}
Now according to that config, it would seem that the proxy pass would return a 200 all the time. Occasionally I would get 500 but when I threw in an error_log to see what was going on, all of my request_body data was in there and I couldn't see a problem. So I caught that and wrote to the same log. Since nginx doesn't like the same name for the tracking variable, I just used my_tracking_2 and wrote to the same log as when it returns a 200. Definitely not the most elegant solution and I welcome any better solution. I've seen the post module, but in my scenario, I couldn't recompile from source.
This solution works like a charm:
http {
log_format postdata $request_body;
server {
location = /post.php {
access_log /var/log/nginx/postdata.log postdata;
fastcgi_pass php_cgi;
}
}
}
I think the trick is making nginx believe that you will call a CGI script.
Edit 2022-03-15: there is some discussion on where log_format
should be set. The documentation clearly says that it needs to be in the http
context: http://nginx.org/en/docs/http/ngx_http_log_module.html#log_format
If you put log_format
in the server
context, nginx will fail to load the config: nginx: [emerg] "log_format" directive is not allowed here in <path>:<line>
(tested with nginx 1.20 on ubuntu 18.04)