【问题标题】:"Request module" causing issues while doing the get request, on the middleware that uses "connect" in node“请求模块”在执行获取请求时导致问题,在节点中使用“连接”的中间件上
【发布时间】:2013-10-09 03:51:06
【问题描述】:

我在客户端使用request module 执行REST 获取请求,其中中间件是connect,然后将请求路由到为它提供服务的节点服务器。问题是我在使用请求模块发出请求时尝试使用选项json:true,因此我不需要解析和验证收到的响应正文。但不幸的是,它没有到达服务器,因为它在中间件(连接)本身中失败并说“无效 JSON”,因为由于请求设置的内容类型,它似乎验证了 JSON(当没有请求正文时)模块。

这是我使用请求模块提出的请求。

  request(
    {
        uri: myurl,
        json: true, //issue area
        headers: {
             //some headers. but no content-type sepcified
        }
    }
    , function (error, response, body) {
        console.log(body); 
        //Here body comes as object if json:true (not for get as it fails in validation at connect middleware itself), else i need to perform JSON.parse(body).
      }); 

这是请求模块设置中json 属性的定义(来自文档)。

json - 将 body 设置为 JSON 表示值并添加 Content-type: application/json 标头。此外,将响应正文解析为 json。

但显然这是一个GET 请求,我不会设置任何content-type(但使用 json:true 选项请求模块似乎在内部设置它)。

我可以通过下面 connect 的 json.js sn-p 追踪到这一点

return function json(req, res, next) {
    if (req._body) return next();
    req.body = req.body || {};
    // check Content-Type
     //This guy fails because content-type is set as application/json by request module internally
    if ('application/json' != utils.mime(req)) return next();

    // flag as parsed
    req._body = true;

    // parse
    limit(req, res, function(err){
      if (err) return next(err);
      var buf = '';
      req.setEncoding('utf8');
      req.on('data', function(chunk){ buf += chunk });
      req.on('end', function(){
    //Here the problem area obviously buf[0] is undefined
        if (strict && '{' != buf[0] && '[' != buf[0]) return next(utils.error(400, 'invalid json'));
        try {
         ......           

显然这不是连接的问题,但它可能是json:true 属性提供的不完整功能。我知道我可以设置json:false 并使用JSON.parse() 将响应(JSON)解析为javascript 对象,但是对于我不需要验证或解析的其他请求类型(设置json:true 时)我获得了这种灵活性JSON 到手动对象,而不是我从请求模块的完整回调中获取它作为对象。

我想知道是否有任何其他选项可以让我将响应主体作为对象,而不会出现由连接失败引起的这些问题,或者有关此功能的任何其他信息可以证明这种行为与 json:true(我不能'找不到任何),或任何人使用过的任何其他解决方案,或对此的任何令人满意的解释也值得赞赏!谢谢。

【问题讨论】:

  • 可能标头与 json:true 冲突。 json:true 也添加了一个接受头。尝试删除标题。
  • @user568109 事实上,除了我自己的之外,我不添加任何标题,它们不会冲突。问题是一旦我无法控制请求模块设置它们,尤其是导致问题的内容类型,我该如何删除它们?
  • 我现在得到你的问题,似乎 json: true 选项期望用户自己设置正文。所以你能像json:{}body:{} 那样尝试json:true。这应该很有希望。
  • @user568109 是的,这是一种解决方法。事实上,我发现他们已经在最新版本的请求模块中解决了这个问题。它不再设置内容类型

标签: javascript json node.js connect


【解决方案1】:

如果其他人遇到同样的问题,请添加答案。

查看request模块源码,好像是最新版本request中已经修复的bug。因此,如果您使用的是旧版本(我的是 2.0.5),请考虑将其升级为新版本。

较早的有以下代码,所以无论 json 为 true 并且没有明确设置正文,它仍然用于将 content-type 设置为标题。

 if (options.json) {
    options.headers['content-type'] = 'application/json' //<-- this is being set always
    if (typeof options.json === 'boolean') {
      if (typeof options.body === 'object') options.body = JSON.stringify(options.body)
    } else {
      options.body = JSON.stringify(options.json)
    }
  ......

随着最新版本的变化:

  if (options.json) {
    self.json(options.json)

 //...More code 
 //and in json function

 this._json = true
  if (typeof val === 'boolean') {
    if (typeof this.body === 'object') {
      this.body = safeStringify(this.body)
      self.setHeader('content-type', 'application/json') //<-- sets it only if there is a body
    }
  } else {
    this.body = safeStringify(val)
    self.setHeader('content-type', 'application/json')
  }

【讨论】:

    猜你喜欢
    • 2019-02-09
    • 2023-04-03
    • 2018-09-25
    • 2021-08-11
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多