对于路由,我希望我的中间件将/html 文件夹中定义的路由请求传递给服务器 HTML(ejs),如果 header Content-Type 是 application/json,则使用/api 中定义的路由文件夹。
但我不想在每条 route 都定义它。 所以我不是在寻找定义一些我可以在每条 route 检查的 req.api 属性的中间件
app.get('/', function(req, res) {
if(req.api_call) {
// serve api
} else {
// serve html
}
});
但是我想要这样的东西:
// HTML folder
app.get('/', function(req, res) {
res.send('hi');
});
// API folder
app.get('/', function(req, res) {
res.json({message: 'hi'});
});
这可能吗?如果可以,我该怎么做?
我希望它像这样工作:
app.use(checkApiCall, apiRouter);
app.use(checkHTMLCall, htmlRouter);
最佳答案
您可以在 Express 链中插入第一个中间件,中间件处理程序检查请求类型,然后通过向其添加前缀路径将 req.url
修改为伪 URL。然后,此修改将强制该请求仅转到特定路由器(设置为处理该特定 URL 前缀的路由器)。我已经使用以下代码验证了这在 Express 中是否有效:
var express = require('express');
var app = express();
app.listen(80);
var routerAPI = express.Router();
var routerHTML = express.Router();
app.use(function(req, res, next) {
// check for some condition related to incoming request type and
// decide how to modify the URL into a pseudo-URL that your routers
// will handle
if (checkAPICall(req)) {
req.url = "/api" + req.url;
} else if (checkHTMLCall(req)) {
req.url = "/html" + req.url;
}
next();
});
app.use("/api", routerAPI);
app.use("/html", routerHTML);
// this router gets hit if checkAPICall() added `/api` to the front
// of the path
routerAPI.get("/", function(req, res) {
res.json({status: "ok"});
});
// this router gets hit if checkHTMLCall() added `/api` to the front
// of the path
routerHTML.get("/", function(req, res) {
res.end("status ok");
});
注意:我没有填写 checkAPICall()
或 checkHTMLCall()
的代码,因为您没有完全具体说明您希望它们如何工作。我在自己的测试服务器中模拟了它们,以查看该概念是否有效。我假设您可以为这些函数提供适当的代码或替换您自己的 if
语句。
事先回答
我刚刚验证了您可以在 Express 中间件中更改 req.url
所以如果您有一些修改 req.url
的中间件,它将影响路由那个要求。
// middleware that modifies req.url into a pseudo-URL based on
// the incoming request type so express routing for the pseudo-URLs
// can be used to distinguish requests made to the same path
// but with a different request type
app.use(function(req, res, next) {
// check for some condition related to incoming request type and
// decide how to modify the URL into a pseudo-URL that your routers
// will handle
if (checkAPICall(req)) {
req.url = "/api" + req.url;
} else if (checkHTMLCall(req)) {
req.url = "/html" + req.url;
}
next();
});
// this will get requests sent to "/" with our request type that checkAPICall() looks for
app.get("/api/", function(req, res) {
res.json({status: "ok"});
});
// this will get requests sent to "/" with our request type that checkHTMLCall() looks for
app.get("/html/", function(req, res) {
res.json({status: "ok"});
});
旧答案
我能够像这样成功地在 express 前面放置一个请求回调,并看到它成功地修改了传入的 URL,然后像这样影响 express 路由:
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(function(req, res) {
// test modifying the URL before Express sees it
// this could be extended to examine the request type and modify the URL accordingly
req.url = "/api" + req.url;
return app.apply(this, arguments);
});
server.listen(80);
app.get("/api/", function(req, res) {
res.json({status: "ok"});
});
app.get("/html/", function(req, res) {
res.end("status ok");
});
这个例子(我测试过)只是硬连线将“/api”添加到 URL 的前面,但您可以自己检查传入的请求类型,然后适本地修改 URL。我还没有探索这是否可以完全在 Express 中完成。
在这个例子中,当我请求“/”时,我得到了 JSON。
关于node.js - 基于 Content-Type header 的 Expressjs 路由器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35896820/