我正在使用Node重新编写使用Node.js的现有网站。
该站点的前端将使用Backbone JS,因此我需要拥有符合本机Backbone同步的所有必要路由。现在,大多数URL的客户端和Backbone同步都是一样的。但它们不能用于常规GET,因为它们需要返回JSON。
所以我在想,在Backbone中为模型/集合URL添加扩展名(例如.json
,以及在Express中添加扩展名来为每条路径添加此内容是否是个好主意:
app.get('/p/:topCategory/:category/:product.:format', function(req, res) { ... });
if (req.params.id == 'json')
哪里发送JSON,否则我们呈现HTML?
还是有更好的方法吗?请帮忙。
答案 0 :(得分:12)
更好的方法是使用Express 3.x中的内容协商功能,即res.format
:
https://github.com/visionmedia/express/blob/master/lib/response.js#L299-378
res.format({
text: function(){
res.send('hey');
},
html: function(){
res.send('<p>hey</p>');
},
json: function(){
res.send({ message: 'hey' });
}
});
你接近也没关系,Yammer为前。使用相同的方法:http://developer.yammer.com/api/#message-viewing
答案 1 :(得分:6)
在您的请求中使用Accept
标头:Accept: application/json
如果您想要接收JSON,Accept: text/HTML
,如果您想要HTML。
答案 2 :(得分:2)
另一种替代方法,它还检查为jQuery等人设置了“X-Requested-With”标题。
var onlyAllowJsonRequests = function (req, res, next) {
var acceptJson = (req.accepted.length && _.any(req.accepted, function (acc) { return acc.value.indexOf("json") !== -1 }));
// also check that "X-Requested-With": "XMLHttpRequest" header is set
if (acceptJson && (req.xhr === true)) {
next();
} else {
res.send(406, "Not Acceptable");
}
};
app.use(onlyAllowJsonRequests);
NB下划线是依赖性。
答案 3 :(得分:2)
我认为正确的方法是在您的应用中实施内容协商。是的,Express 3.x工具是一种方法,可以直接回答你的问题,但我不认为这是最好的方法,因为它将内容协商责任放在路由逻辑中。我认为这不是一个好地方,因为它不遵循single responsibility原则,将内容协商置于路由逻辑中。
我已经在我的blog engine中实施了内容协商;审查可能有助于指导您朝着良好的方向发展。要点是代码通过内容协商逻辑确定文件扩展名。然后,使用文件扩展名,它想要找到相应的视图文件,将其呈现为响应并将其发送回客户端。这个想法是它根据内容协商以所请求的表示中的请求资源进行响应。 routing logic仅指定视图,但不知道内容协商。这发生在路由逻辑之外,这使得设计更加灵活。
这种设计的结果是能够要求特定的资源表示,如:
http://blog.joeyguerra.com/index.json并获取JSON表示 http://blog.joeyguerra.com/index.phtml并获取部分(或HTML片段)HTML表示 http://blog.joeyguerra.com/index.xml并获取XML表示。