nginx: хранение данных POST в PostgreSQL

#postgresql #rest #nginx #openresty

#postgresql #rest #nginx #openresty

Вопрос:

Сервер nginx предоставляет простой интерфейс REST, используя экземпляр PostgreSQL в качестве серверной части. Nginx должен вставить данные POST (уже в формате JSON) в таблицу базы данных. К сожалению, $request_body файл, содержащий данные POST, заполняется nginx только на fastcgi_pass , proxy_pass , …

ngx_form_input также не помогает, поскольку он ожидает, что данные POST будут представлены в формате ключ-значение. Я пробовал ngx_echo, но это приводит к внутренней ошибке сервера:

 location ~ "^/api/v1/dummy/$" {
    auth_basic              "Restricted";
    auth_basic_user_file    /usr/local/etc/nginx/.htpasswd;

    if ($request_method != POST) {
        return 405;
    }

    client_max_body_size    100k;
    client_body_buffer_size 100k;

    echo_read_request_body;

    postgres_pass       postgresql;
    postgres_escape     $json =$request_body;

    postgres_query      POST "INSERT INTO mytable (data) VALUES ('$json')";
    postgres_rewrite    POST changes    201;
    postgres_rewrite    POST no_changes 204;
}
  

Похоже, что ngx_echo не работает вместе с ngx_postgres. Существуют ли какие-либо другие способы получения данных тела запроса?

Ответ №1:

Обе директивы echo_read_request_body и postgres_pass работают на этапе содержимого. В этом случае будет работать только один модуль.

Проблема здесь в том, что nginx асинхронен по своей природе. Nginx может инициировать восходящее соединение до получения полного тела запроса.

Используя OpenResty, вы можете заставить nginx прочитать все тело запроса с помощью lua_need_request_body. Позаботьтесь о client_body_buffer_size и client_max_body_size . Включить пустое rewrite_by_lua* .

Другое возможное решение — написать код Lua, например, внутри set_by_lua_block и прочитать полное тело запроса, имейте в виду, что оно может быть помещено в буфер в файл, используйте ngx.req.get_body_file для проверки.

Комментарии:

1. В конечном счете, это единственное, что работает. Я добавил rewrite_by_lua_block для получения тела запроса с помощью ngx.req.read_body() и ngx.req.get_body_data() . Спасибо за разъяснение о том, почему оба модуля не могут использоваться одновременно.

Ответ №2:

Я согласен с Александром Альтшулером. Nginx не поддерживает захват request_body на этапе перезаписи, на котором выполняется postgres_escape директива.

Я модифицировал модуль ngx_postgres в моей ветке GitHub, для захвата тела запроса. Но мой запрос на извлечение вряд ли будет принят.

В этой ветке добавлена функция отслеживания запросов POST. Вы можете сохранять запросы к базе данных PostgreSQL, например, используя такую конфигурацию в этой ветке

 location /dlr/sms
{
    allow all;
    postgres_escape_request_body on;
    postgres_pass     database;
    postgres_query    POST      "SELECT table2sms.treat_sms_dlr('$request_body')";
    postgres_rewrite  POST      changes 200;
    postgres_rewrite  POST      no_changes 400;
    postgres_output   value;
}