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