Регистрация данных POST от $ request_body - PullRequest
56 голосов
/ 09 февраля 2011

У меня есть моя конфигурация конфигурации для обработки множества запросов GET, которые отображают пиксели, которые прекрасно работают для обработки аналитики и разбора строк запроса для регистрации. С дополнительным сторонним потоком данных мне нужно обработать POST-запрос к заданному URL-адресу, который имеет JSON в ожидаемом формате регистрации внутри его тела запроса. Я не хочу использовать вторичный сервер с proxy_pass и просто хочу записать весь ответ в связанный файл журнала, например, что он делает с запросами GET. Фрагмент кода, который я использую, выглядит следующим образом:

GET-запрос (который прекрасно работает):

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

Вот то, что я пытаюсь сделать: POST-запрос (который не работает):

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 дает мне страницу 404 не найдена.

Тогда я попробовал:

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

Керлинг curl http://myurl/bk.gif -d name=example дает мне 405 Not Allowed.

Моя текущая версия nginx/0.7.62. Любая помощь в правильном направлении очень ценится! Спасибо!

UPDATE Так что теперь мой пост выглядит так:

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

Он правильно регистрирует данные поста, но возвращает 404 на конце запроса. Если я изменю код выше, чтобы вернуть 200, например, так:

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

Затем он возвращает 200 правильно, но больше не записывает данные записи.

ДРУГОЕ ОБНОВЛЕНИЕ Кинда нашла рабочее решение. Надеюсь, это поможет другим на их пути.

Ответы [ 6 ]

66 голосов
/ 19 сентября 2011

Это решение работает как шарм (обновлено в 2017 году, чтобы учесть, что log_format должен быть в http-части конфигурации nginx):

log_format postdata $request_body;

server {
    # (...)

    location = /post.php {
       access_log  /var/log/nginx/postdata.log  postdata;
       fastcgi_pass php_cgi;
    }
}

Я думаю, уловка заставляет nginx поверить, что вы вызовете скрипт cgi.

34 голосов
/ 26 декабря 2012

Попробуйте echo_read_request_body.

" echo_read_request_body ... Явно читает тело запроса, так что переменная $ request_body всегда будет иметь непустые значения (если тело не настолько велико, что оно было сохранено Nginx во локальном временном файле ). "

location /log {
  log_format postdata $request_body;
  access_log /mnt/logs/nginx/my_tracking.access.log postdata;
  echo_read_request_body;
}
11 голосов
/ 05 июля 2011

Хорошо. Итак, наконец я смог записать данные постов и вернуть 200. Это своего рода хакерское решение, которым я не горжусь, которое в основном переопределяет естественное поведение для error_page, но мой неопытность по временным шкалам nginx plus привела меня к этому решению :

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

Теперь, согласно этой конфигурации, может показаться, что проход прокси-сервера будет возвращать 200 все время. Иногда я получал 500, но когда я добавлял error_log, чтобы увидеть, что происходит, все мои данные request_body были там, и я не мог увидеть проблему. Я поймал это и написал в тот же журнал. Поскольку nginx не нравится то же имя для переменной отслеживания, я просто использовал my_tracking_2 и записал в тот же журнал, что и когда он возвращает 200. Определенно, это не самое элегантное решение, и я приветствую любое лучшее решение. Я видел модуль post, но в моем сценарии я не смог перекомпилировать из исходного кода.

6 голосов
/ 21 февраля 2013

FWIW, у меня этот конфиг работает:

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;
}
4 голосов
/ 13 января 2015

nginx формат журнала взят здесь: http://nginx.org/en/docs/http/ngx_http_log_module.html

не нужно устанавливать ничего лишнего

работал для меня на GET и 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;
    }
}

просто изменить upstream_ip и upstream_port

0 голосов
/ 14 июня 2012

У меня была похожая проблема.GET-запросы работали, и их (пустые) тела запросов записывались в файл журнала.POST-запросы завершились неудачно с 404. Немного поэкспериментировав, я обнаружил, что все POST-запросы терпели неудачу.Я нашел сообщение на форуме с просьбой о запросах POST , и решение там сработало для меня.Это решение?Добавьте строку proxy_header прямо перед строкой proxy_pass, точно так же, как в примере ниже.

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

(это с nginx 1.2.1, что стоит).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...