在 Express JS 中为 Ajax 设置 REST 路由,仅用于 Backbone

Posted

技术标签:

【中文标题】在 Express JS 中为 Ajax 设置 REST 路由,仅用于 Backbone【英文标题】:Set up REST routes in Express JS for Ajax only to use with Backbone 【发布时间】:2012-06-13 01:22:09 【问题描述】:

我正在使用带有 Express 的 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

或者有更好的方法吗?请帮忙。

【问题讨论】:

【参考方案1】:

我认为正确的做法是在您的应用程序中实施内容协商。是的,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 表示。

【讨论】:

【参考方案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】:

更好的方法是使用 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

【讨论】:

感谢您的回复。我没有在 Express 文档中找到 res.format() 。但我找到了 req.is('html') 或 req.is('json')。我想任何一个都应该工作,但 res.format() 看起来更好,因为它的功能,我不需要为 res.is() 使用 if/else if。 它还没有在文档中,因为 Express 3.x 是新的,并且需要更新站点(据我所知,这将很快发生)。【参考方案4】:

在您的请求中使用 Accept 标头:Accept: application/json 如果您想要接收 JSON,Accept: text/HTML 如果您想要 HTML。

【讨论】:

如何在 Node 端进行设置? 您使用标准的 javascript 文本解析技术(正则表达式等)在 req.headers 中查找以 Accept: 开头的任何内容。我这样做的方式是,如果其中任何一个请求 JSON,则发送一个 JSON 响应,如果没有一个请求,则发送一个 HTML 响应。

以上是关于在 Express JS 中为 Ajax 设置 REST 路由,仅用于 Backbone的主要内容,如果未能解决你的问题,请参考以下文章

在我的 express 中为 node.js 设置了 cors 但仍然给出关于 cors 的相同错误

使用 ASP.NET MVC 在 JS 文件中为 jQuery 设置 ajax url

在 express.js 中为 node.js 使用 jsonp

如何使用 express.js 在 Ajax 调用中实现 CSRF 保护(寻找完整示例)?

使用 node.js 和 express 的 JQuery Ajax 发布请求

如何在 Cpanel 中为 Node.js 应用程序配置端口?