Nginx proxy_pass на основе метода запроса POST, PUT или DELETE

У меня есть два экземпляра iKaaro, запущенных на портах 8080 и 9080, где экземпляр 9080 доступен только для чтения.

Я не уверен, как использовать nginx, например, если метод запроса POST, PUT, DELETE, тогда отправьте на экземпляр записи (8080), иначе отправьте экземпляр 9080.

Я сделал что-то, используя местоположение, используя регулярное выражение, но это неверно.

Из http://wiki.nginx.org/HttpLuaModule я вижу, что есть "константы метода HTTP", которые можно вызывать, поэтому правильно ли добавить местоположение block as:

location ~* "(ngx.HTTP_POST|ngx.HTTP_DELETE|ngx.HTTP_PUT)" {
    proxy_pass http://127.0.0.1:8080;

Спасибо

Ответ 1

Я просто сделал быстрый тест, и это сработало для меня:

server {
  location / {
    # This proxy_pass is used for requests that don't
    # match the limit_except
    proxy_pass http://127.0.0.1:8080;

    # For requests that *aren't* a PUT, POST, or DELETE,
    # pass to :9080
    limit_except PUT POST DELETE {
      proxy_pass http://127.0.0.1:9080;
    }
  }
}

Ответ 2

Я предполагаю, что у вас есть основы. I.E., вы установили Lua 5.1 или, еще лучше, LuaJIT 2.0 на свой сервер, скомпилировали Nginx с модулем ngx_lua и настроили ngx_lua по мере необходимости.

С этим на месте, это выполнит задание:

location /test {
    content_by_lua '
        local reqType = ngx.var.request_method
        if reqType == ngx.HTTP_POST 
            OR reqType == ngx.HTTP_DELETE 
            OR reqType == ngx.HTTP_PUT 
        then
            res = ngx.location.capture("/write_instance")
        else
            res = ngx.location.capture("/read_instance")
        end
        ngx.say(res.body)
    ';
}
location /write_instance {
    internal;
    proxy_pass http://127.0.0.1:8080;
}
location /read_instance {
    internal;
    proxy_pass http://127.0.0.1:9080;
}

UPDATE

Я подумал, что, возможно, вы использовали Lua в большей степени. Пример ниже также будет работать по тому же принципу, что и limit_except.

location /test {
    if ($request_method !~* GET) {
        # For Write Requests
        proxy_pass http://127.0.0.1:8080;
    }
    # For Read Requests
    proxy_pass http://127.0.0.1:9080;
}

Блок "if" и "limit_except" эффективно создает блок вложенного местоположения, и как только условие будет соответствовать, будет выполнен только обработчик содержимого ( "proxy_pass" ) созданного таким образом внутреннего блока местоположения.

Не совсем понятно, почему, если иногда говорят, что это "зло", но в этом случае "злое" поведение, обычное для "if" и "limit_except", может быть именно тем, что вы хотите.

Итак, вы можете выбрать три варианта!

Обратите внимание, что вам нужно будет следить за тем, чтобы вы не укусили поведение "злого" с любыми опциями "if" или "limit_except", если вам нужно установить любые другие директивы.

I.E., если вы устанавливаете директиву внутри блока "if" или "limit_except", она может быть неактивна вне ее, и аналогично, что-то, установленное снаружи, может быть унаследовано внутри. Таким образом, вы должны смотреть, как по умолчанию наследуются, или нет, в зависимости от случая, с обоими подходами.

Все потенциальные проблемы, перечисленные на странице If is Evil, применимы в равной степени к "if" и "limit_except" здесь. Подход, основанный на Lua, позволит избежать многих из этих потенциальных ошибок, предложенных на этой странице.

Удачи!

Ответ 3

В случае, если кто-то ищет способ просто создать условия по методу запроса, синтаксис следующий:

if ($request_method = DELETE ) {
   . . . 
}

Ответ 4

Я бы рекомендовал функцию отображения nginx. Это выходит за пределы вашего блока местоположения:

map $request_method $destination {
    default 8080;
    PUT 9080;
    POST 9080;
    DELETE 9080;
}

Затем в вашем блоке местоположения:

proxy_pass http://127.0.0.1:$destination

Это тоже все регулярные выражения, поэтому вы можете делать такие вещи, как:

map $request_method $cookie_auth $destination {
    default 8080;
    "^POST " 9080;
    "^PUT someAuthCookieValue" 9080;
}

Плюс это позволяет избежать использования, если вообще. Это довольно здорово. Я использовал его, чтобы направлять весь трафик записи в кластере WordPress на один сокет FastCGI TCP на удаленном node, но отправлять трафик чтения в локальный сокет FastCGI UNIX.