今天研究了下nginx中如何实现一次跨server跳转的问题. 想要实现例如请求rewrite.cn而转向本地的rewrited.cn来处理. nginx作为一个反向代理服务器, 拥有强大的跳转指令.
我们经常会使用rewrite
指令来进行uri重写以实现跨location的内部跳转.
为了解决跨server的location跳转, 首先想到的仍然是rewrite
指令. 将整个url重写成new_url.我们看一下官方wiki
说明:
rewrite regex replacement [ flag ]
If the replacement string begins with http:// then the client will be redirected, and any further rewrite directives are terminated.
同样是在nginx官网的Pitfalls 找到如下一段配置:
1
2
3
4
5
6
7
8
server {
server_name www.domain.com;
return 301 $scheme://domain.com$request_uri;
}
server {
server_name domain.com;
[...]
}
很明显, 通过这两段我们可以知道我们可以通过http
协议的跳转协议来让客户端进行跳转, 很遗憾, 这样不是一个很好的解决方案, 我希望的是纯粹在server端做….
如果rewrite
不行,想到可以试试第三方模块, 很容易的就想到了agentzh春哥 的ngx_lua
模块. 于是就将注意力集中到了ngx.exec
, ngx.redirect
, ngx.location.capture
上.
经过简单阅读相关文档, 发现还是行不通. 另外在github上找到了类似的需求, agentzh也做了相应的回答(点我 ).
简单说就是因为内部制约问题, 无法用过重写 或者子请求 等情况进行跨server的访问. 最简单的实现方法是通过proxy_pass
代理模块来进行.
那我们就按照上述思路实现一下好了. 现在我们希望通过访问rewrite.cn/rewrited.cn/js/action.js来访问到rewrited.cn/js/action.js. 因为考虑到重写的需求可能会很复杂, 因此使用lua
模块
进行rewrite
rewrite.lua 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- get the target host from the uri
function rewrite_decode ( uri )
local _ , _ , host , d_uri = string.find ( uri , ' ^/(.-)(/.*)$' )
return host , d_uri
end
local uri = ngx . var . uri
host , d_uri = rewrite_decode ( uri )
if host == nil or d_uri == nil then
return ngx . exit ( ngx . HTTP_NOT_FOUND )
end
ngx . req . set_uri ( d_uri , false )
ngx . req . set_header ( ' Host' , host )
ngx . var . _proxy_host = host
rewrite.com的nginx配置文件:
rewrite.lua 1
2
3
4
5
6
7
8
9
10
11
12
server {
server_name rewrite . cn ;
listen 80 ;
access_log logs / rewrite . cn . log ;
location / {
set $ _proxy_host ' ' ;
rewrite_by_lua_file lua_script / rewrite . lua ;
proxy_set_header Host $ _proxy_host ;
proxy_pass http : // 127.0.0.1 : 80 ;
}
}
rewrited.com的nginx配置文件:
rewrite.lua 1
2
3
4
5
6
7
8
9
server {
server_name rewrited . cn ;
listen 80 ;
access_log logs / rewrited . cn . log ;
location / {
content_by_lua_file lua_script / fake_content . lua ;
}
}
这里的fake_content.lua
是用来进行相关的测试的, 内容如下:
fake_content.lua 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
-- debug
local uri = ngx . var . uri
local args = ngx . var . args
local host = ngx . var . host
local hds = ngx . req . get_headers ()
ngx . say ( " uri => " .. uri )
if args ~= nil then
ngx . say ( " args => " .. args )
else
ngx . say ( " args => nil" )
end
if host ~= nil then
ngx . say ( " host => " .. host )
else
ngx . say ( " host is nil" )
end
ngx . say ( " \n ------ req headers ------" )
for k , v in pairs ( hds ) do
ngx . say ( k .. " : " .. v )
end
可以通过curl
以及观察相应的访问日志来查看是否正常:
1
curl -x 127.0.0.1:80 rewrite.cn/rewrited.cn/js/action.js