Как я могу манипулировать телом JSON запроса POST, используя Nginx и Lua?

Я делаю проверку концепции, чтобы продемонстрировать, как мы можем реализовать 3scale в нашем стеке. В одном примере я хочу сделать некоторые манипуляции с телом POST- запроса, чтобы создать фасад API, который отображает то, что может быть устаревшим форматом API, на новый внутренний. Например. изменить что-то вроде

{ "foo" : "bar" , "deprecated" : true }

в

{ "FOO" : "bar" }

Модуль Lua документирует content_by_lua, который выглядит как соответствующий метод

Не используйте эту директиву и другие директивы обработчика содержимого в одном месте. Например, эта директива и директива proxy_pass не должны использоваться в одном месте.

Насколько я понимаю, content_by_lua - это обработчик контента, такой как proxy_pass, только один из которых можно использовать для каждого местоположения.

Я не думаю, что есть какой-либо способ удалить proxy_pass, так как это основа работы прокси, поэтому можно ли захватить запрос в отдельном месте, использовать content_by_lua, затем перейти в местоположение, реализующее proxy_pass, или есть другой метод, такой как rewrite_by_lua, который более подходит?


Если это поможет кому-то еще, я добавил следующую функцию (мой первый бит Lua), которая удаляет user_key параметр, который 3scale требует для авторизации, но недопустим для нашего API, если переадресован на:

function remove_user_key()
  ngx.req.read_body()
  -- log the original body so we can compare to the new one later
  local oldbody = ngx.req.get_body_data()
  log(oldbody)
  -- grab the POST parameters as a table
  local params = ngx.req.get_post_args()

  -- build up the new JSON string
  local newbody = "{"

   for k,v in pairs(params) do
     -- add all the params we want to keep
     if k ~= "user_key" then
        log("adding"..k.." as "..v)
        newbody = newbody..'"'..k..'":"'..v..'",'
     else 
        log("not adding user_key")
     end
   end
  --remove the last trailing comma before closing this off
  newbody = string.sub(newbody, 0, #newbody-1)
  newbody = newbody.."}"

  ngx.req.set_body_data(newbody)
  log(newbody)
end

if ngx.req.get_method() == "POST" then
  remove_user_key()
end

3 ответа

Решение

Я предложу вам использовать access_by_lua
в nginx.conf

место нахождения / {
                # хост и порт для fastcgi сервера
                default_type text/html;
                установить $URL "http://$http_host$request_uri";
                access_by_lua_file /home/lua/cache.lua;
                proxy_pass http://$target;
                -------
                ---------

в файле cache.lua вы можете сделать что-то вроде:

если ngx.req.get_method() == "POST", то
    - проверьте, является ли метод запроса POST 
    - реализовать свою логику 
    вернуть
конец

Добавим к тому, что Prashant уже упоминал: когда вы загружаете свои файлы конфигурации Nginx из 3scale, вы заметите, что в них включен файл Lua. Этот файл уже вызывается из access_by_lua_file,

Этот файл, по моему мнению, будет лучшим местом для добавления кода манипуляции с телом. Он будет выполняться для каждого запроса до proxy_pass на ваш сервер API отправлено.

Кроме того, это действительно хорошая статья в блоге о том, как выполнить различные преобразования ваших запросов с помощью Lua внутри Nginx:

Недавно мне пришлось манипулировать апстримом на основе значения JSON в пост-запросе, и я нашел это полезным: NGINX LUA и JSON

Это базовая конфигурация, но дает представление о том, как это сделать.

Другие вопросы по тегам