想实现一个文件区间下载的接口, 比如通过 /file?start=0&length=100 下载文件的前100个字节。
写了一个 rewrite_by_lua 的脚本,脚本根据 uri args 给 request 的 header 添加 Range:
bytes=xx-xxx 的字段, 然后交给 nginx 的 file handle 处理。
直接访问,脚本所在 location 正常工作。 但作为 ngx.location.capture 的 uri , capture 返回了文件的全部内容。
从 log 里面看, uri args 的传递没有问题, subrequest 中给 header 添加字段似乎没有成功。
我看文档里只是提到
“Note that subrequests issued by ngx.location.capture inherit all the
request headers of the current request by default”
还有 for ngx.req.set_header "None of the current request's subrequests
will be affected." 但都没有说到在 subrequest 里面修改 request header。
想请教一下各位, 这是 ngx_lua 的限制么? 如果是的话,有什么能绕开限制的方法么 ?
你是如何通过 URL 参数给子请求添加请求头的?
目前 ngx.location.capture 没有提供直接的接口来做到这一点,但至少有两种做法(相关示例都已经在我本地测试通过):
方法一
在发送子请求之前临时改写当前请求的 Range 请求头,这样子请求可以自动继承到父请求的请求头,子请求结束后再把父请求的 Range 请求头恢复原先的值,例如:
location /test {
rewrite_by_lua '
local old_range = ngx.var.http_range
print("old range: ", old_range)
ngx.req.set_header("Range", "bytes=2-10")
local res = ngx.location.capture("/sub")
ngx.req.set_header("Range", old_range)
print("[", res.body, "]")
';
}
location /sub {
proxy_pass http://127.0.0.1:$server_port/index.html;
}
方法二:
使用 proxy_set_header 配置指令在子请求中直接设置请求头,需要设置的 Range 头的值通过 nginx 变量传递进子请求的
location,例如:
location /test {
set $range '';
rewrite_by_lua '
local res = ngx.location.capture("/sub", { vars = { range
= "bytes=2-10" } })
print("[", res.body, "]")
';
}
location /sub {
proxy_set_header Range $range;
proxy_pass http://127.0.0.1:$server_port/index.html;
}
无疑方法二更优雅一些,同时效率上也会更高一些。
方法二还可以引伸出方法三,即在 location /sub 中使用 ngx_header_more 模块的
more_set_input_headers 配置指令改写 Range 请求头,数据从父请求到子请求的传递也可以借助于 nginx
变量来完成。
> 直接访问,脚本所在 location 正常工作。 但作为 ngx.location.capture 的 uri , capture 返回了文件的全部内容。
> 从 log 里面看, uri args 的传递没有问题, subrequest 中给 header 添加字段似乎没有成功。
>
因为你没有提供示例代码和配置,所以我不清楚你是如何去做的,更不清楚你说的"没有成功"是什么原因。可以直接尝试我上面给出的两种解法 :)
Best regards,
-agentzh
2012/6/12 王曦 <wang...@gmail.com>:
> 这两天也遇到了给subrequest加header的问题,我现在用的方法如下,不修改当前请求,在子请求的location中通过ngx_lua提供的功能添加header,应该算是第一种方法的改良,但不知道效率和第二中方法比如何?
>
直接在子请求访问的 location 中修改请求头也是可以的。如果追求效率的话,也可以直接使用 ngx_headers_more 模块的
more_set_input_headers 配置指令:
http://wiki.nginx.org/HttpHeadersMoreModule#more_set_input_headers
TIMTOWTDI! :D
Regards,
-agentzh
--
邮件自: 列表“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