【问题标题】:Set node request header based on encoded formData value根据编码的 formData 值设置节点请求头
【发布时间】:2016-01-04 23:47:41
【问题描述】:

我正在尝试使用request npm 包向需要特殊标头的 API 发送 HTTP POST,该标头由请求正文的字符串表示形式的 base64 编码 MD5 哈希组成。

生成 MD5 哈希的代码:

function md5(val) {
    val = val || '';
    return crypto.createHash('md5').update(val).digest('base64');
}

当没有 formData 时,对于 GET 或 DELETE 请求,我应该使用的值是一个空字符串,效果很好。 API 接受标头并返回请求的数据。

不幸的是,当使用formData 选项发布文件时,对象正在被request 模块编码。因此,当服务器将我的 MD5 哈希与最终收到的正文进行比较时,它不匹配并引发错误。

我需要的简化请求:

var formData = {
    left: 0,
    top: 0,
    width: 0,
    height: 0,
    profileImage: fs.readFileSync(__dirname + '/test_image.jpg')
};

var reqOptions = {
    url: 'https://example.com/user/1234/profile-image',
    method: 'POST,
    json: true,
    headers: {
        'Content-MD5': md5(formData)
    },
    formData: formData
}

request(reqOptions, function(err, response, body) {
    //process the response...
});

上面的例子会抛出一个错误,因为 formData 变量是一个对象,而crypto 模块需要一个字符串。我开始手动编写代码来将 formData 对象转换为字符串,但是当 request 模块已经完成编码所有表单值的所有逻辑时,重写所有逻辑似乎有点荒谬。

我正在寻找一种可靠的方法来获取 exact 编码的表单内容,在 request 模块处理它们之后,但在实际发送请求之前,所以我可以构建哈希值并添加标头。

【问题讨论】:

  • 您是否尝试过将其编码为Buffer 并使用request 发送缓冲区?这样您就可以实际将请求正文提取为字符串

标签: javascript node.js encoding http-headers npm-request


【解决方案1】:

您可以通过以下方式手动执行此操作:

var crypto = require('crypto');
var FormData = require('form-data');

var form = new FormData();
form.append('left', 0);
form.append('top', 0);
form.append('width', 0);
form.append('height', 0);
form.append('profileImage', fs.readFileSync(__dirname + '/test_image.jpg'));

var rawChunks = [];
var hash = crypto.createHash('md5');
form.on('data', function(chunk) {
  rawChunks.push(chunk);
  hash.update(chunk);
}).on('end', function() {
  var headers = form.getHeaders();
  headers['Content-MD5'] = hash.digest('base64');
  var req = request({
    url: 'https://example.com/user/1234/profile-image',
    method: 'POST',
    headers: headers
  }, function(err, res, body) {
    // Do something with response
  });
  for (var i = 0; i < rawChunks.length; ++i)
    req.write(rawChunks[i]);
  req.end();
});

另一种可能的替代方法是使用分块编码并将Content-MD5 作为 HTTP 尾标(出现在正文之后的标头)传递。这将允许您防止在内存中缓冲生成的表单数据(如果您决定将fs.readFileSync() 更改为fs.createReadStream(),甚至可能在内存中缓冲文件字段)。然而,这一切都取决于目标服务器是否支持尾部标头(无论是解析它们还是实际使用它们)。

【讨论】:

    【解决方案2】:

    request 使用form-data npm 包对表单提交进行编码。该对象可通过request.form() 访问。您应该能够将其通过管道传输到 md5 哈希实例中:

    var formData = r.form();
    var hash = crypto.createHash('md5');
    hash.setEncoding('hex');
    form.on('end', function() {
        hash.end();
        console.log('hash is', hash.read());
        // submit request here
    });
    

    如果您将 form 流式传输到 md5 哈希中,然后 request 尝试再次使用相同的流,则可能会出现问题。在这种情况下,需要、实例化和填充 form-data 自己来计算哈希。然后创建另一个表单数据实例并将其传递给request

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-06
      • 1970-01-01
      • 2010-12-12
      相关资源
      最近更新 更多