node.js - 如何使用nodejs请求模块复制curl命令?

标签 node.js heroku amazon-s3

如何复制此 curl 请求:

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

使用 Node request模块?

我需要执行此操作以在 AWS S3 上 PUT 文件,并匹配 Heroku 在 Heroku's sources endpoint API output 的 put_url 中提供的签名。 .

我已经尝试过这个(其中 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 发送的请求相同,因为我知道 curl 请求符合 AWS S3 Uploading Objects Using Pre-Signed URLs 的期望API。 Heroku 生成 PUT url,因此我无法控制它的创建。我确实知道 curl 命令可以工作,正如我测试过的那样——这很好,因为它是 Heroku 提供的示例。

我正在使用 curl 7.35.0 和 request 2.53.0。

最佳答案

Amazon API 不喜欢分块上传。文件需要以未分块的方式发送。所以这是有效的代码:

// 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); }
      });
    }
  });
},

关于node.js - 如何使用nodejs请求模块复制curl命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28569366/

相关文章:

ios - 如何在 iOS 中压缩图像?

ios - Safari 或 IOS 中视频的 aws-sdk getSignedUrl 不起作用

java - 如何排查 Amazon S3 GET 请求签名不匹配问题?

javascript - Node.js 类递归发射

java - Playframework 2.3.9 sbt 在 heroku 上构建导入失败

html - 将 CSS 链接到 HTML 背景颜色

PHP实时聊天备份服务器生产问题

ruby-on-rails - 如何获取我的 Heroku 站点的 DNS 记录以与 Google Apps 配合使用?

javascript - 在 node/express 中解析 bool 查询字符串参数的正确方法

javascript - Mocha/Chai expect.to.throw 没有捕捉到抛出的错误