subrequest 修改 request header 的问题

901 views
Skip to first unread message

袁也

unread,
May 28, 2012, 9:43:36 AM5/28/12
to open...@googlegroups.com
openresty 新手。

想实现一个文件区间下载的接口, 比如通过 /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 的限制么? 如果是的话,有什么能绕开限制的方法么 ?

agentzh

unread,
May 28, 2012, 11:08:23 AM5/28/12
to open...@googlegroups.com
2012/5/28 袁也 <west...@gmail.com>:

> 想实现一个文件区间下载的接口, 比如通过 /file?start=0&length=100 下载文件的前100个字节。
> 写了一个 rewrite_by_lua 的脚本,脚本根据 uri args 给 request 的 header 添加 Range:
> bytes=xx-xxx 的字段, 然后交给 nginx 的 file handle 处理。
>

你是如何通过 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

王曦

unread,
Jun 12, 2012, 1:23:48 AM6/12/12
to open...@googlegroups.com
这两天也遇到了给subrequest加header的问题,我现在用的方法如下,不修改当前请求,在子请求的location中通过ngx_lua提供的功能添加header,应该算是第一种方法的改良,但不知道效率和第二中方法比如何?

location /sub {
    rewrite_by_lua '
        ngx.req.set_header("Range", "bytes=2-10");
    ';
    proxy_pass http://127.0.0.1:$server_port/index.html;
}

location /test {
    content_by_lua '
        local rsp = ngx.location.capture("/sub");
    ';
}
如果新header的内容不是固定的,可以在当前请求中将其存在ngx.ctx或nginx变量中,然后capture的时候通过ctx或copy_all_vars传到子请求中

agentzh

unread,
Jun 12, 2012, 1:36:43 AM6/12/12
to open...@googlegroups.com
Hello!

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

Wendal Chen

unread,
Jun 12, 2012, 2:00:44 AM6/12/12
to open...@googlegroups.com
用lua-resty-http 来替代 ngx.location.capture 吧

https://github.com/liseen/lua-resty-http 




--
Wendal Chen
GuangDong China
Reply all
Reply to author
Forward
0 new messages