2012/6/8 刘鑫 <marc...@gmail.com>:
> 但是下面的代码会有问题:
>
你的 Lua 代码中有几处明显的问题,请见下面的评注:
>
> server {
> server_name _;
> location / {
> # proxy_pass http://localhost:8080;
> set $is_dynamic '';
> set_by_lua $is_dynamic '
> method = ngx.req.get_uri_args()["method"];
> if ngx.var.request_method == "GET" and method ~= nil then
> return "yes";
> elseif ngx.var.request_method == "PUT" then {
首先,您这里的 if /elseif 的语法有问题,then 后面不应跟 { ... } 花括号,这不是合法的 Lua 语法。我这里可以得到这样的错误消息:
[error] ... failed to load Lua inlined code: [string
\"set_by_lua\"]:5: unexpected symbol near '{'
> local m = ngx.re.match(ngx.var.remote_addr,
> "^10\\.0\\.0\\.[0-9]+$");
其次,这里的 \ 转义序列是有问题的,因为你使用的是 set_by_lua,所以 Lua 代码本身是一个 nginx 字符串,所以 \
需要转义一次,而 Lua 代码内你又使用了 "..." 这个 Lua 字符串常量,所以 \ 还需要再转义一次,因此正确的写法是:
local m = ngx.re.match(ngx.var.remote_addr, "^10\\\\.0\\\\.0\\\\.[0-9]+$");
如果这个看得过于复杂,也可以换用 [[...]] 的形式,这样只需要为 nginx 字符串的语法转义一次 \:
local m = ngx.re.match(ngx.var.remote_addr, [[^10\\.0\\.0\\.[0-9]+$]]);
如果你的 Lua 代码是放在外部 .lua 文件中的话,就不再需要为 nginx 字符串语法对 \ 进行额外转义了。关于此问题的更多讨论,可以见:
http://wiki.nginx.org/HttpLuaModule#Special_PCRE_Sequences
一般地,对于这种简单的模式匹配,使用 Lua 标准的 string.find 或者 string.match 会更加高效和简便一些 :)
> if m == nil then
> ngx.exit(401);
再次,ngx.exit 在 set_by_lua 的上下文中是不可用的,见它的文档中的"context"列表:
http://wiki.nginx.org/HttpLuaModule#ngx.exit
建议换用 rewrite_by_lua 或者 access_by_lua :)
Best regards,
-agentzh
P.S. 同时抄送给了 openresty 邮件列表 https://groups.google.com/group/openresty
,以便其他用户也可以参考一下,呵呵 :)
--
邮件自: 列表“openresty”,专用于技术讨论!
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com
详情: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
建议: 提问的智慧 http://wiki.woodpecker.org.cn/moin/AskForHelp
教程: http://agentzh.org/misc/nginx/agentzh-nginx-tutorials-zhcn.html
啊,感谢你的详细讲解,那个语法错误刚刚我也发现了,而且我测试了一下,用allow/deny不足以区分来自proxy的访问,目前我的测试代码是这样的:location / {content_by_lua 'local remote_ip = ngx.req.get_headers()["X-Real-IP"];if remote_ip == nil thenremote_ip = ngx.var.remote_addr;end;local m = ngx.re.match(remote_ip, "^192\\.168\\.56\\.[0-9]+$");if m ~= nil thenngx.say(remote_ip);elsengx.exit(403);end;';}我现在把测试代码改一下,让它更接近实际场景:)
- 都可以的, openresty 里有 interl 模式的完全跳转,,纯内部数据流通,很爽脆的!
- 嗯嗯嗯,俺对内忽悠没有成功,怎么外边儿的旧金山人都开始研究了?!
- 推荐使用 tengine+openrsty 进行多重优化!
> 在 2012年6月8日 下午2:49,刘鑫 <marc...@gmail.com>写道:
>
>> 啊,感谢你的详细讲解,那个语法错误刚刚我也发现了,而且我测试了一下,用allow/deny不足以区分来自proxy的访问,目前我的测试代码是这样的:
>>
>> location / {
>> content_by_lua '
>> local remote_ip = ngx.req.get_headers()["X-Real-IP"];
>> if remote_ip == nil then
>> remote_ip = ngx.var.remote_addr;
>> end;
>> local m = ngx.re.match(remote_ip,
>> "^192\\.168\\.56\\.[0-9]+$");
>> if m ~= nil then
>> ngx.say(remote_ip);
>> else
>> ngx.exit(403);
>> end;
>> ';
>> }
>>
>> 我现在把测试代码改一下,让它更接近实际场景:)
>>
>>
>
>
>
> --
> 国难思良将
>
> 智拙实验室: http://zerolabrary.appspot.com/
> ……
>
> 劉鑫
> March.Liu
>
> --
> 邮件自: 列表“openresty”,专用于技术讨论!
> 发言: 请发邮件到 open...@googlegroups.com
> 退订: 请发邮件至 openresty+...@googlegroups.com
> 详情: http://groups.google.com/group/openresty
> 官网: http://openresty.org/
> 仓库: https://github.com/agentzh/ngx_openresty
> 建议: 提问的智慧 http://wiki.woodpecker.org.cn/moin/AskForHelp
> 教程: http://agentzh.org/misc/nginx/agentzh-nginx-tutorials-zhcn.html
--
人生苦短, Pythonic! 冗余不做,日子甭过!备份不做,十恶不赦!
俺: http://about.me/zoom.quiet
文字协议: http://creativecommons.org/licenses/by-sa/2.5/cn/
在 2012年6月8日 下午2:56,刘鑫 <marc...@gmail.com> 写道:
> PS,原本我想用access_by_lua,但是这里我需要把它proxy到另一个server{...},rewrite好像只能转向到同一个http://host:port下面?- 都可以的, openresty 里有 interl 模式的完全跳转,,纯内部数据流通,很爽脆的!
>
- 嗯嗯嗯,俺对内忽悠没有成功,怎么外边儿的旧金山人都开始研究了?!
- 推荐使用 tengine+openrsty 进行多重优化!
> 在 2012年6月8日 下午2:49,刘鑫 <marc...@gmail.com>写道:
>
>> 啊,感谢你的详细讲解,那个语法错误刚刚我也发现了,而且我测试了一下,用allow/deny不足以区分来自proxy的访问,目前我的测试代码是这样的:
>>
>> location / {
>> content_by_lua '
>> local remote_ip = ngx.req.get_headers()["X-Real-IP"];
>> if remote_ip == nil then
>> remote_ip = ngx.var.remote_addr;
>> end;
>> local m = ngx.re.match(remote_ip,
>> "^192\\.168\\.56\\.[0-9]+$");
>> if m ~= nil then
>> ngx.say(remote_ip);
>> else
>> ngx.exit(403);
>> end;
>> ';
>> }
>>
>> 我现在把测试代码改一下,让它更接近实际场景:)
>>
>>
>
>
>
> --
> 国难思良将
>
> 智拙实验室: http://zerolabrary.appspot.com/
> ......
2012/6/8 刘鑫 <marc...@gmail.com>:
> 啊,感谢你的详细讲解,那个语法错误刚刚我也发现了,而且我测试了一下,用allow/deny不足以区分来自proxy的访问,目前我的测试代码是这样的:
>
> location / {
> content_by_lua '
> local remote_ip = ngx.req.get_headers()["X-Real-IP"];
> if remote_ip == nil then
> remote_ip = ngx.var.remote_addr;
> end;
> local m = ngx.re.match(remote_ip, "^192\\.168\\.56\\.[0-9]+$");
这一行代码中的正则表达式仍然存在转义的问题。如果你使用 LuaJIT 2.0.0 beta9 以上版本运行你的 Lua 代码的话,会得到下面这一行错误:
[error] 7829\#0: *1 Failed to load Lua inlined code: [string
\"content_by_lua\"]:6: invalid escape sequence near '\"^192'
如果你使用标准 Lua 5.1 是会把 \. 默默地解释为 . 的,而这显然不是你想要的,呵呵。
对非法转义序列的错误检查是 Lua 5.2 和 LuaJIT 2.0.0 beta9+ 引入的新特性。
正如我早先那封邮件中指出的,在这个内联 Lua 代码到 nginx.conf 的上下文中的正确的写法应当是:
local m = ngx.re.match(remote_ip, [[^192\\.168\\.56\\.[0-9]+$]]);
Regards,
-agentzh
2012/6/8 smallfish <smallf...@gmail.com>:
> 我现在的做法是:
> 1. 搞多个upstream
> 2. 在access_by_lua里判断校验的结果,然后拼出upstream的名字
> 3. 最后proxy_pass到上面的变量结果中去
是的,这是一种推荐的做法。当然,另外一种做法是在 access_by_lua 中使用 ngx.exec()
进行内部跳转,这样在那些使用有限域名的情况下可以避免请求时运态请求 DNS 服务器(当然,这个对性能的影响也有限,毕竟 nginx 自己的
resolver 也是带缓存的) :)
Best regards,
-agentzh
2012/6/8 Zoom.Quiet <zoom....@gmail.com>:
> - 推荐使用 tengine+openrsty 进行多重优化!
>
Tengine 的一个好处是可以自动进行 CPU 亲缘性配置。如果使用标准 Nginx 核心同时自己配置好 CPU affinity
的话,在使用 ngx_lua 等 OpenResty 组件时,应该在性能上不会有什么区别。(欢迎 Tengine 团队的朋友们指正,呵呵)
另外,我个人目前只支持 OpenResty 组件在标准 Nginx 核心上的技术问题 :) 特定于 Tengine 的问题需要
Tengine 团队来支持了,呵呵。
Regards,
-agentzh
- 是也乎,是也乎
- Tengine 提供对 Nginx 的原生增强
- openresty 提供对 Nginx 的非入侵式功能扩展
相得益彰哪,,,
> Regards,
> -agentzh
2012/6/8 刘鑫 <marc...@gmail.com>:
> 我这个需求跟鱼哥的有点不一样,对于非匹配网段,其实我希望把它阻挡到外面,所以我原本想把某些匹配的直接return一个403,但是测试发现执行完return
> 403后,nginx没有结束request,而是继续去执行下面的代码。即使break也不行。所以我现在做了一个比较囧的实现,专门写一个只返回403的server节点。
> 不知道大家有什么比较好的方案?
如果需要在 access_by_lua 中提前结束当前请求,可以使用 ngx.exit() 函数:
http://wiki.nginx.org/HttpLuaModule#ngx.exit
特别地,在你的场景中,直接写 ngx.exit(403) 就好了 :)
请注意,access_by_lua 总是运行在 ngx_rewrite 模块之后,所以 ngx_rewrite 模块的 return 和
break 自然都会在 access_by_lua 之前执行。
关于这里的执行顺序问题,可以参见我的 Nginx 连载教程:
http://agentzh.org/misc/nginx/agentzh-nginx-tutorials-zhcn.html#02-NginxDirectiveExecOrder01
Best regards,
-agentzh
Hello!
2012/6/8 刘鑫 <marc...@gmail.com>:
> 我这个需求跟鱼哥的有点不一样,对于非匹配网段,其实我希望把它阻挡到外面,所以我原本想把某些匹配的直接return一个403,但是测试发现执行完return如果需要在 access_by_lua 中提前结束当前请求,可以使用 ngx.exit() 函数:
> 403后,nginx没有结束request,而是继续去执行下面的代码。即使break也不行。所以我现在做了一个比较囧的实现,专门写一个只返回403的server节点。
> 不知道大家有什么比较好的方案?
http://wiki.nginx.org/HttpLuaModule#ngx.exit
特别地,在你的场景中,直接写 ngx.exit(403) 就好了 :)
请注意,access_by_lua 总是运行在 ngx_rewrite 模块之后,所以 ngx_rewrite 模块的 return 和
break 自然都会在 access_by_lua 之前执行。
关于这里的执行顺序问题,可以参见我的 Nginx 连载教程:
http://agentzh.org/misc/nginx/agentzh-nginx-tutorials-zhcn.html#02-NginxDirectiveExecOrder01
Best regards,
-agentzh