关于返回响应内容的处理

1,882 views
Skip to first unread message

mike19...@gmail.com

unread,
Jul 7, 2015, 7:46:20 AM7/7/15
to open...@googlegroups.com
curl  'http://test.aaa.com/2015060114092583r9k8wj2c9idl9r95/800000/m.m3u8?a=2&b=4&as=8'
通过访问nginx服务后获取文件内容,
现在想获取的文件内容根据URI的参数做一些更改。
原本打算在connect_by_lua写,但是location中有proxy_pass无法修改,最终放弃
不知道还有什么好的方法来实现这种要求

Yichun Zhang (agentzh)

unread,
Jul 7, 2015, 9:16:15 AM7/7/15
to openresty
Hello!
两种选择:

1. 使用 ngx.location.capture 发起子请求到你的目标 location,然后在 Lua 里面对 res.body 进行修改。
2. 使用 body_filter_by_lua 直接对响应体作修改,但要小心流式处理的问题。

Regards,
-agentzh

mike19...@gmail.com

unread,
Jul 7, 2015, 10:02:14 PM7/7/15
to open...@googlegroups.com
谢谢大神的意见。
1.通过body_filter_by_lua 直接对响应体作修改,之前尝试过由于增加了chunk里面内容的字符内容,由于connect_length的影响,不能请求到全部内容。如果修改head的头信息的话(修改ngx.header.HEADER中相应的数值 ),发现nginx的errorlog里面报
2015/07/08 07:23:43 [error] 27554#0: *260 attempt to set ngx.header.HEADER after sending out response headers while sending to client,
不知道对这种情况有什么解决办法吗?
2.body_filter_by_lua里面对chunk内容的修改是否不能增加或者删除内容,只能保证内容大小不变的情况下进行修改?
3.参照http://wiki.nginx.org/HttpLuaModule#body_filter_by_lua,如果修改了body_filter_by_lua后,ngx.arg[x]怎么判断是最后一个呢,文档中说the "eof" flag,但是判断string的"eof"貌似不行,还是判断ngx.arg[x]的type是boolean的话就是buff最后一个?



在 2015年7月7日星期二 UTC+8下午9:16:15,agentzh写道:

Yichun Zhang (agentzh)

unread,
Jul 7, 2015, 10:08:25 PM7/7/15
to openresty
Hello!

2015-07-08 10:02 GMT+08:00 <mike19...@gmail.com>:
> 谢谢大神的意见。
> 1.通过body_filter_by_lua
> 直接对响应体作修改,之前尝试过由于增加了chunk里面内容的字符内容,由于connect_length的影响,不能请求到全部内容。如果修改head的头信息的话(修改ngx.header.HEADER中相应的数值
> ),发现nginx的errorlog里面报
> 2015/07/08 07:23:43 [error] 27554#0: *260 attempt to set ngx.header.HEADER
> after sending out response headers while sending to client,
> 不知道对这种情况有什么解决办法吗?

你应该在 header_filter_by_lua 里面对响应头进行修改,在 body filter 里面改已经太晚了(上面的错误消息清楚地指示了这一点)。

> 2.body_filter_by_lua里面对chunk内容的修改是否不能增加或者删除内容,只能保证内容大小不变的情况下进行修改?

当然不是。引用一下 body_filter_by_lua 的官方文档对此问题的说明:

“When the Lua code may change the length of the response body, then it
is required to always clear out the Content-Length response header (if
any) in a header filter to enforce streaming output, as in

location /foo {
# fastcgi_pass/proxy_pass/...

header_filter_by_lua 'ngx.header.content_length = nil';
body_filter_by_lua 'ngx.arg[1] = string.len(ngx.arg[1]) .. "\\n"';
}


https://github.com/openresty/lua-nginx-module#body_filter_by_lua

> 3.参照http://wiki.nginx.org/HttpLuaModule#body_filter_by_lua,如果修改了body_filter_by_lua后,ngx.arg[x]怎么判断是最后一个呢,文档中说the
> "eof" flag,但是判断string的"eof"貌似不行,还是判断ngx.arg[x]的type是boolean的话就是buff最后一个?
>

引用一下官方文档:

“the "eof" flag indicating the end of the response body data stream is
passed via ngx.arg[2] (as a Lua boolean value)”

显然,ngx.arg[2] 就是 eof :)

Regards,
-agentzh

mike19...@gmail.com

unread,
Jul 7, 2015, 11:17:20 PM7/7/15
to open...@googlegroups.com
> 1.通过body_filter_by_lua
> 直接对响应体作修改,
之前尝试过由于增加了chunk里面内容的字符内容,由于connect_length的影响,不能请求到全部内容。如果修改head的头信息的话(修改ngx.header.HEADER中相应的数值
> ),发现nginx的errorlog里面报
> 2015/07/08 07:23:43 [error] 27554#0: *260 attempt to set ngx.header.HEADER
> after sending out response headers while sending to client,
> 不知道对这种情况有什么解决办法吗?

你应该在 header_filter_by_lua 里面对响应头进行修改,在 body filter 里面改已经太晚了(上面的错误消息清楚地指示了这一点)。

加入了 header_filter_by_lua 'ngx.header.content_length = nil';后 Connect_Length没有了可以强制输出了。

现在想设置
Connect_Length的数值,但是因为在body_filter_by_lua中修改内容的, Connect_Length需要在header_filter_by_lua中修改,
header_filter_by_lua先于body_filter_by_lua运行,所以Connect_Length的数值不好设置
鉴于这种情况,大神有什么好的建议吗?

Yichun Zhang (agentzh)

unread,
Jul 7, 2015, 11:37:13 PM7/7/15
to openresty
Hello!

2015-07-08 11:17 GMT+08:00 mike19890421:
> 现在想设置Connect_Length的数值,但是因为在body_filter_by_lua中修改内容的,
> Connect_Length需要在header_filter_by_lua中修改,
> 而header_filter_by_lua先于body_filter_by_lua运行,所以Connect_Length的数值不好设置
> 鉴于这种情况,大神有什么好的建议吗?
>

如果你不能事先预估出新的响应体长度,那么显然你只能采用全缓冲的处理模式,即使用我先前建议过的 ngx.location.capture 这种子请求全缓存做法。

这是流式处理常常面对的悖论:要在流的开始输出长度,但又不能在那个时间事先知道流的长度。

Regards,
-agentzh
Reply all
Reply to author
Forward
0 new messages