diff --git a/dist/index.js b/dist/index.js index ae5a0689..c061abcf 100644 --- a/dist/index.js +++ b/dist/index.js @@ -201,7 +201,7 @@ AWS.util.update(AWS.S3.prototype, { 1) User defined version specified: a) always return user defined version 2) No user defined version specified: - a) default to lowest version the region supports + a) If not using presigned urls, default to V4 b) If using presigned urls, default to lowest version the region supports */ if (userDefinedVersion) { @@ -280,6 +280,7 @@ AWS.util.update(AWS.S3.prototype, { request.addListener('extractError', this.extractError); request.addListener('extractData', AWS.util.hoistPayloadMember); request.addListener('extractData', this.extractData); + request.addListener('extractData', this.extractErrorFrom200Response); request.addListener('beforePresign', this.prepareSignedUrl); if (this.shouldDisableBodySigning(request)) { request.removeListener('afterBuild', AWS.EventListeners.Core.COMPUTE_SHA256); @@ -366,6 +367,12 @@ AWS.util.update(AWS.S3.prototype, { message: 'Access point ARN region is empty' }); } + if (!/[0-9]{12}/.exec(parsedArn.accountId)) { + throw AWS.util.error(new Error(), { + code: 'InvalidAccessPointARN', + message: 'Access point ARN accountID does not match regex "[0-9]{12}"' + }); + } if ( parsedArn.resource.indexOf('accesspoint:') !== 0 && parsedArn.resource.indexOf('accesspoint/') !== 0 @@ -384,7 +391,7 @@ AWS.util.update(AWS.S3.prototype, { } var accessPoint = parsedArn.resource.split(delimiter)[1]; var accessPointPrefix = accessPoint + '-' + parsedArn.accountId; - if (!req.service.isDnsCompatible(accessPointPrefix) || accessPointPrefix.match(/\./)) { + if (!req.service.dnsCompatibleBucketName(accessPointPrefix) || accessPointPrefix.match(/\./)) { throw AWS.util.error(new Error(), { code: 'InvalidAccessPointARN', message: 'Access point ARN is not DNS compatible. Got ' + accessPoint @@ -611,7 +618,7 @@ AWS.util.update(AWS.S3.prototype, { * @api private */ populateUriFromAccessPoint: function populateUriFromAccessPoint(req) { - if (req.service._originalConfig.endpoint) { + if (req.service._originalConfig && req.service._originalConfig.endpoint) { throw AWS.util.error(new Error(), { code: 'InvalidConfiguration', message: 'Custom endpoint is not compatible with access point ARN' @@ -783,7 +790,7 @@ AWS.util.update(AWS.S3.prototype, { if (this.config.s3ForcePathStyle) return true; if (this.config.s3BucketEndpoint) return false; - if (this.isDnsCompatible(bucketName)) { + if (this.dnsCompatibleBucketName(bucketName)) { return (this.config.sslEnabled && bucketName.match(/\./)) ? true : false; } else { return true; // not dns compatible names must always use path style @@ -796,7 +803,7 @@ AWS.util.update(AWS.S3.prototype, { * * @api private */ - isDnsCompatible: function isDnsCompatible(bucketName) { + 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+/); @@ -805,17 +812,31 @@ AWS.util.update(AWS.S3.prototype, { }, /** - * @return [Boolean] whether response contains an error + * For COPY operations, some can be error even with status code 200. + * SDK treats the response as exception when response body indicates + * an exception or body is empty. + * * @api private */ - successfulResponse: function successfulResponse(resp) { - var req = resp.request; + extractErrorFrom200Response: function extractErrorFrom200Response(resp) { + if (!operationsWith200StatusCodeError[resp.request.operation]) return; var httpResponse = resp.httpResponse; - if (operationsWith200StatusCodeError[req.operation] && - httpResponse.body.toString().match('')) { - return false; - } else { - return httpResponse.statusCode < 300; + if (httpResponse.body && httpResponse.body.toString().match('')) { + // Response body with '...' indicates an exception. + // Get S3 client object. In ManagedUpload, this.service refers to + // S3 client object. + resp.data = null; + var service = this.service ? this.service : this; + service.extractError(resp); + throw resp.error; + } else if (!httpResponse.body || !httpResponse.body.toString().match(/<[\w_]/)) { + // When body is empty or incomplete, S3 might stop the request on detecting client + // side aborting the request. + resp.data = null; + throw AWS.util.error(new Error(), { + code: 'InternalError', + message: 'S3 aborted request' + }); } }, @@ -1038,7 +1059,7 @@ AWS.util.update(AWS.S3.prototype, { if (cachedRegion && cachedRegion !== request.httpRequest.region) { service.updateReqBucketRegion(request, cachedRegion); done(); - } else if (!service.isDnsCompatible(bucket)) { + } else if (!service.dnsCompatibleBucketName(bucket)) { service.updateReqBucketRegion(request, 'us-east-1'); if (bucketRegionCache[bucket] !== 'us-east-1') { bucketRegionCache[bucket] = 'us-east-1'; @@ -1477,10 +1498,14 @@ AWS.util.update(AWS.S3.prototype, { params = {}; } var hostname = this.endpoint.hostname; + // copy params so that appending keys does not unintentioinallly + // mutate params object argument passed in by user + var copiedParams = AWS.util.copy(params); + if (hostname !== this.api.globalEndpoint && !params.CreateBucketConfiguration) { - params.CreateBucketConfiguration = { LocationConstraint: this.config.region }; + copiedParams.CreateBucketConfiguration = { LocationConstraint: this.config.region }; } - return this.makeRequest('createBucket', params, callback); + return this.makeRequest('createBucket', copiedParams, callback); }, /** @@ -2422,7 +2447,7 @@ const s3 = new S3({ accessKeyId: AWS_KEY_ID, secretAccessKey: SECRET_ACCESS_KEY }); -const objKey = DESTINATION_DIR === '/' ? `${shortid()}/` : DESTINATION_DIR; +const destinationDir = DESTINATION_DIR === '/' ? shortid() : DESTINATION_DIR; const paths = klawSync(SOURCE_DIR, { nodir: true }); @@ -2437,16 +2462,18 @@ function upload(params) { }); }); } + function run() { + const sourceDir = path.join(process.cwd(), SOURCE_DIR); return Promise.all( paths.map(p => { - const Key = p.path.replace(path.join(process.cwd(), SOURCE_DIR), objKey); const fileStream = fs.createReadStream(p.path); + const bucketPath = path.join(destinationDir, path.relative(sourceDir, p.path)); const params = { Bucket: BUCKET, ACL: 'public-read', Body: fileStream, - Key, + Key: bucketPath, ContentType: lookup(p.path) || 'text/plain' }; return upload(params); @@ -2456,9 +2483,9 @@ function run() { run() .then(locations => { - core.info(`object key - ${objKey}`); + core.info(`object key - ${destinationDir}`); core.info(`object locations - ${locations}`); - core.setOutput('object_key', objKey); + core.setOutput('object_key', destinationDir); core.setOutput('object_locations', locations); }) .catch(err => { @@ -4304,9 +4331,13 @@ var PromisesDependency; * Defaults to `true`. * * @!attribute endpointDiscoveryEnabled - * @return [Boolean] whether to enable endpoint discovery for operations that - * allow optionally using an endpoint returned by the service. - * Defaults to 'false' + * @return [Boolean|undefined] whether to call operations with endpoints + * given by service dynamically. Setting this config to `true` will enable + * endpoint discovery for all applicable operations. Setting it to `false` + * will explicitly disable endpoint discovery even though operations that + * require endpoint discovery will presumably fail. Leaving it to + * `undefined` means SDK only do endpoint discovery when it's required. + * Defaults to `undefined` * * @!attribute endpointCacheSize * @return [Number] the size of the global cache storing endpoints from endpoint @@ -4459,10 +4490,13 @@ AWS.Config = AWS.util.inherit({ * S3 Transfer Acceleration endpoint with the S3 service. Default: `false`. * @option options clientSideMonitoring [Boolean] whether to collect and * publish this client's performance metrics of all its API requests. - * @option options endpointDiscoveryEnabled [Boolean] whether to enable endpoint - * discovery for operations that allow optionally using an endpoint returned by - * the service. - * Defaults to 'false' + * @option options endpointDiscoveryEnabled [Boolean|undefined] whether to + * call operations with endpoints given by service dynamically. Setting this + * config to `true` will enable endpoint discovery for all applicable operations. + * Setting it to `false` will explicitly disable endpoint discovery even though + * operations that require endpoint discovery will presumably fail. Leaving it + * to `undefined` means SDK will only do endpoint discovery when it's required. + * Defaults to `undefined` * @option options endpointCacheSize [Number] the size of the global cache storing * endpoints from endpoint discovery operations. Once endpoint cache is created, * updating this setting cannot change existing cache size. @@ -4693,7 +4727,7 @@ AWS.Config = AWS.util.inherit({ retryDelayOptions: {}, useAccelerateEndpoint: false, clientSideMonitoring: false, - endpointDiscoveryEnabled: false, + endpointDiscoveryEnabled: undefined, endpointCacheSize: 1000, hostPrefixEnabled: true, stsRegionalEndpoints: 'legacy' @@ -5463,2600 +5497,2419 @@ module.exports = {"pagination":{}}; /***/ }), -/***/ 292: -/***/ (function(__unusedmodule, exports, __webpack_require__) { +/***/ 293: +/***/ (function(module) { -;(function (sax) { // wrapper for non-node envs - sax.parser = function (strict, opt) { return new SAXParser(strict, opt) } - sax.SAXParser = SAXParser - sax.SAXStream = SAXStream - sax.createStream = createStream +module.exports = require("buffer"); - // When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns. - // When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)), - // since that's the earliest that a buffer overrun could occur. This way, checks are - // as rare as required, but as often as necessary to ensure never crossing this bound. - // Furthermore, buffers are only tested at most once per write(), so passing a very - // large string into write() might have undesirable effects, but this is manageable by - // the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme - // edge case, result in creating at most one complete copy of the string passed in. - // Set to Infinity to have unlimited buffers. - sax.MAX_BUFFER_LENGTH = 64 * 1024 +/***/ }), - var buffers = [ - 'comment', 'sgmlDecl', 'textNode', 'tagName', 'doctype', - 'procInstName', 'procInstBody', 'entity', 'attribName', - 'attribValue', 'cdata', 'script' - ] +/***/ 304: +/***/ (function(module) { - sax.EVENTS = [ - 'text', - 'processinginstruction', - 'sgmldeclaration', - 'doctype', - 'comment', - 'opentagstart', - 'attribute', - 'opentag', - 'closetag', - 'opencdata', - 'cdata', - 'closecdata', - 'error', - 'end', - 'ready', - 'script', - 'opennamespace', - 'closenamespace' - ] +module.exports = require("string_decoder"); - function SAXParser (strict, opt) { - if (!(this instanceof SAXParser)) { - return new SAXParser(strict, opt) - } +/***/ }), - var parser = this - clearBuffers(parser) - parser.q = parser.c = '' - parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH - parser.opt = opt || {} - parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags - parser.looseCase = parser.opt.lowercase ? 'toLowerCase' : 'toUpperCase' - parser.tags = [] - parser.closed = parser.closedRoot = parser.sawRoot = false - parser.tag = parser.error = null - parser.strict = !!strict - parser.noscript = !!(strict || parser.opt.noscript) - parser.state = S.BEGIN - parser.strictEntities = parser.opt.strictEntities - parser.ENTITIES = parser.strictEntities ? Object.create(sax.XML_ENTITIES) : Object.create(sax.ENTITIES) - parser.attribList = [] +/***/ 306: +/***/ (function(__unusedmodule, __unusedexports, __webpack_require__) { - // namespaces form a prototype chain. - // it always points at the current tag, - // which protos to its parent tag. - if (parser.opt.xmlns) { - parser.ns = Object.create(rootNS) - } +var AWS = __webpack_require__(395); +var STS = __webpack_require__(733); - // mostly just for error reporting - parser.trackPosition = parser.opt.position !== false - if (parser.trackPosition) { - parser.position = parser.line = parser.column = 0 - } - emit(parser, 'onready') - } +/** + * Represents credentials retrieved from STS Web Identity Federation support. + * + * By default this provider gets credentials using the + * {AWS.STS.assumeRoleWithWebIdentity} service operation. This operation + * requires a `RoleArn` containing the ARN of the IAM trust policy for the + * application for which credentials will be given. In addition, the + * `WebIdentityToken` must be set to the token provided by the identity + * provider. See {constructor} for an example on creating a credentials + * object with proper `RoleArn` and `WebIdentityToken` values. + * + * ## Refreshing Credentials from Identity Service + * + * In addition to AWS credentials expiring after a given amount of time, the + * login token from the identity provider will also expire. Once this token + * expires, it will not be usable to refresh AWS credentials, and another + * token will be needed. The SDK does not manage refreshing of the token value, + * but this can be done through a "refresh token" supported by most identity + * providers. Consult the documentation for the identity provider for refreshing + * tokens. Once the refreshed token is acquired, you should make sure to update + * this new token in the credentials object's {params} property. The following + * code will update the WebIdentityToken, assuming you have retrieved an updated + * token from the identity provider: + * + * ```javascript + * AWS.config.credentials.params.WebIdentityToken = updatedToken; + * ``` + * + * Future calls to `credentials.refresh()` will now use the new token. + * + * @!attribute params + * @return [map] the map of params passed to + * {AWS.STS.assumeRoleWithWebIdentity}. To update the token, set the + * `params.WebIdentityToken` property. + * @!attribute data + * @return [map] the raw data response from the call to + * {AWS.STS.assumeRoleWithWebIdentity}. Use this if you want to get + * access to other properties from the response. + */ +AWS.WebIdentityCredentials = AWS.util.inherit(AWS.Credentials, { + /** + * Creates a new credentials object. + * @param (see AWS.STS.assumeRoleWithWebIdentity) + * @example Creating a new credentials object + * AWS.config.credentials = new AWS.WebIdentityCredentials({ + * RoleArn: 'arn:aws:iam::1234567890:role/WebIdentity', + * WebIdentityToken: 'ABCDEFGHIJKLMNOP', // token from identity service + * RoleSessionName: 'web' // optional name, defaults to web-identity + * }, { + * // optionally provide configuration to apply to the underlying AWS.STS service client + * // if configuration is not provided, then configuration will be pulled from AWS.config + * + * // specify timeout options + * httpOptions: { + * timeout: 100 + * } + * }); + * @see AWS.STS.assumeRoleWithWebIdentity + * @see AWS.Config + */ + constructor: function WebIdentityCredentials(params, clientConfig) { + AWS.Credentials.call(this); + this.expired = true; + this.params = params; + this.params.RoleSessionName = this.params.RoleSessionName || 'web-identity'; + this.data = null; + this._clientConfig = AWS.util.copy(clientConfig || {}); + }, - if (!Object.create) { - Object.create = function (o) { - function F () {} - F.prototype = o - var newf = new F() - return newf - } - } + /** + * Refreshes credentials using {AWS.STS.assumeRoleWithWebIdentity} + * + * @callback callback function(err) + * Called when the STS service responds (or fails). When + * this callback is called with no error, it means that the credentials + * information has been loaded into the object (as the `accessKeyId`, + * `secretAccessKey`, and `sessionToken` properties). + * @param err [Error] if an error occurred, this value will be filled + * @see get + */ + refresh: function refresh(callback) { + this.coalesceRefresh(callback || AWS.util.fn.callback); + }, - if (!Object.keys) { - Object.keys = function (o) { - var a = [] - for (var i in o) if (o.hasOwnProperty(i)) a.push(i) - return a + /** + * @api private + */ + load: function load(callback) { + var self = this; + self.createClients(); + self.service.assumeRoleWithWebIdentity(function (err, data) { + self.data = null; + if (!err) { + self.data = data; + self.service.credentialsFrom(data, self); + } + callback(err); + }); + }, + + /** + * @api private + */ + createClients: function() { + if (!this.service) { + var stsConfig = AWS.util.merge({}, this._clientConfig); + stsConfig.params = this.params; + this.service = new STS(stsConfig); } } - function checkBufferLength (parser) { - var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10) - var maxActual = 0 - for (var i = 0, l = buffers.length; i < l; i++) { - var len = parser[buffers[i]].length - if (len > maxAllowed) { - // Text/cdata nodes can get big, and since they're buffered, - // we can get here under normal conditions. - // Avoid issues by emitting the text node now, - // so at least it won't get any bigger. - switch (buffers[i]) { - case 'textNode': - closeText(parser) - break +}); - case 'cdata': - emitNode(parser, 'oncdata', parser.cdata) - parser.cdata = '' - break - case 'script': - emitNode(parser, 'onscript', parser.script) - parser.script = '' - break +/***/ }), - default: - error(parser, 'Max buffer length exceeded: ' + buffers[i]) - } - } - maxActual = Math.max(maxActual, len) - } - // schedule the next check for the earliest possible buffer overrun. - var m = sax.MAX_BUFFER_LENGTH - maxActual - parser.bufferCheckPosition = m + parser.position - } +/***/ 312: +/***/ (function(module, __unusedexports, __webpack_require__) { - function clearBuffers (parser) { - for (var i = 0, l = buffers.length; i < l; i++) { - parser[buffers[i]] = '' - } - } +// Generated by CoffeeScript 1.12.7 +(function() { + var XMLDocument, XMLDocumentCB, XMLStreamWriter, XMLStringWriter, assign, isFunction, ref; - function flushBuffers (parser) { - closeText(parser) - if (parser.cdata !== '') { - emitNode(parser, 'oncdata', parser.cdata) - parser.cdata = '' - } - if (parser.script !== '') { - emitNode(parser, 'onscript', parser.script) - parser.script = '' - } - } + ref = __webpack_require__(582), assign = ref.assign, isFunction = ref.isFunction; - SAXParser.prototype = { - end: function () { end(this) }, - write: write, - resume: function () { this.error = null; return this }, - close: function () { return this.write(null) }, - flush: function () { flushBuffers(this) } - } + XMLDocument = __webpack_require__(559); - var Stream - try { - Stream = __webpack_require__(413).Stream - } catch (ex) { - Stream = function () {} - } + XMLDocumentCB = __webpack_require__(768); - var streamWraps = sax.EVENTS.filter(function (ev) { - return ev !== 'error' && ev !== 'end' - }) + XMLStringWriter = __webpack_require__(750); - function createStream (strict, opt) { - return new SAXStream(strict, opt) - } + XMLStreamWriter = __webpack_require__(458); - function SAXStream (strict, opt) { - if (!(this instanceof SAXStream)) { - return new SAXStream(strict, opt) + module.exports.create = function(name, xmldec, doctype, options) { + var doc, root; + if (name == null) { + throw new Error("Root element needs a name"); + } + options = assign({}, xmldec, doctype, options); + doc = new XMLDocument(options); + root = doc.element(name); + if (!options.headless) { + doc.declaration(options); + if ((options.pubID != null) || (options.sysID != null)) { + doc.doctype(options); + } } + return root; + }; - Stream.apply(this) + module.exports.begin = function(options, onData, onEnd) { + var ref1; + if (isFunction(options)) { + ref1 = [options, onData], onData = ref1[0], onEnd = ref1[1]; + options = {}; + } + if (onData) { + return new XMLDocumentCB(options, onData, onEnd); + } else { + return new XMLDocument(options); + } + }; - this._parser = new SAXParser(strict, opt) - this.writable = true - this.readable = true + module.exports.stringWriter = function(options) { + return new XMLStringWriter(options); + }; - var me = this + module.exports.streamWriter = function(stream, options) { + return new XMLStreamWriter(stream, options); + }; - this._parser.onend = function () { - me.emit('end') - } +}).call(this); - this._parser.onerror = function (er) { - me.emit('error', er) - // if didn't throw, then means error was handled. - // go ahead and clear error, so we can write again. - me._parser.error = null - } +/***/ }), - this._decoder = null +/***/ 315: +/***/ (function(module, __unusedexports, __webpack_require__) { - streamWraps.forEach(function (ev) { - Object.defineProperty(me, 'on' + ev, { - get: function () { - return me._parser['on' + ev] - }, - set: function (h) { - if (!h) { - me.removeAllListeners(ev) - me._parser['on' + ev] = h - return h - } - me.on(ev, h) - }, - enumerable: true, - configurable: false - }) - }) - } +var util = __webpack_require__(153); +var Rest = __webpack_require__(618); +var Json = __webpack_require__(912); +var JsonBuilder = __webpack_require__(337); +var JsonParser = __webpack_require__(806); - SAXStream.prototype = Object.create(Stream.prototype, { - constructor: { - value: SAXStream - } - }) +function populateBody(req) { + var builder = new JsonBuilder(); + var input = req.service.api.operations[req.operation].input; - SAXStream.prototype.write = function (data) { - if (typeof Buffer === 'function' && - typeof Buffer.isBuffer === 'function' && - Buffer.isBuffer(data)) { - if (!this._decoder) { - var SD = __webpack_require__(304).StringDecoder - this._decoder = new SD('utf8') + if (input.payload) { + var params = {}; + var payloadShape = input.members[input.payload]; + params = req.params[input.payload]; + if (params === undefined) return; + + if (payloadShape.type === 'structure') { + req.httpRequest.body = builder.build(params, payloadShape); + applyContentTypeHeader(req); + } else { // non-JSON payload + req.httpRequest.body = params; + if (payloadShape.type === 'binary' || payloadShape.isStreaming) { + applyContentTypeHeader(req, true); } - data = this._decoder.write(data) } - - this._parser.write(data.toString()) - this.emit('data', data) - return true - } - - SAXStream.prototype.end = function (chunk) { - if (chunk && chunk.length) { - this.write(chunk) + } else { + var body = builder.build(req.params, input); + if (body !== '{}' || req.httpRequest.method !== 'GET') { //don't send empty body for GET method + req.httpRequest.body = body; } - this._parser.end() - return true + applyContentTypeHeader(req); } +} - SAXStream.prototype.on = function (ev, handler) { - var me = this - if (!me._parser['on' + ev] && streamWraps.indexOf(ev) !== -1) { - me._parser['on' + ev] = function () { - var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments) - args.splice(0, 0, ev) - me.emit.apply(me, args) - } - } +function applyContentTypeHeader(req, isBinary) { + var operation = req.service.api.operations[req.operation]; + var input = operation.input; - return Stream.prototype.on.call(me, ev, handler) + if (!req.httpRequest.headers['Content-Type']) { + var type = isBinary ? 'binary/octet-stream' : 'application/json'; + req.httpRequest.headers['Content-Type'] = type; } +} - // this really needs to be replaced with character classes. - // XML allows all manner of ridiculous numbers and digits. - var CDATA = '[CDATA[' - var DOCTYPE = 'DOCTYPE' - var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace' - var XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/' - var rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE } +function buildRequest(req) { + Rest.buildRequest(req); - // http://www.w3.org/TR/REC-xml/#NT-NameStartChar - // This implementation works on strings, a single character at a time - // as such, it cannot ever support astral-plane characters (10000-EFFFF) - // without a significant breaking change to either this parser, or the - // JavaScript language. Implementation of an emoji-capable xml parser - // is left as an exercise for the reader. - var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/ + // never send body payload on HEAD/DELETE + if (['HEAD', 'DELETE'].indexOf(req.httpRequest.method) < 0) { + populateBody(req); + } +} - var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/ +function extractError(resp) { + Json.extractError(resp); +} - var entityStart = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/ - var entityBody = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/ +function extractData(resp) { + Rest.extractData(resp); - function isWhitespace (c) { - return c === ' ' || c === '\n' || c === '\r' || c === '\t' - } + var req = resp.request; + var operation = req.service.api.operations[req.operation]; + var rules = req.service.api.operations[req.operation].output || {}; + var parser; + var hasEventOutput = operation.hasEventOutput; - function isQuote (c) { - return c === '"' || c === '\'' + if (rules.payload) { + var payloadMember = rules.members[rules.payload]; + var body = resp.httpResponse.body; + if (payloadMember.isEventStream) { + parser = new JsonParser(); + resp.data[payload] = util.createEventStream( + AWS.HttpClient.streamsApiVersion === 2 ? resp.httpResponse.stream : body, + parser, + payloadMember + ); + } else if (payloadMember.type === 'structure' || payloadMember.type === 'list') { + var parser = new JsonParser(); + resp.data[rules.payload] = parser.parse(body, payloadMember); + } else if (payloadMember.type === 'binary' || payloadMember.isStreaming) { + resp.data[rules.payload] = body; + } else { + resp.data[rules.payload] = payloadMember.toType(body); + } + } else { + var data = resp.data; + Json.extractData(resp); + resp.data = util.merge(data, resp.data); } +} - function isAttribEnd (c) { - return c === '>' || isWhitespace(c) - } +/** + * @api private + */ +module.exports = { + buildRequest: buildRequest, + extractError: extractError, + extractData: extractData +}; - function isMatch (regex, c) { - return regex.test(c) - } - function notMatch (regex, c) { - return !isMatch(regex, c) - } +/***/ }), - var S = 0 - sax.STATE = { - BEGIN: S++, // leading byte order mark or whitespace - BEGIN_WHITESPACE: S++, // leading whitespace - TEXT: S++, // general stuff - TEXT_ENTITY: S++, // & and such. - OPEN_WAKA: S++, // < - SGML_DECL: S++, // - SCRIPT: S++, //