如何使用nodejs请求模块复制curl命令?

我怎样才能复制这个curl请求:

 $ curl "https://s3-external-1.amazonaws.com/herokusources/..." \ -X PUT -H 'Content-Type:' --data-binary @temp/archive.tar.gz 

用节点请求模块?

我需要这样做来在AWS S3上放置一个文件,并匹配来自Heroku的源端点API输出的put_url中的Heroku提供的签名。

我已经尝试过( source是Heroku源端点API输出):

 // PUT tarball function(source, cb){ putUrl = source.source_blob.put_url; urlObj = url.parse(putUrl); var options = { headers: {}, method : 'PUT', url : urlObj } fs.createReadStream('temp/archive.tar.gz') .pipe(request( options, function(err, incoming, response){ if (err){ cb(err); } else { cb(null, source); } } )); } 

但是,我得到以下SignatureDoesNotMatch错误。

 <?xml version="1.0"?> <Error> <Code>SignatureDoesNotMatch</Code> <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message> <AWSAccessKeyId>AKIAJURUZ6XB34ESX54A</AWSAccessKeyId> <StringToSign>PUT\n\nfalse\n1424204099\n/heroku-sources-production/heroku.com/d1ed2f1f-4c81-43c8-9997-01706805fab8</StringToSign> <SignatureProvided>DKh8Y+c7nM/6vJr2pabvis3Gtsc=</SignatureProvided> <StringToSignBytes>50 55 54 0a 0a 66 61 6c 73 65 0a 31 34 32 34 32 30 34 30 39 39 0a 2f 68 65 72 6f 6b 75 2d 73 6f 75 72 63 65 73 2d 70 72 6f 64 75 63 74 69 6f 6e 2f 68 65 72 6f 6b 75 2e 63 6f 6d 2f 64 31 65 64 32 66 31 66 2d 34 63 38 31 2d 34 33 63 38 2d 39 39 39 37 2d 30 31 37 30 36 38 30 35 66 61 62 38</StringToSignBytes> <RequestId>A7F1C5F7A68613A9</RequestId> <HostId>JGW6l8G9kFNfPgSuecFb6y9mh7IgJh28c5HKJbiP6qLLwvrHmESF1H5Y1PbFPAdv</HostId> </Error> 

以下是Heroku源端点API输出的示例:

 { source_blob: { get_url: 'https://s3-external-1.amazonaws.com/heroku-sources-production/heroku.com/2c6641c3-af40-4d44-8cdb-c44ee5f670c2?AWSAccessKeyId=AKIAJURUZ6XB34ESX54A&Signature=hYYNQ1WjwHqyyO0QMtjVXYBvsJg%3D&Expires=1424156543', put_url: 'https://s3-external-1.amazonaws.com/heroku-sources-production/heroku.com/2c6641c3-af40-4d44-8cdb-c44ee5f670c2?AWSAccessKeyId=AKIAJURUZ6XB34ESX54A&Signature=ecj4bxLnQL%2FZr%2FSKx6URJMr6hPk%3D&Expires=1424156543' } } 

更新

这里的关键问题是我使用request模块发送的PUT请求应该与使用curl发送的PUT请求相同,因为我知道curl请求符合AWS S3使用预先签名的URL上传对象 API的期望。 Heroku生成PUTurl,所以我无法控制它的创build。 我知道curl命令正如我testing过的那样工作 – 这是好的,因为它是Heroku提供的例子。

我正在使用curl 7.35.0和request 2.53.0。

亚马逊API不喜欢分块上传。 该文件需要发送unchunked。 所以这里是工作的代码:

 // PUT tarball function(source, cb){ console.log('Uploading tarball...'); putUrl = source.source_blob.put_url; urlObj = url.parse(putUrl); fs.readFile(config.build.temp + 'archive.tar.gz', function(err, data){ if (err){ cb(err); } else { var options = { body : data, method : 'PUT', url : urlObj }; request(options, function(err, incoming, response){ if (err){ cb(err); } else { cb(null, source); } }); } }); },