在node中使用“connect”的中间件上执行get请求时,“请求模块”导致问题

elcex8rz  于 2023-05-28  发布在  Node.js
关注(0)|答案(1)|浏览(133)

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

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).
      });

下面是request模块设置中json属性的定义(来自文档)。
json -将body but设置为值的JSON表示,并添加Content-type:application/json头文件。另外,将响应体解析为json。
但很明显,这是一个GET请求,我不会设置任何content-type(但使用json:true选项,请求模块似乎在内部设置它)。
我可以通过下面的connect的json.js代码段来跟踪这一点

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 {
         ......

显然,这不是connect的问题,但它可能是json:true属性提供的不完整功能。我知道我可以只设置json:false并使用JSON.parse()将响应(JSON)解析为javascript对象,但对于其他请求类型(当设置json:true时),我不需要手动验证或解析JSON对象,而是从request模块的完整回调中获取它作为对象。
我想知道是否有任何其他的选择,我可以得到响应体作为对象,而没有这些问题所造成的连接失败,或任何其他信息,这个功能,证明这种行为与json:true(我找不到任何),或任何其他解决方案,任何人都使用,或任何令人满意的解释,这也是赞赏!谢谢。

hgqdbh6s

hgqdbh6s1#

如果其他人遇到同样的问题,添加一个答案。
查看request模块源代码,它似乎是一个bug,已经在request的最新版本中修复。因此,如果您使用的是较旧的版本(我的是2. 0. 5),请考虑升级为较新的版本。
旧版本有以下代码,所以不管json是否为true,也没有显式设置body,它仍然用于将content-type设置为header。

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')
  }

相关问题