我的nodeJS Api需要根据标头返回HTML或Json。如果标题是:
Accept = application/json
Api需要返回Json,否则我的Api需要返回一个HTML文件。
这是我在路线上使用的代码:
var app = express();
app.use('/auth', require('./routes/Authenticate'));
在Authenticate文件中我捕获/登录,然后执行登录。如果成功,我重定向到/ users。在/ users中,我使用if语句检查Accept:
router.get('/users', function(req,res){
if(req.get('Accept') === 'application/json'){
res.json({ success: true, user: req.user });
} else {
res.render("account/profile") //redirect to the file
}
});
这可行(来自此solution)但有更好的方法吗?因为有20个端点,应用程序正在增长,这对每个端点都是一团糟。
答案 0 :(得分:0)
您可以将这些操作拆分为2个功能。一个用于验证内容类型,另一个用于执行操作。
router.get('/users', checkIfJson, action);
function checkIfJson(req, res, next) {
if(!(req.get('Content-Type') === 'application/json')) {
res.render("account/profile");
return;
}
next();
}
function action(req, res) {
res.json({ success: true, user: req.user });
return;
}
如果您编写代码,则可以将checkIfJson重用于其他路径。
答案 1 :(得分:0)
您可以使用自定义函数
包装router.get函数router.wrappedGet = function (path, callback) {
router.get(path, function (req, res) {
if (req.get('Content-Type') === 'application/json') {
res.render = res.json;
}
callback(req, res);
})
};
答案 2 :(得分:0)
这就是我所做的-似乎非常简单。
router.get("/foo", HTML_ACCEPTED, (req, res) => res.send("<html><h1>baz</h1><p>qux</p></html>"))
router.get("/foo", JSON_ACCEPTED, (req, res) => res.json({foo: "bar"}))
以下是这些中间件的工作方式。
function HTML_ACCEPTED (req, res, next) { return req.accepts("html") ? next() : next("route") }
function JSON_ACCEPTED (req, res, next) { return req.accepts("json") ? next() : next("route") }
我个人认为这是易读的(因此可以维护)。
$ curl localhost:5000/foo --header "Accept: text/html"
<html><h1>baz</h1><p>qux</p></html>
$ curl localhost:5000/foo --header "Accept: application/json"
{"foo":"bar"}
注意:
HTML
路由放在JSON
路由之前,因为某些浏览器会接受HTML 或 JSON,因此它们将获得最先列出的路由。我希望API用户能够理解和设置Accept标头,但是我不希望浏览器用户使用,因此浏览器会获得优先选择。next('route')
。简而言之,next()
跳到同一路由中的下一个中间件 ,而next('route')
退出此路由并尝试下一条。