Enregistrement des données POST à ​​partir de $ request_body

J’ai ma configuration de configuration pour gérer un tas de requêtes GET qui rendent les pixels qui fonctionnent bien pour gérer les parsings et parsingr les chaînes de requêtes pour la journalisation. Avec un stream de données tiers supplémentaire, je dois traiter une requête POST vers une URL donnée qui a JSON dans un format loggable prévu à l’intérieur de son corps de requête. Je ne veux pas utiliser un serveur secondaire avec proxy_pass et je veux simplement consigner la réponse complète dans un fichier journal associé, comme avec les requêtes GET. Un extrait de code que j’utilise ressemble à ceci:

GET request (qui fonctionne très 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; } 

Voici un peu ce que j’essaie de faire: Demande POST (qui ne fonctionne pas):

 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 me donne une page 404 introuvable.

Puis j’ai essayé:

 location /bk.gif { empty_gif; log_format bk_tracking $request_body; access_log /mnt/logs/nginx/bk.access.log bk_tracking; } 

Curling curl http://img.zgserver.com/logging/bk.gif -d name=example me donne un 405 Not Allowed .

Ma version actuelle est nginx/0.7.62 . Toute aide dans la bonne direction est très appréciée! Merci!

MISE À JOUR Alors maintenant, mon article ressemble à ceci:

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

Il enregistre les données de publication correctement, mais retourne un 404 à la fin des demandeurs. Si je change le code ci-dessus pour retourner un 200 comme ça:

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

Ensuite, il renvoie le 200 correctement, mais n’enregistre plus les données de publication.

Une autre mise à jour Kinda a trouvé une solution de travail. J’espère que cela peut aider les autres sur leur chemin.

Cette solution fonctionne comme un charme (mise à jour en 2017 pour tenir compte du fait que log_format doit être dans la partie http de la configuration de nginx):

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

Je pense que l’astuce consiste à faire croire à nginx que vous allez appeler un script cgi.

Essayez echo_read_request_body.

” echo_read_request_body … Lit explicitement le corps de la requête afin que la variable $ request_body ait toujours des valeurs non vides (à moins que le corps soit trop gros pour être enregistré par Nginx dans un fichier temporaire local).”

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

D’accord. Donc, finalement, j’ai pu enregistrer les données post et retourner un 200. C’est une sorte de solution de piratage dont je ne suis pas fier, qui remplace le comportement naturel de error_page, mais mon inexpérience des délais nginx plus m’a conduit à cette 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; } 

Maintenant, selon cette configuration, il semblerait que le passage de proxy renverrait un 200 tout le temps. Parfois, je recevais 500 mais quand j’ai jeté un journal des erreurs pour voir ce qui se passait, toutes mes données request_body étaient là et je ne pouvais pas voir de problème. Alors j’ai attrapé ça et j’ai écrit au même journal. Puisque nginx n’aime pas le même nom pour la variable de suivi, j’ai simplement utilisé my_tracking_2 et écrit dans le même journal que lorsqu’il renvoie un 200. Ce n’est certainement pas la solution la plus élégante et je me réjouis de toute meilleure solution. J’ai vu le module de post, mais dans mon scénario, je ne pouvais pas recomstackr à partir des sources.

Format de journal nginx pris ici: http://nginx.org/en/docs/http/ngx_http_log_module.html

pas besoin d’installer quoi que ce soit en plus

a travaillé pour moi pour les requêtes GET et 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; } } 

changez simplement upstream_ip et upstream_port

FWIW, cette config a fonctionné pour moi:

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

J’avais un problème similaire. Les requêtes GET ont fonctionné et leurs corps de requête (vides) ont été écrits dans le fichier journal. Les requêtes POST ont échoué avec un 404. En expérimentant un peu, j’ai constaté que toutes les requêtes POST échouaient. J’ai trouvé un post sur le forum demandant des requêtes POST et la solution qu’il y avait pour moi. Cette solution? Ajoutez une ligne proxy_header juste avant la ligne proxy_pass , exactement comme dans l’exemple ci-dessous.

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

(Ceci est avec nginx 1.2.1 pour ce qu’il vaut.)