123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809 |
- var AWS = require('./core');
- var AcceptorStateMachine = require('./state_machine');
- var inherit = AWS.util.inherit;
- var domain = AWS.util.domain;
- var jmespath = require('jmespath');
- /**
- * @api private
- */
- var hardErrorStates = {success: 1, error: 1, complete: 1};
- function isTerminalState(machine) {
- return Object.prototype.hasOwnProperty.call(hardErrorStates, machine._asm.currentState);
- }
- var fsm = new AcceptorStateMachine();
- fsm.setupStates = function() {
- var transition = function(_, done) {
- var self = this;
- self._haltHandlersOnError = false;
- self.emit(self._asm.currentState, function(err) {
- if (err) {
- if (isTerminalState(self)) {
- if (domain && self.domain instanceof domain.Domain) {
- err.domainEmitter = self;
- err.domain = self.domain;
- err.domainThrown = false;
- self.domain.emit('error', err);
- } else {
- throw err;
- }
- } else {
- self.response.error = err;
- done(err);
- }
- } else {
- done(self.response.error);
- }
- });
- };
- this.addState('validate', 'build', 'error', transition);
- this.addState('build', 'afterBuild', 'restart', transition);
- this.addState('afterBuild', 'sign', 'restart', transition);
- this.addState('sign', 'send', 'retry', transition);
- this.addState('retry', 'afterRetry', 'afterRetry', transition);
- this.addState('afterRetry', 'sign', 'error', transition);
- this.addState('send', 'validateResponse', 'retry', transition);
- this.addState('validateResponse', 'extractData', 'extractError', transition);
- this.addState('extractError', 'extractData', 'retry', transition);
- this.addState('extractData', 'success', 'retry', transition);
- this.addState('restart', 'build', 'error', transition);
- this.addState('success', 'complete', 'complete', transition);
- this.addState('error', 'complete', 'complete', transition);
- this.addState('complete', null, null, transition);
- };
- fsm.setupStates();
- /**
- * ## Asynchronous Requests
- *
- * All requests made through the SDK are asynchronous and use a
- * callback interface. Each service method that kicks off a request
- * returns an `AWS.Request` object that you can use to register
- * callbacks.
- *
- * For example, the following service method returns the request
- * object as "request", which can be used to register callbacks:
- *
- * ```javascript
- * // request is an AWS.Request object
- * var request = ec2.describeInstances();
- *
- * // register callbacks on request to retrieve response data
- * request.on('success', function(response) {
- * console.log(response.data);
- * });
- * ```
- *
- * When a request is ready to be sent, the {send} method should
- * be called:
- *
- * ```javascript
- * request.send();
- * ```
- *
- * Since registered callbacks may or may not be idempotent, requests should only
- * be sent once. To perform the same operation multiple times, you will need to
- * create multiple request objects, each with its own registered callbacks.
- *
- * ## Removing Default Listeners for Events
- *
- * Request objects are built with default listeners for the various events,
- * depending on the service type. In some cases, you may want to remove
- * some built-in listeners to customize behaviour. Doing this requires
- * access to the built-in listener functions, which are exposed through
- * the {AWS.EventListeners.Core} namespace. For instance, you may
- * want to customize the HTTP handler used when sending a request. In this
- * case, you can remove the built-in listener associated with the 'send'
- * event, the {AWS.EventListeners.Core.SEND} listener and add your own.
- *
- * ## Multiple Callbacks and Chaining
- *
- * You can register multiple callbacks on any request object. The
- * callbacks can be registered for different events, or all for the
- * same event. In addition, you can chain callback registration, for
- * example:
- *
- * ```javascript
- * request.
- * on('success', function(response) {
- * console.log("Success!");
- * }).
- * on('error', function(error, response) {
- * console.log("Error!");
- * }).
- * on('complete', function(response) {
- * console.log("Always!");
- * }).
- * send();
- * ```
- *
- * The above example will print either "Success! Always!", or "Error! Always!",
- * depending on whether the request succeeded or not.
- *
- * @!attribute httpRequest
- * @readonly
- * @!group HTTP Properties
- * @return [AWS.HttpRequest] the raw HTTP request object
- * containing request headers and body information
- * sent by the service.
- *
- * @!attribute startTime
- * @readonly
- * @!group Operation Properties
- * @return [Date] the time that the request started
- *
- * @!group Request Building Events
- *
- * @!event validate(request)
- * Triggered when a request is being validated. Listeners
- * should throw an error if the request should not be sent.
- * @param request [Request] the request object being sent
- * @see AWS.EventListeners.Core.VALIDATE_CREDENTIALS
- * @see AWS.EventListeners.Core.VALIDATE_REGION
- * @example Ensuring that a certain parameter is set before sending a request
- * var req = s3.putObject(params);
- * req.on('validate', function() {
- * if (!req.params.Body.match(/^Hello\s/)) {
- * throw new Error('Body must start with "Hello "');
- * }
- * });
- * req.send(function(err, data) { ... });
- *
- * @!event build(request)
- * Triggered when the request payload is being built. Listeners
- * should fill the necessary information to send the request
- * over HTTP.
- * @param (see AWS.Request~validate)
- * @example Add a custom HTTP header to a request
- * var req = s3.putObject(params);
- * req.on('build', function() {
- * req.httpRequest.headers['Custom-Header'] = 'value';
- * });
- * req.send(function(err, data) { ... });
- *
- * @!event sign(request)
- * Triggered when the request is being signed. Listeners should
- * add the correct authentication headers and/or adjust the body,
- * depending on the authentication mechanism being used.
- * @param (see AWS.Request~validate)
- *
- * @!group Request Sending Events
- *
- * @!event send(response)
- * Triggered when the request is ready to be sent. Listeners
- * should call the underlying transport layer to initiate
- * the sending of the request.
- * @param response [Response] the response object
- * @context [Request] the request object that was sent
- * @see AWS.EventListeners.Core.SEND
- *
- * @!event retry(response)
- * Triggered when a request failed and might need to be retried or redirected.
- * If the response is retryable, the listener should set the
- * `response.error.retryable` property to `true`, and optionally set
- * `response.error.retryDelay` to the millisecond delay for the next attempt.
- * In the case of a redirect, `response.error.redirect` should be set to
- * `true` with `retryDelay` set to an optional delay on the next request.
- *
- * If a listener decides that a request should not be retried,
- * it should set both `retryable` and `redirect` to false.
- *
- * Note that a retryable error will be retried at most
- * {AWS.Config.maxRetries} times (based on the service object's config).
- * Similarly, a request that is redirected will only redirect at most
- * {AWS.Config.maxRedirects} times.
- *
- * @param (see AWS.Request~send)
- * @context (see AWS.Request~send)
- * @example Adding a custom retry for a 404 response
- * request.on('retry', function(response) {
- * // this resource is not yet available, wait 10 seconds to get it again
- * if (response.httpResponse.statusCode === 404 && response.error) {
- * response.error.retryable = true; // retry this error
- * response.error.retryDelay = 10000; // wait 10 seconds
- * }
- * });
- *
- * @!group Data Parsing Events
- *
- * @!event extractError(response)
- * Triggered on all non-2xx requests so that listeners can extract
- * error details from the response body. Listeners to this event
- * should set the `response.error` property.
- * @param (see AWS.Request~send)
- * @context (see AWS.Request~send)
- *
- * @!event extractData(response)
- * Triggered in successful requests to allow listeners to
- * de-serialize the response body into `response.data`.
- * @param (see AWS.Request~send)
- * @context (see AWS.Request~send)
- *
- * @!group Completion Events
- *
- * @!event success(response)
- * Triggered when the request completed successfully.
- * `response.data` will contain the response data and
- * `response.error` will be null.
- * @param (see AWS.Request~send)
- * @context (see AWS.Request~send)
- *
- * @!event error(error, response)
- * Triggered when an error occurs at any point during the
- * request. `response.error` will contain details about the error
- * that occurred. `response.data` will be null.
- * @param error [Error] the error object containing details about
- * the error that occurred.
- * @param (see AWS.Request~send)
- * @context (see AWS.Request~send)
- *
- * @!event complete(response)
- * Triggered whenever a request cycle completes. `response.error`
- * should be checked, since the request may have failed.
- * @param (see AWS.Request~send)
- * @context (see AWS.Request~send)
- *
- * @!group HTTP Events
- *
- * @!event httpHeaders(statusCode, headers, response, statusMessage)
- * Triggered when headers are sent by the remote server
- * @param statusCode [Integer] the HTTP response code
- * @param headers [map<String,String>] the response headers
- * @param (see AWS.Request~send)
- * @param statusMessage [String] A status message corresponding to the HTTP
- * response code
- * @context (see AWS.Request~send)
- *
- * @!event httpData(chunk, response)
- * Triggered when data is sent by the remote server
- * @param chunk [Buffer] the buffer data containing the next data chunk
- * from the server
- * @param (see AWS.Request~send)
- * @context (see AWS.Request~send)
- * @see AWS.EventListeners.Core.HTTP_DATA
- *
- * @!event httpUploadProgress(progress, response)
- * Triggered when the HTTP request has uploaded more data
- * @param progress [map] An object containing the `loaded` and `total` bytes
- * of the request.
- * @param (see AWS.Request~send)
- * @context (see AWS.Request~send)
- * @note This event will not be emitted in Node.js 0.8.x.
- *
- * @!event httpDownloadProgress(progress, response)
- * Triggered when the HTTP request has downloaded more data
- * @param progress [map] An object containing the `loaded` and `total` bytes
- * of the request.
- * @param (see AWS.Request~send)
- * @context (see AWS.Request~send)
- * @note This event will not be emitted in Node.js 0.8.x.
- *
- * @!event httpError(error, response)
- * Triggered when the HTTP request failed
- * @param error [Error] the error object that was thrown
- * @param (see AWS.Request~send)
- * @context (see AWS.Request~send)
- *
- * @!event httpDone(response)
- * Triggered when the server is finished sending data
- * @param (see AWS.Request~send)
- * @context (see AWS.Request~send)
- *
- * @see AWS.Response
- */
- AWS.Request = inherit({
- /**
- * Creates a request for an operation on a given service with
- * a set of input parameters.
- *
- * @param service [AWS.Service] the service to perform the operation on
- * @param operation [String] the operation to perform on the service
- * @param params [Object] parameters to send to the operation.
- * See the operation's documentation for the format of the
- * parameters.
- */
- constructor: function Request(service, operation, params) {
- var endpoint = service.endpoint;
- var region = service.config.region;
- var customUserAgent = service.config.customUserAgent;
- if (service.signingRegion) {
- region = service.signingRegion;
- } else if (service.isGlobalEndpoint) {
- region = 'us-east-1';
- }
- this.domain = domain && domain.active;
- this.service = service;
- this.operation = operation;
- this.params = params || {};
- this.httpRequest = new AWS.HttpRequest(endpoint, region);
- this.httpRequest.appendToUserAgent(customUserAgent);
- this.startTime = service.getSkewCorrectedDate();
- this.response = new AWS.Response(this);
- this._asm = new AcceptorStateMachine(fsm.states, 'validate');
- this._haltHandlersOnError = false;
- AWS.SequentialExecutor.call(this);
- this.emit = this.emitEvent;
- },
- /**
- * @!group Sending a Request
- */
- /**
- * @overload send(callback = null)
- * Sends the request object.
- *
- * @callback callback function(err, data)
- * If a callback is supplied, it is called when a response is returned
- * from the service.
- * @context [AWS.Request] the request object being sent.
- * @param err [Error] the error object returned from the request.
- * Set to `null` if the request is successful.
- * @param data [Object] the de-serialized data returned from
- * the request. Set to `null` if a request error occurs.
- * @example Sending a request with a callback
- * request = s3.putObject({Bucket: 'bucket', Key: 'key'});
- * request.send(function(err, data) { console.log(err, data); });
- * @example Sending a request with no callback (using event handlers)
- * request = s3.putObject({Bucket: 'bucket', Key: 'key'});
- * request.on('complete', function(response) { ... }); // register a callback
- * request.send();
- */
- send: function send(callback) {
- if (callback) {
- // append to user agent
- this.httpRequest.appendToUserAgent('callback');
- this.on('complete', function (resp) {
- callback.call(resp, resp.error, resp.data);
- });
- }
- this.runTo();
- return this.response;
- },
- /**
- * @!method promise()
- * Sends the request and returns a 'thenable' promise.
- *
- * Two callbacks can be provided to the `then` method on the returned promise.
- * The first callback will be called if the promise is fulfilled, and the second
- * callback will be called if the promise is rejected.
- * @callback fulfilledCallback function(data)
- * Called if the promise is fulfilled.
- * @param data [Object] the de-serialized data returned from the request.
- * @callback rejectedCallback function(error)
- * Called if the promise is rejected.
- * @param error [Error] the error object returned from the request.
- * @return [Promise] A promise that represents the state of the request.
- * @example Sending a request using promises.
- * var request = s3.putObject({Bucket: 'bucket', Key: 'key'});
- * var result = request.promise();
- * result.then(function(data) { ... }, function(error) { ... });
- */
- /**
- * @api private
- */
- build: function build(callback) {
- return this.runTo('send', callback);
- },
- /**
- * @api private
- */
- runTo: function runTo(state, done) {
- this._asm.runTo(state, done, this);
- return this;
- },
- /**
- * Aborts a request, emitting the error and complete events.
- *
- * @!macro nobrowser
- * @example Aborting a request after sending
- * var params = {
- * Bucket: 'bucket', Key: 'key',
- * Body: Buffer.alloc(1024 * 1024 * 5) // 5MB payload
- * };
- * var request = s3.putObject(params);
- * request.send(function (err, data) {
- * if (err) console.log("Error:", err.code, err.message);
- * else console.log(data);
- * });
- *
- * // abort request in 1 second
- * setTimeout(request.abort.bind(request), 1000);
- *
- * // prints "Error: RequestAbortedError Request aborted by user"
- * @return [AWS.Request] the same request object, for chaining.
- * @since v1.4.0
- */
- abort: function abort() {
- this.removeAllListeners('validateResponse');
- this.removeAllListeners('extractError');
- this.on('validateResponse', function addAbortedError(resp) {
- resp.error = AWS.util.error(new Error('Request aborted by user'), {
- code: 'RequestAbortedError', retryable: false
- });
- });
- if (this.httpRequest.stream && !this.httpRequest.stream.didCallback) { // abort HTTP stream
- this.httpRequest.stream.abort();
- if (this.httpRequest._abortCallback) {
- this.httpRequest._abortCallback();
- } else {
- this.removeAllListeners('send'); // haven't sent yet, so let's not
- }
- }
- return this;
- },
- /**
- * Iterates over each page of results given a pageable request, calling
- * the provided callback with each page of data. After all pages have been
- * retrieved, the callback is called with `null` data.
- *
- * @note This operation can generate multiple requests to a service.
- * @example Iterating over multiple pages of objects in an S3 bucket
- * var pages = 1;
- * s3.listObjects().eachPage(function(err, data) {
- * if (err) return;
- * console.log("Page", pages++);
- * console.log(data);
- * });
- * @example Iterating over multiple pages with an asynchronous callback
- * s3.listObjects(params).eachPage(function(err, data, done) {
- * doSomethingAsyncAndOrExpensive(function() {
- * // The next page of results isn't fetched until done is called
- * done();
- * });
- * });
- * @callback callback function(err, data, [doneCallback])
- * Called with each page of resulting data from the request. If the
- * optional `doneCallback` is provided in the function, it must be called
- * when the callback is complete.
- *
- * @param err [Error] an error object, if an error occurred.
- * @param data [Object] a single page of response data. If there is no
- * more data, this object will be `null`.
- * @param doneCallback [Function] an optional done callback. If this
- * argument is defined in the function declaration, it should be called
- * when the next page is ready to be retrieved. This is useful for
- * controlling serial pagination across asynchronous operations.
- * @return [Boolean] if the callback returns `false`, pagination will
- * stop.
- *
- * @see AWS.Request.eachItem
- * @see AWS.Response.nextPage
- * @since v1.4.0
- */
- eachPage: function eachPage(callback) {
- // Make all callbacks async-ish
- callback = AWS.util.fn.makeAsync(callback, 3);
- function wrappedCallback(response) {
- callback.call(response, response.error, response.data, function (result) {
- if (result === false) return;
- if (response.hasNextPage()) {
- response.nextPage().on('complete', wrappedCallback).send();
- } else {
- callback.call(response, null, null, AWS.util.fn.noop);
- }
- });
- }
- this.on('complete', wrappedCallback).send();
- },
- /**
- * Enumerates over individual items of a request, paging the responses if
- * necessary.
- *
- * @api experimental
- * @since v1.4.0
- */
- eachItem: function eachItem(callback) {
- var self = this;
- function wrappedCallback(err, data) {
- if (err) return callback(err, null);
- if (data === null) return callback(null, null);
- var config = self.service.paginationConfig(self.operation);
- var resultKey = config.resultKey;
- if (Array.isArray(resultKey)) resultKey = resultKey[0];
- var items = jmespath.search(data, resultKey);
- var continueIteration = true;
- AWS.util.arrayEach(items, function(item) {
- continueIteration = callback(null, item);
- if (continueIteration === false) {
- return AWS.util.abort;
- }
- });
- return continueIteration;
- }
- this.eachPage(wrappedCallback);
- },
- /**
- * @return [Boolean] whether the operation can return multiple pages of
- * response data.
- * @see AWS.Response.eachPage
- * @since v1.4.0
- */
- isPageable: function isPageable() {
- return this.service.paginationConfig(this.operation) ? true : false;
- },
- /**
- * Sends the request and converts the request object into a readable stream
- * that can be read from or piped into a writable stream.
- *
- * @note The data read from a readable stream contains only
- * the raw HTTP body contents.
- * @example Manually reading from a stream
- * request.createReadStream().on('data', function(data) {
- * console.log("Got data:", data.toString());
- * });
- * @example Piping a request body into a file
- * var out = fs.createWriteStream('/path/to/outfile.jpg');
- * s3.service.getObject(params).createReadStream().pipe(out);
- * @return [Stream] the readable stream object that can be piped
- * or read from (by registering 'data' event listeners).
- * @!macro nobrowser
- */
- createReadStream: function createReadStream() {
- var streams = AWS.util.stream;
- var req = this;
- var stream = null;
- if (AWS.HttpClient.streamsApiVersion === 2) {
- stream = new streams.PassThrough();
- process.nextTick(function() { req.send(); });
- } else {
- stream = new streams.Stream();
- stream.readable = true;
- stream.sent = false;
- stream.on('newListener', function(event) {
- if (!stream.sent && event === 'data') {
- stream.sent = true;
- process.nextTick(function() { req.send(); });
- }
- });
- }
- this.on('error', function(err) {
- stream.emit('error', err);
- });
- this.on('httpHeaders', function streamHeaders(statusCode, headers, resp) {
- if (statusCode < 300) {
- req.removeListener('httpData', AWS.EventListeners.Core.HTTP_DATA);
- req.removeListener('httpError', AWS.EventListeners.Core.HTTP_ERROR);
- req.on('httpError', function streamHttpError(error) {
- resp.error = error;
- resp.error.retryable = false;
- });
- var shouldCheckContentLength = false;
- var expectedLen;
- if (req.httpRequest.method !== 'HEAD') {
- expectedLen = parseInt(headers['content-length'], 10);
- }
- if (expectedLen !== undefined && !isNaN(expectedLen) && expectedLen >= 0) {
- shouldCheckContentLength = true;
- var receivedLen = 0;
- }
- var checkContentLengthAndEmit = function checkContentLengthAndEmit() {
- if (shouldCheckContentLength && receivedLen !== expectedLen) {
- stream.emit('error', AWS.util.error(
- new Error('Stream content length mismatch. Received ' +
- receivedLen + ' of ' + expectedLen + ' bytes.'),
- { code: 'StreamContentLengthMismatch' }
- ));
- } else if (AWS.HttpClient.streamsApiVersion === 2) {
- stream.end();
- } else {
- stream.emit('end');
- }
- };
- var httpStream = resp.httpResponse.createUnbufferedStream();
- if (AWS.HttpClient.streamsApiVersion === 2) {
- if (shouldCheckContentLength) {
- var lengthAccumulator = new streams.PassThrough();
- lengthAccumulator._write = function(chunk) {
- if (chunk && chunk.length) {
- receivedLen += chunk.length;
- }
- return streams.PassThrough.prototype._write.apply(this, arguments);
- };
- lengthAccumulator.on('end', checkContentLengthAndEmit);
- stream.on('error', function(err) {
- shouldCheckContentLength = false;
- httpStream.unpipe(lengthAccumulator);
- lengthAccumulator.emit('end');
- lengthAccumulator.end();
- });
- httpStream.pipe(lengthAccumulator).pipe(stream, { end: false });
- } else {
- httpStream.pipe(stream);
- }
- } else {
- if (shouldCheckContentLength) {
- httpStream.on('data', function(arg) {
- if (arg && arg.length) {
- receivedLen += arg.length;
- }
- });
- }
- httpStream.on('data', function(arg) {
- stream.emit('data', arg);
- });
- httpStream.on('end', checkContentLengthAndEmit);
- }
- httpStream.on('error', function(err) {
- shouldCheckContentLength = false;
- stream.emit('error', err);
- });
- }
- });
- return stream;
- },
- /**
- * @param [Array,Response] args This should be the response object,
- * or an array of args to send to the event.
- * @api private
- */
- emitEvent: function emit(eventName, args, done) {
- if (typeof args === 'function') { done = args; args = null; }
- if (!done) done = function() { };
- if (!args) args = this.eventParameters(eventName, this.response);
- var origEmit = AWS.SequentialExecutor.prototype.emit;
- origEmit.call(this, eventName, args, function (err) {
- if (err) this.response.error = err;
- done.call(this, err);
- });
- },
- /**
- * @api private
- */
- eventParameters: function eventParameters(eventName) {
- switch (eventName) {
- case 'restart':
- case 'validate':
- case 'sign':
- case 'build':
- case 'afterValidate':
- case 'afterBuild':
- return [this];
- case 'error':
- return [this.response.error, this.response];
- default:
- return [this.response];
- }
- },
- /**
- * @api private
- */
- presign: function presign(expires, callback) {
- if (!callback && typeof expires === 'function') {
- callback = expires;
- expires = null;
- }
- return new AWS.Signers.Presign().sign(this.toGet(), expires, callback);
- },
- /**
- * @api private
- */
- isPresigned: function isPresigned() {
- return Object.prototype.hasOwnProperty.call(this.httpRequest.headers, 'presigned-expires');
- },
- /**
- * @api private
- */
- toUnauthenticated: function toUnauthenticated() {
- this._unAuthenticated = true;
- this.removeListener('validate', AWS.EventListeners.Core.VALIDATE_CREDENTIALS);
- this.removeListener('sign', AWS.EventListeners.Core.SIGN);
- return this;
- },
- /**
- * @api private
- */
- toGet: function toGet() {
- if (this.service.api.protocol === 'query' ||
- this.service.api.protocol === 'ec2') {
- this.removeListener('build', this.buildAsGet);
- this.addListener('build', this.buildAsGet);
- }
- return this;
- },
- /**
- * @api private
- */
- buildAsGet: function buildAsGet(request) {
- request.httpRequest.method = 'GET';
- request.httpRequest.path = request.service.endpoint.path +
- '?' + request.httpRequest.body;
- request.httpRequest.body = '';
- // don't need these headers on a GET request
- delete request.httpRequest.headers['Content-Length'];
- delete request.httpRequest.headers['Content-Type'];
- },
- /**
- * @api private
- */
- haltHandlersOnError: function haltHandlersOnError() {
- this._haltHandlersOnError = true;
- }
- });
- /**
- * @api private
- */
- AWS.Request.addPromisesToClass = function addPromisesToClass(PromiseDependency) {
- this.prototype.promise = function promise() {
- var self = this;
- // append to user agent
- this.httpRequest.appendToUserAgent('promise');
- return new PromiseDependency(function(resolve, reject) {
- self.on('complete', function(resp) {
- if (resp.error) {
- reject(resp.error);
- } else {
- // define $response property so that it is not enumerable
- // this prevents circular reference errors when stringifying the JSON object
- resolve(Object.defineProperty(
- resp.data || {},
- '$response',
- {value: resp}
- ));
- }
- });
- self.runTo();
- });
- };
- };
- /**
- * @api private
- */
- AWS.Request.deletePromisesFromClass = function deletePromisesFromClass() {
- delete this.prototype.promise;
- };
- AWS.util.addPromises(AWS.Request);
- AWS.util.mixin(AWS.Request, AWS.SequentialExecutor);
|