如何定义Node.js应用程序上下文路径
How to define Node.js application context path?
来自Java世界,其中基于servlet的应用程序上下文路径是基于WAR文件名设置的,我试图理解在Node.js中定义上下文路径的最佳实践。
所讨论的Node应用程序没有在代码中定义上下文路径。例如,Express代码假设获取故事的请求具有路径为/story/1的URL。因此,JavaScript UI代码将向http://host:port/story/1发出请求。同样地,用户要连接到主应用程序页面,他们将访问http://host:port/。
我想将用户看到的URL更改为http://host:port/myapp。问题是如何一致地将"myapp"定义为应用程序上下文。我正在考虑的选项:
- 在Express.js代码中定义上下文。
- 在Nginx代理服务器中定义上下文
我如何确保用户总是在URL中看到"myapp"?我还需要重新映射所有的内部请求(那些由UI代码)也有'/myapp'上下文?
使用Nginx似乎更干净,因为它不需要更改代码。但是,这个目标可以通过Nginx配置单独实现吗?如果可以,如何实现?
由于这是一个常见的问题,因此必须有一个定义良好的模式来解决它。
正如你所说,最好在nginx配置中这样做,以便于上下文路径独立于应用程序代码。
在nginx端,你可以用location
指令设置上下文路径,然后你可以从path中删除context path
并将请求发送给应用程序。它可以通过nginx的重写指令来完成,如下所示:
location /myapp/ {
rewrite ^/myapp/(.*)$ /$1 break;
...
}
因此,在nodejs (express)端,你应该假设应用程序运行在根路径(/)下。
你可以使用express router。
const express = require('express');
const app = express();
const http = require('http');
const httpServer = http.createServer(app);
const router = express.Router();
const contextPath = '/api';
router.get('/', function(req, res) {
res.send("you've reached the API endpoint");
});
app.use(contextPath, router);
httpsServer.listen(9000));
对host:9000/api/的get请求现在将返回"您已到达api端点"
实际上有很多方法可以将上下文路径添加到现有的express应用程序中。其中一种方法是利用http.createServer()。在下面的代码中,我添加了2个带有上下文路径的应用程序和一个备用应用程序。
const http = require('http');
const express = require('express');
const printReq = req => `contextPath: ${req.theContextPath}, url: ${req.url}, originalUrl ${req.theOriginalUrl}`;
// Your original app
const app = express();
app.get('/hello', (req, res) => res.send(`Hello original, ${printReq(req)}`))
app.get('*', (req, res) => res.send(`Default original app routing , ${printReq(req)}`))
// second app with context /app1
const app1 = express();
const contextPath1 = '/app1'
app1.get('/hello', (req, res) => res.send(`Hello app1, ${printReq(req)}`))
app1.get('*', (req, res) => res.send(`Default app1 routing, ${printReq(req)}`))
// third app with context /app2
const app2 = express();
const contextPath2 = '/app2'
app2.get('/hello', (req, res) => res.send(`Hello app2, ${printReq(req)}`))
app2.get('*', (req, res) => res.send(`Default app2 routing, ${printReq(req)}`))
const stripContextPath = (req, contextPath) => {
req.theOriginalUrl=req.url;
req.theContextPath=contextPath;
req.url = req.url.replace(new RegExp('^' + contextPath), '');
}
// -----------------------------------------------------------------------------------------------------------
// create raw server
const server = http.createServer((req, res) => {
if(req.url.startsWith(contextPath1)){
stripContextPath(req, contextPath1);
app1(req, res);
}else if(req.url.startsWith(contextPath2)){
stripContextPath(req, contextPath2);
app2(req, res);
}else{
// fallback
app(req, res);
}
});
server.listen(3000, '0.0.0.0', () => console.log('server listening at', server.address()));
你可以在保存为server.js并安装express dependency后做一些测试。
顺便说一句,如果你想用代理来做,除了nginx,你还可以使用节点http代理来给你现有的应用程序提供上下文路径
- 在openshift node js应用程序中获取请求
- 使用CI和CodeDeploy对node.js应用程序进行连续部署
- 如何构建angular.js应用程序
- node.js应用程序中的async.js问题
- 使用connect vhost为多个express.js应用程序提供服务
- 在node.js应用程序中接收JMS消息
- JS应用程序中基于DOM的XSS保护
- Express.js应用程序最大CPU
- Node.js应用程序-由NPM启动时的不同Node_ENV
- 如何将现有的angular js应用程序集成到Laravel 5中
- React js应用程序's在托管应用程序中打开时将覆盖css样式
- angular js应用程序不工作
- 使用Sails.JS为静态HTML/JS应用程序提供身份验证
- 如何计算angular JS应用程序(单页应用程序)的页面加载时间
- 使用Q节点模块时,Bluemix node.js应用程序部署失败
- Heroku类型的简单HTML/JS应用程序托管
- 通过SSL/TLS连接访问Vagrant上的Node.js应用程序
- 在Backbone.js应用程序中使用lodash而不是下划线
- fs.readFileSync()在express js应用程序中失败
- 在Chrome和Safari中启动Angular JS应用程序的差异