LoginSignup
1
1

More than 5 years have passed since last update.

aws-sdkでRiakCSへのupload時のエラーを回避する方法

Last updated at Posted at 2015-07-06

aws-sdkを使ってRiakCSにマルチパードアップロードするときに403エラーでハマった時のメモ。

原因

lib/signers/s3.js内でsignatureを生成する際に、uploadIdに含まれる=%3Dにエスケープされているせいで認証に失敗してしまっている様子。

回避策

途中で%3D=に戻してあげる

aws-sdk-custom.js
'use strict';

var AWS = require('aws-sdk');
var inherit = AWS.util.inherit;

/**
 * @api private
 */
AWS.Signers.S3 = inherit(AWS.Signers.S3, {
  canonicalizedResource: function canonicalizedResource() {

    var r = this.request;

    var parts = r.path.split('?');
    var path = parts[0];
    var querystring = parts[1];

    var resource = '';

    if (r.virtualHostedBucket)
      resource += '/' + r.virtualHostedBucket;

    resource += path;

    if (querystring) {

      // collect a list of sub resources and query params that need to be signed
      var resources = [];

      AWS.util.arrayEach.call(this, querystring.split('&'), function (param) {
        var name = param.split('=')[0];
        var value = param.split('=')[1];
        if (this.subResources[name] || this.responseHeaders[name]) {
          var subresource = { name: name };
          if (value !== undefined) {
            if (this.subResources[name]) {
              subresource.value = value;
            } else {
              subresource.value = decodeURIComponent(value);
            }
          }
          resources.push(subresource);
        }
      });

      resources.sort(function (a, b) { return a.name < b.name ? -1 : 1; });

      if (resources.length) {

        querystring = [];
        AWS.util.arrayEach(resources, function (res) {
          if (res.value === undefined)
            querystring.push(res.name);
          else {
            // '%3D'を'='に置換
            if (res.name === 'uploadId') {
              res.value = res.value.replace(/%3D/g, '=');
            }
            querystring.push(res.name + '=' + res.value);
          }
        });

        resource += '?' + querystring.join('&');
      }

    }

    return resource;

  },
});

module.exports = AWS;

使用例

demo.js
var fs = require('fs');
var AWS = require('./aws-sdk-custom');
var config = require('./config.json');
var s3 = new AWS.S3(config);

var params = {
  Bucket: 'bucket',
  Key: 'key',
  Body: fs.createReadStream('./bigfile')
};

s3.upload(params, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else     console.log(data);           // successful response
});

もっといい方法がある気がする。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1