2011-02-08 24 views
44

Tengo mi configuración de configuración para manejar un montón de solicitudes GET que rinden píxeles que funcionan bien para manejar el 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 un código que estoy usando el siguiente aspecto:

petición 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í es un poco lo que yo estoy tratando de hacer: solicitud POST (que hace 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 encontrado.

Luego 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 una 405 Not Allowed.

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

ACTUALIZACIÓN Así que ahora mi puesto 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; } 

es que lo almacena los datos enviados correctamente, pero devuelve un 404 sobre los solicitantes fin. Si cambio el código anterior para devolver un 200, 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; 
    return 200; 
} 
location /dummy { set $test 0; } 

continuación se retorna el 200 correctamente, pero ya no registra los datos de envío.

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

+0

has llegado a ninguna parte con esto? Estoy frente a un problema similar. –

Respuesta

45

Esta solución funciona como un encanto (actualizado en 2017 en honor a ese log_format tiene que 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á haciendo nginx creen que va a llamar una secuencia de comandos cgi.

+10

Tengo que mover "log_format postdata $ request_body;" a la parte del servidor porque nginx dice que "la directiva log_format no está permitida aquí" –

+4

Esta es la respuesta correcta. Excepto, como mencionó @OlegNeumyvakin, tuve que mover la parte 'log_format'. Pero en mi caso, tuve que moverlo dentro del bloque "http", en lugar de dentro del bloque "servidor", para que funcione. Pero esto hizo el truco! – Matt

+1

@OlegNeumyvakin & Matt: He puesto sus comentarios en la respuesta misma (pendiente de revisión en este momento). ¡Gracias! –

8

Ok. 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 recompilar desde la fuente.

+1

La solución que se le ocurrió es muy similar a la respuesta aceptada aquí: http://stackoverflow.com/questions/17609472/really-logging-the-post-request-body-instead-of-with-nginx Desde que nginx doesn Analizar el cuerpo a menos que se envíe a un proxy o a un servidor de cgi rápido, el proxy a sí mismo funciona. – turtlemonvh

+0

usamos una solución similar, por proxy_pass la solicitud POST a la otra ubicación. – arganzheng

0

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, encontré que todas las solicitudes POST estaban fallando. Encontré un forum posting asking about POST requests y la solución allí funcionó para mí. ¿Esa solución? Agregue una línea proxy_header justo antes de la línea proxy_pass, exactamente como en el 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 para lo que vale la pena.)

29

Try 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; 
} 
+3

Esto funcionó mejor que la respuesta aceptada, ya que no necesitaba instalar fastcgi – Fluffy

+4

@Fluffy sí, pero necesita 'echo_read_request_body' para instalarse ... – NoamG

+3

instalar por' apt-get install nginx-full' – firelynx

3

Fwiw, esta configuración que 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; 
} 
+0

Esto funcionó para mí también. ¡Aclamaciones! – Rafay

4

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

hay necesidad de instalar nada extra

trabajó para mí para GET y POST solicitudes:

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

acaba de cambiar upstream_ip y upstream_port