node.js - 基于 Content-Type header 的 Expressjs 路由器

标签 node.js api express middleware

对于路由,我希望我的中间件将/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/

相关文章:

javascript - 使用 PHP 实时更新数据

javascript - 获取回调时 Express.js req.body 未定义

node.js - 从 Node js中的二维数组生成docx表

node.js - Mongoose 或查询

node.js - 在 Moleculer 中获取正文 POST 请求

javascript - 循环/迭代要返回的对象数组和字符串数组 - Javascript

json - 使用 API 从粉丝页面获取 Facebook 状态

javascript - 我如何创建一个 div 并将 JSON 中的 'brands' 数据放入其中?

postgresql - 如何在不嵌套输出的情况下在 Sequelize 中包含模型

javascript - 使用 Socket.IO 时如何访问 session 标识符?