Как я могу управлять телом 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

person Jesse    schedule 01.04.2014    source источник


Ответы (3)


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

location / {
                #host and port to fastcgi server
                default_type text/html;
                set $URL "http://$http_host$request_uri";
                access_by_lua_file /home/lua/cache.lua;
                proxy_pass http://$target;
                -------
                ---------

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

if ngx.req.get_method() == "POST" then
    -- check if request method is POST 
    -- implement your logic 
    return
end
person Prashant Gaur    schedule 01.04.2014

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

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

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

person vdg    schedule 02.04.2014
comment
Спасибо, я действительно добавил код, который опубликовал выше, в конец файла, о котором вы упомянули, когда заметил, что access_by_lua_file уже вызывается. - person Jesse; 02.04.2014

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

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

person Dimitar Atanasov    schedule 26.03.2015
comment
Ссылка не работает. : / - person qräbnö; 08.07.2020