Registrando datos de POST desde $ request_body

Tengo mi configuración de configuración para manejar un montón de solicitudes GET que rinden píxeles que funcionan bien para manejar análisis y analizar cadenas de consulta para el registro. Con una secuencia de datos de terceros adicional, necesito manejar una solicitud POST a una url determinada que tiene JSON en un formato de conexión esperado dentro de su cuerpo de solicitud. No quiero usar un servidor secundario con proxy_pass y solo quiero registrar toda la respuesta en un archivo de registro asociado como lo que hace con las solicitudes GET. Un fragmento de código que estoy usando tiene el siguiente aspecto:

Solicitud GET (que funciona muy bien):

 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; } 

Aquí hay algo que bash hacer: solicitud POST (que no funciona):

 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 me da una página 404 no encontrada.

Entonces probé:

 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 me da un 405 Not Allowed .

Mi versión actual es nginx/0.7.62 . ¡Cualquier ayuda en la dirección correcta es muy apreciada! ¡Gracias!

ACTUALIZAR Ahora mi publicación es así:

 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; } 

Está registrando los datos de la publicación correctamente, pero devuelve un 404 en el extremo de los solicitantes. Si cambio el código anterior para devolver un 200, haga lo siguiente:

 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; } 

Luego devuelve el 200 correctamente, pero ya no registra los datos de la publicación.

OTRA ACTUALIZACIÓN Encontró una solución de trabajo. Con suerte, esto puede ayudar a otros en su camino.

Esta solución funciona como un amuleto (actualizado en 2017 para reconocer que log_format debe estar en la parte http de la configuración de nginx):

 log_format postdata $request_body; server { # (...) location = /post.php { access_log /var/log/nginx/postdata.log postdata; fastcgi_pass php_cgi; } } 

Creo que el truco está en hacer que nginx crea que llamarás a un script cgi.

Prueba echo_read_request_body.

” echo_read_request_body … Lee explícitamente el cuerpo de la solicitud para que la variable $ request_body siempre tenga valores no vacíos (a menos que el cuerpo sea tan grande que haya sido guardado por Nginx en un archivo temporal local).”

 location /log { log_format postdata $request_body; access_log /mnt/logs/nginx/my_tracking.access.log postdata; echo_read_request_body; } 

De acuerdo. Así que finalmente pude registrar los datos de la publicación y devolver 200. Es una especie de solución hacky de la que no estoy orgulloso, que básicamente anula el comportamiento natural de error_page, pero mi inexperiencia de nginx plus timelines me lleva a esta solución :

 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; } 

Ahora, según esa configuración, parecería que el pase de proxy devolvería un 200 todo el tiempo. De vez en cuando obtenía 500 pero cuando ingresé un error_log para ver qué estaba pasando, todos mis datos de request_body estaban allí y no pude ver un problema. Así que atrapé eso y escribí en el mismo registro. Como a nginx no le gusta el mismo nombre para la variable de seguimiento, acabo de usar my_tracking_2 y escribí en el mismo registro que cuando devuelve 200. Definitivamente no es la solución más elegante y acepto cualquier solución mejor. He visto el módulo de publicación, pero en mi caso, no pude recomstackr desde la fuente.

formato de registro nginx tomado de aquí: http://nginx.org/en/docs/http/ngx_http_log_module.html

no es necesario instalar nada extra

trabajado para mí para las solicitudes GET y 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; } } 

solo cambie upstream_ip y upstream_port

FWIW, esta configuración funcionó para mí:

 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; } 

Tuve un problema similar. Las solicitudes GET funcionaron y sus cuerpos de solicitud (vacíos) se escribieron en el archivo de registro. Las solicitudes POST fallaron con un 404. Experimentando un poco, descubrí que todas las solicitudes POST fallaban. Encontré una publicación en el foro preguntando sobre las solicitudes POST y la solución que allí funcionó. ¿Esa solución? Agregue una línea proxy_header justo antes de la línea proxy_pass , exactamente como la del ejemplo a continuación.

 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; } } 

(Esto es con nginx 1.2.1 por lo que vale).