web-dev-qa-db-fra.com

Journalisation POST données de $ request_body

J'ai ma configuration de configuration pour gérer un tas de requêtes GET qui rendent les pixels qui fonctionnent correctement pour gérer les analyses et analyser les chaînes de requête pour la journalisation. Avec un flux de données tiers supplémentaire, je dois gérer une demande POST) à une URL donnée qui contient JSON dans un format de connexion attendu à l'intérieur de son corps de demande. Je ne souhaite pas utiliser serveur secondaire avec proxy_pass et je veux juste enregistrer toute la réponse dans un fichier journal associé, comme pour les demandes GET. Un extrait de code que j'utilise ressemble à ce qui suit:

Demande GET (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: POST request (qui ne fonctionne pas):

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 donne une page 404 non trouvée.

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://myurl/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!

[~ # ~] mettre à jour [~ # ~] Alors maintenant, mon message 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 correctement les données de publication, mais renvoie 404 à la fin des demandeurs. Si je modifie le code ci-dessus pour renvoyer un 200 comme suit:

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

Puis il retourne le 200 correctement, mais n'enregistre plus les données de publication.

NE AUTRE MISE À JOUR Kinda a trouvé une solution de travail. Espérons que cela puisse aider les autres sur leur chemin.

58
Chris Barretto

Cette solution fonctionne à merveille (mise à jour en 2017 pour tenir compte du fait que log_format doit figurer 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 le truc consiste à faire croire à nginx que vous appellerez un script cgi.

66
ahofmann

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 (sauf si le corps est si gros qu'il a été 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;
}
35
boqapt

D'accord. Alors, finalement, j'ai pu enregistrer les données de publication et renvoyer 200. C'est une sorte de solution compliquée dont je ne suis pas fier, qui surpasse fondamentalement le comportement naturel de error_page, mais mon inexpérience de 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 laissez-passer par procuration renverrait un 200 tout le temps. Parfois, j'obtenais 500, mais quand j'ai jeté dans un error_log pour voir ce qui se passait, toutes mes données de request_body étaient là et je ne pouvais pas voir un problème. J'ai donc compris cela et écrit dans le 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 toute solution meilleure est la bienvenue. J'ai vu le module de publication, mais dans mon scénario, je ne pouvais pas recompiler à partir des sources.

11
Chris Barretto

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

nginx format du journal pris à partir d'ici: http://nginx.org/en/docs/http/ngx_http_log_module.html

pas besoin d'installer quoi que ce soit d'extra

a travaillé pour moi pour GET et POST requêtes:

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

il suffit de changer upstream_ip et upstream_port

4
NoamG

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 demandes POST ont échoué avec un 404. En expérimentant un peu, j'ai constaté que toutes les demandes POST échouaient. J'ai trouvé un message sur le forum qui posait des questions sur POST demandes et la solution qui fonctionnait pour moi. Cette solution? Ajoutez une ligne proxy_header Juste avant la ligne proxy_pass, Exactement comme celle de 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 que cela vaut.)

0
epicsmile

La solution ci-dessous était le meilleur format que j'ai trouvé.

log_format postdata escape=json '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $bytes_sent '
                       '"$http_referer" "$http_user_agent" "$request_body"';
server {
        listen 80;

        server_name api.some.com;

        location / {
         access_log  /var/log/nginx/postdata.log  postdata;
         proxy_pass      http://127.0.0.1:8080;
        }

}

Pour cette entrée

curl -d '{"key1":"value1", "key2":"value2"}' -H "Content-Type: application/json" -X POST http://api.deprod.com/postEndpoint

Générer ce bon résultat

201.23.89.149 -  [22/Aug/2019:15:58:40 +0000] "POST /postEndpoint HTTP/1.1" 200 265 "" "curl/7.64.0" "{\"key1\":\"value1\", \"key2\":\"value2\"}"
0
Bruno