2011-12-21 196 views
19

我有两个iKaaro实例在端口8080和9080上运行,其中9080实例是只读的。nginx proxy_pass基于请求方法是POST,PUT还是DELETE

我不确定如何使用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; 

感谢

+0

你能解释一下这个问题好一点?你尝试过这种设置吗?你有任何错误(哪些)? – kikito 2011-12-21 16:22:46

回答

33

我只是做了一个快速测试,而这个工作对我来说:

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; 
    } 
    } 
} 
+1

这是更短 – khinester 2011-12-21 20:22:55

+1

它也不会依赖于任何第三方模块 – kolbyjack 2011-12-21 20:37:48

+2

不为我上的nginx 1.7.6 .. – 2015-01-31 16:36:38

10

我假设你得到了基础知识到位。 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”选项中的“邪恶”行为。如果您在“if”或“limit_except”块内设置了一个指令,它可能不在其外部,并且类似地,外部设置的内容可能会被继承。所以你必须看两种方法如何默认继承,或者不是,视情况而定。

If is Evil页面上列出的所有潜在问题均适用于此处的“if”和“limit_except”。基于Lua的脚本编写方法将避免该页面上提出的许多潜在缺陷。

祝你好运!

+0

谢谢你这是有道理的。 – khinester 2011-12-21 20:20:32

+0

感谢您的详细解释,所以我需要注意IfiSEvil是否需要运行其他指令。 我可能需要我还需要包括特定的URL,例如位置〜*“(登录| NEW_CONTENT)” {...但我会揣摩出来,回到这里与我的nginx.conf文件,看看是否它可以得到改善。 – khinester 2011-12-22 11:01:08

+0

尝试按特定问题分开查询。我假设在你有三个选项的情况下,关于如何基于请求方法的Nginx路由请求的具体问题已经得到了详尽的解答。你可以直接使用“if”,也可以使用“limit_except”这个if语句来记住潜在的问题,或者使用脚本方法,比如给出的Lua例子来避免这些问题。您可能需要考虑接受给出的答案中的一个或另一个,并询问是否存在其他问题。 – Dayo 2011-12-22 13:28:36

1

万一有人找一种方式来简单地使被请求方法的条件下,语法是:

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

..although工作,我不得不提,那使用IF在配置不推荐nginx团队:http://wiki.nginx.org/IfIsEvil – Sych 2015-02-04 20:02:53

1

我会推荐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套接字,但将读取的流量发送到本地FastCGI UNIX套接字。

相关问题