nginx proxy_pass в зависимости от того, является ли метод запроса POST, PUT или DELETE - PullRequest
21 голосов
/ 21 декабря 2011

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

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

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

С http://wiki.nginx.org/HttpLuaModule Я вижу, что есть «константы метода HTTP», которые можно вызвать, поэтому правильно добавить блок местоположения следующим образом:

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

Спасибо

Ответы [ 4 ]

35 голосов
/ 21 декабря 2011

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

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

    limit_except PUT POST DELETE {
      # For requests that *aren't* a PUT, POST, or DELETE,
      # pass to :9080
      proxy_pass http://127.0.0.1:9080;
    }
  }
}
11 голосов
/ 21 декабря 2011

Полагаю, вы получили основы. То есть вы установили 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 позволит избежать многих из этих потенциальных ловушек, как предлагается на этой странице.

Удачи!

1 голос
/ 24 апреля 2017

Я бы порекомендовал функцию карты 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 на один TCP-сокет FastCGI на удаленном узле, но отправлял трафик чтения на локальный UNIX-сокет FastCGI.

1 голос
/ 30 июня 2014

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

if ($request_method = DELETE ) {
   . . . 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...