%PDF- %PDF-
Direktori : /home/opti/workflow/node_modules/aws-sdk/lib/services/ |
Current File : /home/opti/workflow/node_modules/aws-sdk/lib/services/s3.js |
var AWS = require('../core'); AWS.util.update(AWS.S3.prototype, { /** * @api private */ validateService: function validateService() { // default to us-east-1 when no region is provided if (!this.config.region) this.config.region = 'us-east-1'; }, /** * @api private */ setupRequestListeners: function setupRequestListeners(request) { request.addListener('build', this.addContentType); request.addListener('build', this.populateURI); request.addListener('build', this.computeContentMd5); request.addListener('build', this.computeSha256); request.addListener('build', this.computeSseCustomerKeyMd5); request.removeListener('validate', AWS.EventListeners.Core.VALIDATE_REGION); request.addListener('extractError', this.extractError); request.addListener('extractData', this.extractData); request.addListener('beforePresign', this.prepareSignedUrl); }, /** * S3 prefers dns-compatible bucket names to be moved from the uri path * to the hostname as a sub-domain. This is not possible, even for dns-compat * buckets when using SSL and the bucket name contains a dot ('.'). The * ssl wildcard certificate is only 1-level deep. * * @api private */ populateURI: function populateURI(req) { var httpRequest = req.httpRequest; var b = req.params.Bucket; if (b) { if (!req.service.pathStyleBucketName(b)) { httpRequest.endpoint.hostname = b + '.' + httpRequest.endpoint.hostname; var port = httpRequest.endpoint.port; if (port !== 80 && port !== 443) { httpRequest.endpoint.host = httpRequest.endpoint.hostname + ':' + httpRequest.endpoint.port; } else { httpRequest.endpoint.host = httpRequest.endpoint.hostname; } httpRequest.virtualHostedBucket = b; // needed for signing the request httpRequest.path = httpRequest.path.replace(new RegExp('/' + b), ''); if (httpRequest.path[0] !== '/') { httpRequest.path = '/' + httpRequest.path; } } } }, /** * Adds a default content type if none is supplied. * * @api private */ addContentType: function addContentType(req) { var httpRequest = req.httpRequest; if (!httpRequest.headers['Content-Type']) { // always have a Content-Type httpRequest.headers['Content-Type'] = 'application/octet-stream'; } var contentType = httpRequest.headers['Content-Type']; if (AWS.util.isBrowser()) { if (typeof httpRequest.body === 'string' && !contentType.match(/;\s*charset=/)) { var charset = '; charset=UTF-8'; httpRequest.headers['Content-Type'] += charset; } else { var replaceFn = function(_, prefix, charset) { return prefix + charset.toUpperCase(); }; httpRequest.headers['Content-Type'] = contentType.replace(/(;\s*charset=)(.+)$/, replaceFn); } } }, /** * @api private */ computableChecksumOperations: { putBucketCors: true, putBucketLifecycle: true, putBucketTagging: true, deleteObjects: true }, /** * Checks whether checksums should be computed for the request. * If the request requires checksums to be computed, this will always * return true, otherwise it depends on whether {AWS.Config.computeChecksums} * is set. * * @param req [AWS.Request] the request to check against * @return [Boolean] whether to compute checksums for a request. * @api private */ willComputeChecksums: function willComputeChecksums(req) { if (this.computableChecksumOperations[req.operation]) return true; if (!this.config.computeChecksums) return false; // TODO: compute checksums for Stream objects if (!AWS.util.Buffer.isBuffer(req.httpRequest.body) && typeof req.httpRequest.body !== 'string') { return false; } var rules = req.service.api.operations[req.operation].input.members; // V4 signer uses SHA256 signatures so only compute MD5 if it is required if (req.service.getSignerClass(req) === AWS.Signers.V4) { if (rules.ContentMD5 && !rules.ContentMD5.required) return false; } if (rules.ContentMD5 && !req.params.ContentMD5) return true; }, /** * A listener that computes the Content-MD5 and sets it in the header. * @see AWS.S3.willComputeChecksums * @api private */ computeContentMd5: function computeContentMd5(req) { if (req.service.willComputeChecksums(req)) { var md5 = AWS.util.crypto.md5(req.httpRequest.body, 'base64'); req.httpRequest.headers['Content-MD5'] = md5; } }, /** * @api private */ computeSha256: function computeSha256(req) { if (req.service.getSignerClass(req) === AWS.Signers.V4) { req.httpRequest.headers['X-Amz-Content-Sha256'] = AWS.util.crypto.sha256(req.httpRequest.body || '', 'hex'); } }, /** * @api private */ computeSseCustomerKeyMd5: function computeSseCustomerKeyMd5(req) { var headers = [ 'x-amz-server-side-encryption-customer-key', 'x-amz-copy-source-server-side-encryption-customer-key' ]; AWS.util.arrayEach(headers, function(header) { if (req.httpRequest.headers[header]) { var key = req.httpRequest.headers[header]; var md5header = header + '-MD5'; req.httpRequest.headers[header] = AWS.util.base64.encode(key); if (!req.httpRequest.headers[md5header]) { var value = AWS.util.crypto.md5(key, 'base64'); req.httpRequest.headers[md5header] = AWS.util.base64.encode(value); } } }); }, /** * Returns true if the bucket name should be left in the URI path for * a request to S3. This function takes into account the current * endpoint protocol (e.g. http or https). * * @api private */ pathStyleBucketName: function pathStyleBucketName(bucketName) { // user can force path style requests via the configuration if (this.config.s3ForcePathStyle) return true; if (this.dnsCompatibleBucketName(bucketName)) { return (this.config.sslEnabled && bucketName.match(/\./)) ? true : false; } else { return true; // not dns compatible names must always use path style } }, /** * Returns true if the bucket name is DNS compatible. Buckets created * outside of the classic region MUST be DNS compatible. * * @api private */ dnsCompatibleBucketName: function dnsCompatibleBucketName(bucketName) { var b = bucketName; var domain = new RegExp(/^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/); var ipAddress = new RegExp(/(\d+\.){3}\d+/); var dots = new RegExp(/\.\./); return (b.match(domain) && !b.match(ipAddress) && !b.match(dots)) ? true : false; }, /** * S3 requires that path params not escape forward slashes. * * @api private */ escapePathParam: function escapePathParam(value) { return AWS.util.uriEscapePath(String(value)); }, /** * @return [Boolean] whether response contains an error * @api private */ successfulResponse: function successfulResponse(resp) { var req = resp.request; var httpResponse = resp.httpResponse; if (req.operation === 'completeMultipartUpload' && httpResponse.body.toString().match('<Error>')) return false; else return httpResponse.statusCode < 300; }, /** * @return [Boolean] whether the error can be retried * @api private */ retryableError: function retryableError(error, request) { if (request.operation === 'completeMultipartUpload' && error.statusCode === 200) { return true; } else if (error && error.code === 'RequestTimeout') { return true; } else { var _super = AWS.Service.prototype.retryableError; return _super.call(this, error, request); } }, /** * Provides a specialized parser for getBucketLocation -- all other * operations are parsed by the super class. * * @api private */ extractData: function extractData(resp) { var req = resp.request; if (req.operation === 'getBucketLocation') { var match = resp.httpResponse.body.toString().match(/>(.+)<\/Location/); if (match) { delete resp.data['_']; resp.data.LocationConstraint = match[1]; } } }, /** * Extracts an error object from the http response. * * @api private */ extractError: function extractError(resp) { var codes = { 304: 'NotModified', 403: 'Forbidden', 400: 'BadRequest', 404: 'NotFound' }; var code = resp.httpResponse.statusCode; var body = resp.httpResponse.body; if (codes[code] && body.length === 0) { resp.error = AWS.util.error(new Error(), { code: codes[resp.httpResponse.statusCode], message: null }); } else { var data = new AWS.XML.Parser().parse(body.toString()); resp.error = AWS.util.error(new Error(), { code: data.Code || code, message: data.Message || null }); } }, /** * Get a pre-signed URL for a given operation name. * * @note You must ensure that you have static or previously resolved * credentials if you call this method synchronously (with no callback), * otherwise it may not properly sign the request. If you cannot guarantee * this (you are using an asynchronous credential provider, i.e., EC2 * IAM roles), you should always call this method with an asynchronous * callback. * @param operation [String] the name of the operation to call * @param params [map] parameters to pass to the operation. See the given * operation for the expected operation parameters. In addition, you can * also pass the "Expires" parameter to inform S3 how long the URL should * work for. * @option params Expires [Integer] (900) the number of seconds to expire * the pre-signed URL operation in. Defaults to 15 minutes. * @param callback [Function] if a callback is provided, this function will * pass the URL as the second parameter (after the error parameter) to * the callback function. * @return [String] if called synchronously (with no callback), returns the * signed URL. * @return [null] nothing is returned if a callback is provided. * @example Pre-signing a getObject operation (synchronously) * var params = {Bucket: 'bucket', Key: 'key'}; * var url = s3.getSignedUrl('getObject', params); * console.log('The URL is', url); * @example Pre-signing a putObject (asynchronously) * var params = {Bucket: 'bucket', Key: 'key'}; * s3.getSignedUrl('putObject', params, function (err, url) { * console.log('The URL is', url); * }); * @example Pre-signing a putObject operation with a specific payload * var params = {Bucket: 'bucket', Key: 'key', Body: 'body'}; * var url = s3.getSignedUrl('putObject', params); * console.log('The URL is', url); * @example Passing in a 1-minute expiry time for a pre-signed URL * var params = {Bucket: 'bucket', Key: 'key', Expires: 60}; * var url = s3.getSignedUrl('getObject', params); * console.log('The URL is', url); // expires in 60 seconds */ getSignedUrl: function getSignedUrl(operation, params, callback) { params = AWS.util.copy(params || {}); var expires = params.Expires || 900; delete params.Expires; // we can't validate this var request = this.makeRequest(operation, params); return request.presign(expires, callback); }, /** * @api private */ prepareSignedUrl: function prepareSignedUrl(request) { request.removeListener('build', request.service.addContentType); if (!request.params.Body) { // no Content-MD5/SHA-256 if body is not provided request.removeListener('build', request.service.computeContentMd5); request.removeListener('build', request.service.computeSha256); } }, createBucket: function createBucket(params, callback) { // When creating a bucket *outside* the classic region, the location // constraint must be set for the bucket and it must match the endpoint. // This chunk of code will set the location constraint param based // on the region (when possible), but it will not override a passed-in // location constraint. if (!params) params = {}; var hostname = this.endpoint.hostname; if (hostname !== this.api.globalEndpoint && !params.CreateBucketConfiguration) { params.CreateBucketConfiguration = { LocationConstraint: this.config.region }; } return this.makeRequest('createBucket', params, callback); } });