git-off

Log

Files

Refs

README

s3.js (4440B)

     1 var AWS = require('../core');
     2 var inherit = AWS.util.inherit;
     3 
     4 /**
     5  * @api private
     6  */
     7 AWS.Signers.S3 = inherit(AWS.Signers.RequestSigner, {
     8   /**
     9    * When building the stringToSign, these sub resource params should be
    10    * part of the canonical resource string with their NON-decoded values
    11    */
    12   subResources: {
    13     'acl': 1,
    14     'accelerate': 1,
    15     'cors': 1,
    16     'lifecycle': 1,
    17     'delete': 1,
    18     'location': 1,
    19     'logging': 1,
    20     'notification': 1,
    21     'partNumber': 1,
    22     'policy': 1,
    23     'requestPayment': 1,
    24     'replication': 1,
    25     'restore': 1,
    26     'tagging': 1,
    27     'torrent': 1,
    28     'uploadId': 1,
    29     'uploads': 1,
    30     'versionId': 1,
    31     'versioning': 1,
    32     'versions': 1,
    33     'website': 1
    34   },
    35 
    36   // when building the stringToSign, these querystring params should be
    37   // part of the canonical resource string with their NON-encoded values
    38   responseHeaders: {
    39     'response-content-type': 1,
    40     'response-content-language': 1,
    41     'response-expires': 1,
    42     'response-cache-control': 1,
    43     'response-content-disposition': 1,
    44     'response-content-encoding': 1
    45   },
    46 
    47   addAuthorization: function addAuthorization(credentials, date) {
    48     if (!this.request.headers['presigned-expires']) {
    49       this.request.headers['X-Amz-Date'] = AWS.util.date.rfc822(date);
    50     }
    51 
    52     if (credentials.sessionToken) {
    53       // presigned URLs require this header to be lowercased
    54       this.request.headers['x-amz-security-token'] = credentials.sessionToken;
    55     }
    56 
    57     var signature = this.sign(credentials.secretAccessKey, this.stringToSign());
    58     var auth = 'AWS ' + credentials.accessKeyId + ':' + signature;
    59 
    60     this.request.headers['Authorization'] = auth;
    61   },
    62 
    63   stringToSign: function stringToSign() {
    64     var r = this.request;
    65 
    66     var parts = [];
    67     parts.push(r.method);
    68     parts.push(r.headers['Content-MD5'] || '');
    69     parts.push(r.headers['Content-Type'] || '');
    70 
    71     // This is the "Date" header, but we use X-Amz-Date.
    72     // The S3 signing mechanism requires us to pass an empty
    73     // string for this Date header regardless.
    74     parts.push(r.headers['presigned-expires'] || '');
    75 
    76     var headers = this.canonicalizedAmzHeaders();
    77     if (headers) parts.push(headers);
    78     parts.push(this.canonicalizedResource());
    79 
    80     return parts.join('\n');
    81 
    82   },
    83 
    84   canonicalizedAmzHeaders: function canonicalizedAmzHeaders() {
    85 
    86     var amzHeaders = [];
    87 
    88     AWS.util.each(this.request.headers, function (name) {
    89       if (name.match(/^x-amz-/i))
    90         amzHeaders.push(name);
    91     });
    92 
    93     amzHeaders.sort(function (a, b) {
    94       return a.toLowerCase() < b.toLowerCase() ? -1 : 1;
    95     });
    96 
    97     var parts = [];
    98     AWS.util.arrayEach.call(this, amzHeaders, function (name) {
    99       parts.push(name.toLowerCase() + ':' + String(this.request.headers[name]));
   100     });
   101 
   102     return parts.join('\n');
   103 
   104   },
   105 
   106   canonicalizedResource: function canonicalizedResource() {
   107 
   108     var r = this.request;
   109 
   110     var parts = r.path.split('?');
   111     var path = parts[0];
   112     var querystring = parts[1];
   113 
   114     var resource = '';
   115 
   116     if (r.virtualHostedBucket)
   117       resource += '/' + r.virtualHostedBucket;
   118 
   119     resource += path;
   120 
   121     if (querystring) {
   122 
   123       // collect a list of sub resources and query params that need to be signed
   124       var resources = [];
   125 
   126       AWS.util.arrayEach.call(this, querystring.split('&'), function (param) {
   127         var name = param.split('=')[0];
   128         var value = param.split('=')[1];
   129         if (this.subResources[name] || this.responseHeaders[name]) {
   130           var subresource = { name: name };
   131           if (value !== undefined) {
   132             if (this.subResources[name]) {
   133               subresource.value = value;
   134             } else {
   135               subresource.value = decodeURIComponent(value);
   136             }
   137           }
   138           resources.push(subresource);
   139         }
   140       });
   141 
   142       resources.sort(function (a, b) { return a.name < b.name ? -1 : 1; });
   143 
   144       if (resources.length) {
   145 
   146         querystring = [];
   147         AWS.util.arrayEach(resources, function (res) {
   148           if (res.value === undefined) {
   149             querystring.push(res.name);
   150           } else {
   151             querystring.push(res.name + '=' + res.value);
   152           }
   153         });
   154 
   155         resource += '?' + querystring.join('&');
   156       }
   157 
   158     }
   159 
   160     return resource;
   161 
   162   },
   163 
   164   sign: function sign(secret, string) {
   165     return AWS.util.crypto.hmac(secret, string, 'base64', 'sha1');
   166   }
   167 });
   168 
   169 module.exports = AWS.Signers.S3;