在生产环境部署时,我们经常使用 nginx 反向代理我们的 nodejs 程序,如下:
location /uc/{
rewrite /uc/(.*) /$1 break;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_pass http://172.16.0.10:7001/;
proxy_redirect off;
}
经测试,使用这种 rewrite /uc/(.*) /$1 break; 是可以解决 egg 中 router 的问题
但是无法解决静态资源引用的问题。 请教 EGG 中如何解决?
node + express app.js
// 静态文件目录
var staticDir = path.join(__dirname, 'public');
app.enable('trust proxy');
app.use('/public', express.static(staticDir));
views/login.html
<link rel="stylesheet" href="public/libs/bootstrap/css/bootstrap.min.css">
以上注意静态资源引用没有使用 /public/ 而是使用的 public/
自己解决了,EGG 中不需要 app.enable('trust proxy'); 只需要注意静态资源引用不能使用 /public/ 而是使用的 public/ 即可。
这个问题依然存在, 原先是由于 niginx 缓存存在的原因, 以为正常了.
这个与 trust proxy 没有关系,试试调整一下 static 的参数: https://github.com/eggjs/egg-static#configuration
没有上下文环境的, 使用是没有问题的, 静态文件 以 /public/ 引用, 但使用了 nginx 反向代理后, 如加入前缀 /uc 后, 静态文件的访问自然就有问题, 这方面 express 是通过 app.enable('trust proxy'); 解决了这个问题, 难道 你们在生产环境部署时都没有感到过这样的问题? 也许你们的静态文件是走 cdn 的, 自然也不会有这样的问题.
如果是在 nginx 后面,你可以调整 static 的 prefix 参数来适应一下?
例如你将 prefix 改成 /uc/public,express 的 trust proxy 可以帮你自动判断出来前缀是 uc ?
那 静态资源引用是否也要加上 prefix ?
express 的 trust proxy 是跟 koa 的 proxy 类似的东西吧? 我印象中只是用来配置是否解析来源 ip 的, 跟 static 的 prefix 应该没啥关系才对
@hsxiaoma 如果路径会不一样,你在静态资源引用里面也要使用相对路径
我的意思可能你还没有明白,举个列子吧
// {app-root}/app/router.js
app.get('/','...');
app.get('/info','...');
app.get('/info/:id','...');
<!-- {app-root}/app/view/index.html -->
<script src="/public/mui/js/mui.min.js"></script>
<!-- {app-root}/app/view/info/index.html -->
<script src="/public/mui/js/mui.min.js"></script>
以上列子在没有上下文的情况下,一切正常。
经过 nginx 反向代理后加入了 /uc/
其地址映射则发生了变化
/ --> /uc/
/info --> /uc/info
/info/:id --> /uc/info/:id
/public/... --> /uc/public/...
路由的问题已经解决, 但静态文件没办法解决, 使用 相对路径也是不行的。
express 经测试, 已经解决了这个问题。详细参见: 见下楼层有详细描述
那你最终想访问 /uc/public 还是直接访问 /public 呢,如果你不想变模板的话应该是 /public?
@hsxiaoma 你在模板中使用相对路径引用静态资源,例如你的页面路径在本地为 /page/index.htm,想引用一个 /public/js/index.js,那你的路径就写 ../public/js/index.js,这样当你的所有的路径都加了一个 /uc 前缀,页面变成了 /uc/page/index.js,静态文件变成了 /uc/public/js/index.js,他们的相对路径还是不变的,通过 ../public/js/index.js 还是能引用到。
很不幸, 其实有很多时候 , 路由的地址和你实际的 html的位置是不一致的。
如:
/uc/info --> app/view/info/index.html
../public/.. --> ../../public/...
如果按路由地址来,显然是不合理的, 因为路由属于极易改变的东西
如果你能确定你的前端 nginx 配置的前缀是多少,判断在 nginx 后面时给静态资源加上这个前缀就可以了。
// app/extend/helper.js
module.exports = {
getStatic(path) {
if (this.ctx.get('X-NginX-Proxy')) return `/uc${path}`;
return path;
}
}
// view/index.html
<link rel="stylesheet" href="{{ helper.getStatic(/public/libs/bootstrap/css/bootstrap.min.css)}}">
你的那篇文章放到一个可以被其他人访问的地方吧。
@hsxiaoma 你是 UC 哪个部门的? UC 这边不都走构建静态资源绝对路径的方式么?这属于工程化的范畴了,之前云龙有专门阐述过这块的,都是推荐用绝对路径的。
补充文档
生产环境下
nginx反向代理多个node+express应用时静态资源路径的问题
现有以下 node + express 程序:
nodejs-app1: http://127.0.0.1:3000
nodejs-app2: http://127.0.0.1:3001
nginx 的映射为:
http://yourdoamin/app1 --> http://127.0.0.1:3000
http://yourdoamin/app2 --> http://127.0.0.1:3001
使用 express 时静态文件设置都是以 / 为开头的,此时由于 nginx 映射的地址有 app1 或者 app2 前缀,导致原有的 /public/ 静态文件的地址失效,如何解决这个问题呢?
在 app.js 中使用:
参考: 代理之后的 Express
app.enable(‘trust proxy’);
在所有的视图或引用静态文件的地方,一律使用 public/...
部分代码示例:
upstream app1 {
server 127.0.0.1:3000;
}
upstream app2 {
server 127.0.0.1:3001;
}
server {
location /app1/{
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_max_temp_file_size 0;
proxy_pass http://app1/;
proxy_redirect off;
proxy_read_timeout 240s;
}
location /app2/{
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_max_temp_file_size 0;
proxy_pass http://app2/;
proxy_redirect off;
proxy_read_timeout 240s;
}
}
// app.js
// 静态文件目录
var staticDir = path.join(__dirname, 'public');
app.enable('trust proxy');
app.use('/public', express.static(staticDir));
<link rel="stylesheet" href="public/libs/bootstrap/css/bootstrap.min.css">
以上注意静态资源引用没有使用 /public/ 而是使用的 public/
以上静态资源在不同的应用会自动加上反向代理的路径:
如:
app1 下的 实际会转换为 app1/public/libs/bootstrap/css/bootstrap.min.css
app2 下的 实际会转换为 app2/public/libs/bootstrap/css/bootstrap.min.css
@dead-horse 你不觉得你的解决方案很纠结吗?
你这个解法不就是用相对路径来屏蔽掉了前面的 app1 / app2 前缀么?与 trust proxy 到底有什么关系?
<link rel="stylesheet" href="public/libs/bootstrap/css/bootstrap.min.css">
sorry,我并没没有深究其中原因。 但实例验证, 如果不使用 trust proxy ,则代理失败。
首先,你得先弄明白trust proxy是干嘛用的
是的, 也许我的引用是有问题的, 但我还需要去验证一下。 但这个问题如果使用 CDN 后就不复存在了。
向 @dead-horse @fengmk2 大牛学习
可以先看看 express 这块的源码下。
发自我的 iPhone
在 2017年2月27日,22:54,天马行空 notifications@github.com 写道:
实例验证, 如果不使用 trust proxy ,则代理失败。
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
设置 trust proxy 为非假值会带来两个重要变化:
反向代理可能设置 X-Forwarded-Proto 来告诉应用使用 https 或简单的 http 协议。请参考 req.protocol。
req.ip 和 req.ips 的值将会由 X-Forwarded-For 中列出的 IP 地址构成。
trust proxy 只会影响如何获取客户端的真实 ip 和协议,所以与你这里提到的问题没有关系,真正解决静态资源路径问题的是你用了相对路径来引用静态资源:
你在模板中使用相对路径引用静态资源,例如你的页面路径在本地为 /page/index.htm,想引用一个 /public/js/index.js,那你的路径就写 ../public/js/index.js,这样当你的所有的路径都加了一个 /uc 前缀,页面变成了 /uc/page/index.js,静态文件变成了 /uc/public/js/index.js,他们的相对路径还是不变的,通过 ../public/js/index.js 还是能引用到。
你好!请问这问题最后怎么处理呢?我也遇到了同样问题,在模板中写成相对路径也解决不了。
我现在也遇到了这个问题,通过ip可以访问,但是通过nginx代理后就提示找不到js了
Most helpful comment
可以先看看 express 这块的源码下。
发自我的 iPhone