presign.js (3485B)
1 var AWS = require('../core'); 2 var inherit = AWS.util.inherit; 3 4 /** 5 * @api private 6 */ 7 var expiresHeader = 'presigned-expires'; 8 9 /** 10 * @api private 11 */ 12 function signedUrlBuilder(request) { 13 var expires = request.httpRequest.headers[expiresHeader]; 14 var signerClass = request.service.getSignerClass(request); 15 16 delete request.httpRequest.headers['User-Agent']; 17 delete request.httpRequest.headers['X-Amz-User-Agent']; 18 19 if (signerClass === AWS.Signers.V4) { 20 if (expires > 604800) { // one week expiry is invalid 21 var message = 'Presigning does not support expiry time greater ' + 22 'than a week with SigV4 signing.'; 23 throw AWS.util.error(new Error(), { 24 code: 'InvalidExpiryTime', message: message, retryable: false 25 }); 26 } 27 request.httpRequest.headers[expiresHeader] = expires; 28 } else if (signerClass === AWS.Signers.S3) { 29 request.httpRequest.headers[expiresHeader] = parseInt( 30 AWS.util.date.unixTimestamp() + expires, 10).toString(); 31 } else { 32 throw AWS.util.error(new Error(), { 33 message: 'Presigning only supports S3 or SigV4 signing.', 34 code: 'UnsupportedSigner', retryable: false 35 }); 36 } 37 } 38 39 /** 40 * @api private 41 */ 42 function signedUrlSigner(request) { 43 var endpoint = request.httpRequest.endpoint; 44 var parsedUrl = AWS.util.urlParse(request.httpRequest.path); 45 var queryParams = {}; 46 47 if (parsedUrl.search) { 48 queryParams = AWS.util.queryStringParse(parsedUrl.search.substr(1)); 49 } 50 51 AWS.util.each(request.httpRequest.headers, function (key, value) { 52 if (key === expiresHeader) key = 'Expires'; 53 if (key.indexOf('x-amz-meta-') === 0) { 54 // Delete existing, potentially not normalized key 55 delete queryParams[key]; 56 key = key.toLowerCase(); 57 } 58 queryParams[key] = value; 59 }); 60 delete request.httpRequest.headers[expiresHeader]; 61 62 var auth = queryParams['Authorization'].split(' '); 63 if (auth[0] === 'AWS') { 64 auth = auth[1].split(':'); 65 queryParams['AWSAccessKeyId'] = auth[0]; 66 queryParams['Signature'] = auth[1]; 67 } else if (auth[0] === 'AWS4-HMAC-SHA256') { // SigV4 signing 68 auth.shift(); 69 var rest = auth.join(' '); 70 var signature = rest.match(/Signature=(.*?)(?:,|\s|\r?\n|$)/)[1]; 71 queryParams['X-Amz-Signature'] = signature; 72 delete queryParams['Expires']; 73 } 74 delete queryParams['Authorization']; 75 delete queryParams['Host']; 76 77 // build URL 78 endpoint.pathname = parsedUrl.pathname; 79 endpoint.search = AWS.util.queryParamsToString(queryParams); 80 } 81 82 /** 83 * @api private 84 */ 85 AWS.Signers.Presign = inherit({ 86 /** 87 * @api private 88 */ 89 sign: function sign(request, expireTime, callback) { 90 request.httpRequest.headers[expiresHeader] = expireTime || 3600; 91 request.on('build', signedUrlBuilder); 92 request.on('sign', signedUrlSigner); 93 request.removeListener('afterBuild', 94 AWS.EventListeners.Core.SET_CONTENT_LENGTH); 95 request.removeListener('afterBuild', 96 AWS.EventListeners.Core.COMPUTE_SHA256); 97 98 request.emit('beforePresign', [request]); 99 100 if (callback) { 101 request.build(function() { 102 if (this.response.error) callback(this.response.error); 103 else { 104 callback(null, AWS.util.urlFormat(request.httpRequest.endpoint)); 105 } 106 }); 107 } else { 108 request.build(); 109 if (request.response.error) throw request.response.error; 110 return AWS.util.urlFormat(request.httpRequest.endpoint); 111 } 112 } 113 }); 114 115 module.exports = AWS.Signers.Presign;