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