response.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. var AWS = require('./core');
  2. var inherit = AWS.util.inherit;
  3. var jmespath = require('jmespath');
  4. /**
  5. * This class encapsulates the response information
  6. * from a service request operation sent through {AWS.Request}.
  7. * The response object has two main properties for getting information
  8. * back from a request:
  9. *
  10. * ## The `data` property
  11. *
  12. * The `response.data` property contains the serialized object data
  13. * retrieved from the service request. For instance, for an
  14. * Amazon DynamoDB `listTables` method call, the response data might
  15. * look like:
  16. *
  17. * ```
  18. * > resp.data
  19. * { TableNames:
  20. * [ 'table1', 'table2', ... ] }
  21. * ```
  22. *
  23. * The `data` property can be null if an error occurs (see below).
  24. *
  25. * ## The `error` property
  26. *
  27. * In the event of a service error (or transfer error), the
  28. * `response.error` property will be filled with the given
  29. * error data in the form:
  30. *
  31. * ```
  32. * { code: 'SHORT_UNIQUE_ERROR_CODE',
  33. * message: 'Some human readable error message' }
  34. * ```
  35. *
  36. * In the case of an error, the `data` property will be `null`.
  37. * Note that if you handle events that can be in a failure state,
  38. * you should always check whether `response.error` is set
  39. * before attempting to access the `response.data` property.
  40. *
  41. * @!attribute data
  42. * @readonly
  43. * @!group Data Properties
  44. * @note Inside of a {AWS.Request~httpData} event, this
  45. * property contains a single raw packet instead of the
  46. * full de-serialized service response.
  47. * @return [Object] the de-serialized response data
  48. * from the service.
  49. *
  50. * @!attribute error
  51. * An structure containing information about a service
  52. * or networking error.
  53. * @readonly
  54. * @!group Data Properties
  55. * @note This attribute is only filled if a service or
  56. * networking error occurs.
  57. * @return [Error]
  58. * * code [String] a unique short code representing the
  59. * error that was emitted.
  60. * * message [String] a longer human readable error message
  61. * * retryable [Boolean] whether the error message is
  62. * retryable.
  63. * * statusCode [Numeric] in the case of a request that reached the service,
  64. * this value contains the response status code.
  65. * * time [Date] the date time object when the error occurred.
  66. * * hostname [String] set when a networking error occurs to easily
  67. * identify the endpoint of the request.
  68. * * region [String] set when a networking error occurs to easily
  69. * identify the region of the request.
  70. *
  71. * @!attribute requestId
  72. * @readonly
  73. * @!group Data Properties
  74. * @return [String] the unique request ID associated with the response.
  75. * Log this value when debugging requests for AWS support.
  76. *
  77. * @!attribute retryCount
  78. * @readonly
  79. * @!group Operation Properties
  80. * @return [Integer] the number of retries that were
  81. * attempted before the request was completed.
  82. *
  83. * @!attribute redirectCount
  84. * @readonly
  85. * @!group Operation Properties
  86. * @return [Integer] the number of redirects that were
  87. * followed before the request was completed.
  88. *
  89. * @!attribute httpResponse
  90. * @readonly
  91. * @!group HTTP Properties
  92. * @return [AWS.HttpResponse] the raw HTTP response object
  93. * containing the response headers and body information
  94. * from the server.
  95. *
  96. * @see AWS.Request
  97. */
  98. AWS.Response = inherit({
  99. /**
  100. * @api private
  101. */
  102. constructor: function Response(request) {
  103. this.request = request;
  104. this.data = null;
  105. this.error = null;
  106. this.retryCount = 0;
  107. this.redirectCount = 0;
  108. this.httpResponse = new AWS.HttpResponse();
  109. if (request) {
  110. this.maxRetries = request.service.numRetries();
  111. this.maxRedirects = request.service.config.maxRedirects;
  112. }
  113. },
  114. /**
  115. * Creates a new request for the next page of response data, calling the
  116. * callback with the page data if a callback is provided.
  117. *
  118. * @callback callback function(err, data)
  119. * Called when a page of data is returned from the next request.
  120. *
  121. * @param err [Error] an error object, if an error occurred in the request
  122. * @param data [Object] the next page of data, or null, if there are no
  123. * more pages left.
  124. * @return [AWS.Request] the request object for the next page of data
  125. * @return [null] if no callback is provided and there are no pages left
  126. * to retrieve.
  127. * @since v1.4.0
  128. */
  129. nextPage: function nextPage(callback) {
  130. var config;
  131. var service = this.request.service;
  132. var operation = this.request.operation;
  133. try {
  134. config = service.paginationConfig(operation, true);
  135. } catch (e) { this.error = e; }
  136. if (!this.hasNextPage()) {
  137. if (callback) callback(this.error, null);
  138. else if (this.error) throw this.error;
  139. return null;
  140. }
  141. var params = AWS.util.copy(this.request.params);
  142. if (!this.nextPageTokens) {
  143. return callback ? callback(null, null) : null;
  144. } else {
  145. var inputTokens = config.inputToken;
  146. if (typeof inputTokens === 'string') inputTokens = [inputTokens];
  147. for (var i = 0; i < inputTokens.length; i++) {
  148. params[inputTokens[i]] = this.nextPageTokens[i];
  149. }
  150. return service.makeRequest(this.request.operation, params, callback);
  151. }
  152. },
  153. /**
  154. * @return [Boolean] whether more pages of data can be returned by further
  155. * requests
  156. * @since v1.4.0
  157. */
  158. hasNextPage: function hasNextPage() {
  159. this.cacheNextPageTokens();
  160. if (this.nextPageTokens) return true;
  161. if (this.nextPageTokens === undefined) return undefined;
  162. else return false;
  163. },
  164. /**
  165. * @api private
  166. */
  167. cacheNextPageTokens: function cacheNextPageTokens() {
  168. if (Object.prototype.hasOwnProperty.call(this, 'nextPageTokens')) return this.nextPageTokens;
  169. this.nextPageTokens = undefined;
  170. var config = this.request.service.paginationConfig(this.request.operation);
  171. if (!config) return this.nextPageTokens;
  172. this.nextPageTokens = null;
  173. if (config.moreResults) {
  174. if (!jmespath.search(this.data, config.moreResults)) {
  175. return this.nextPageTokens;
  176. }
  177. }
  178. var exprs = config.outputToken;
  179. if (typeof exprs === 'string') exprs = [exprs];
  180. AWS.util.arrayEach.call(this, exprs, function (expr) {
  181. var output = jmespath.search(this.data, expr);
  182. if (output) {
  183. this.nextPageTokens = this.nextPageTokens || [];
  184. this.nextPageTokens.push(output);
  185. }
  186. });
  187. return this.nextPageTokens;
  188. }
  189. });