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.