我尝试使用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
已经完成时,重写所有编码所有表单值的逻辑似乎有点荒谬模块。
我正在寻找一种可靠的方法来获取完全编码的表单内容,在request
模块处理后,但在请求之前实际发送,所以我可以构建哈希值并添加标题。
答案 0 :(得分:0)
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
来计算哈希值。然后创建另一个form-data实例并将其传递给request
。
答案 1 :(得分:0)
您可以使用以下内容手动执行此操作:
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()
,甚至可能在内存中缓冲文件字段)。但是,它将取决于目标服务器是否支持预告片头(无论是解析它们还是实际上都使用它们)。