I have my config setup to handle a bunch of GET requests which render pixels that work fine to handle analytics and parse query strings for logging. With an additional third party data stream, I need to handle a POST request to a given url that has JSON in an expected loggable format inside of it's request body. I don't want to use a secondary server with proxy_pass
and just want to log the whole response into an associated log file like what it does with GET requests. A snippet of some code that I'm using looks like the following:
GET request (which works great):
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; }
Here is kinda what I am trying to do: POST request (which does not work):
location /bk { log_format bk_tracking $request_body; access_log /mnt/logs/nginx/bk.access.log bk_tracking; }
Curling curl http://myurl/bk -d name=example
gives me a 404 page not found.
Then I tried:
location /bk.gif { empty_gif; log_format bk_tracking $request_body; access_log /mnt/logs/nginx/bk.access.log bk_tracking; }
Curling curl http://myurl/bk.gif -d name=example
gives me a 405 Not Allowed
.
My current version is nginx/0.7.62
. Any help in the right direction is very much appreciated! Thanks!
UPDATE So now my post looks like this:
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; }
It is logging the post data correctly, but returns a 404 on the requesters end. If I change the above code to return a 200 like so:
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; }
Then it return the 200
correctly, but no longer records the post data.
ANOTHER UPDATE Kinda found a working solution. Hopefully this can help other on their way.
By default, NGINX does not log POST data since it can be bulky and take up disk space. However, sometimes you may need to log POST data for debugging purposes.
You can log POST request details by using dumpio module for Apache, which allows logging of HTTP request body.
This solution works like a charm (updated in 2017 to honor that log_format needs to be in the http part of the nginx config):
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.
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; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With