Spaces:
Configuration error
Configuration error
/*! | |
* Copyright 2010 LearnBoost <[email protected]> | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var crypto = require('crypto') | |
, parse = require('url').parse | |
; | |
/** | |
* Valid keys. | |
*/ | |
var keys = | |
[ 'acl' | |
, 'location' | |
, 'logging' | |
, 'notification' | |
, 'partNumber' | |
, 'policy' | |
, 'requestPayment' | |
, 'torrent' | |
, 'uploadId' | |
, 'uploads' | |
, 'versionId' | |
, 'versioning' | |
, 'versions' | |
, 'website' | |
] | |
/** | |
* Return an "Authorization" header value with the given `options` | |
* in the form of "AWS <key>:<signature>" | |
* | |
* @param {Object} options | |
* @return {String} | |
* @api private | |
*/ | |
function authorization (options) { | |
return 'AWS ' + options.key + ':' + sign(options) | |
} | |
module.exports = authorization | |
module.exports.authorization = authorization | |
/** | |
* Simple HMAC-SHA1 Wrapper | |
* | |
* @param {Object} options | |
* @return {String} | |
* @api private | |
*/ | |
function hmacSha1 (options) { | |
return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64') | |
} | |
module.exports.hmacSha1 = hmacSha1 | |
/** | |
* Create a base64 sha1 HMAC for `options`. | |
* | |
* @param {Object} options | |
* @return {String} | |
* @api private | |
*/ | |
function sign (options) { | |
options.message = stringToSign(options) | |
return hmacSha1(options) | |
} | |
module.exports.sign = sign | |
/** | |
* Create a base64 sha1 HMAC for `options`. | |
* | |
* Specifically to be used with S3 presigned URLs | |
* | |
* @param {Object} options | |
* @return {String} | |
* @api private | |
*/ | |
function signQuery (options) { | |
options.message = queryStringToSign(options) | |
return hmacSha1(options) | |
} | |
module.exports.signQuery= signQuery | |
/** | |
* Return a string for sign() with the given `options`. | |
* | |
* Spec: | |
* | |
* <verb>\n | |
* <md5>\n | |
* <content-type>\n | |
* <date>\n | |
* [headers\n] | |
* <resource> | |
* | |
* @param {Object} options | |
* @return {String} | |
* @api private | |
*/ | |
function stringToSign (options) { | |
var headers = options.amazonHeaders || '' | |
if (headers) headers += '\n' | |
var r = | |
[ options.verb | |
, options.md5 | |
, options.contentType | |
, options.date ? options.date.toUTCString() : '' | |
, headers + options.resource | |
] | |
return r.join('\n') | |
} | |
module.exports.stringToSign = stringToSign | |
/** | |
* Return a string for sign() with the given `options`, but is meant exclusively | |
* for S3 presigned URLs | |
* | |
* Spec: | |
* | |
* <date>\n | |
* <resource> | |
* | |
* @param {Object} options | |
* @return {String} | |
* @api private | |
*/ | |
function queryStringToSign (options){ | |
return 'GET\n\n\n' + options.date + '\n' + options.resource | |
} | |
module.exports.queryStringToSign = queryStringToSign | |
/** | |
* Perform the following: | |
* | |
* - ignore non-amazon headers | |
* - lowercase fields | |
* - sort lexicographically | |
* - trim whitespace between ":" | |
* - join with newline | |
* | |
* @param {Object} headers | |
* @return {String} | |
* @api private | |
*/ | |
function canonicalizeHeaders (headers) { | |
var buf = [] | |
, fields = Object.keys(headers) | |
; | |
for (var i = 0, len = fields.length; i < len; ++i) { | |
var field = fields[i] | |
, val = headers[field] | |
, field = field.toLowerCase() | |
; | |
if (0 !== field.indexOf('x-amz')) continue | |
buf.push(field + ':' + val) | |
} | |
return buf.sort().join('\n') | |
} | |
module.exports.canonicalizeHeaders = canonicalizeHeaders | |
/** | |
* Perform the following: | |
* | |
* - ignore non sub-resources | |
* - sort lexicographically | |
* | |
* @param {String} resource | |
* @return {String} | |
* @api private | |
*/ | |
function canonicalizeResource (resource) { | |
var url = parse(resource, true) | |
, path = url.pathname | |
, buf = [] | |
; | |
Object.keys(url.query).forEach(function(key){ | |
if (!~keys.indexOf(key)) return | |
var val = '' == url.query[key] ? '' : '=' + encodeURIComponent(url.query[key]) | |
buf.push(key + val) | |
}) | |
return path + (buf.length ? '?' + buf.sort().join('&') : '') | |
} | |
module.exports.canonicalizeResource = canonicalizeResource | |