|
56 | 56 | notify: true, |
57 | 57 | readOnly: true, |
58 | 58 | value: function() { |
59 | | - return null; |
| 59 | + return null; |
60 | 60 | } |
61 | 61 | }, |
62 | 62 |
|
|
177 | 177 | * body: (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|undefined|Object), |
178 | 178 | * headers: (Object|undefined), |
179 | 179 | * handleAs: (string|undefined), |
| 180 | + * jsonPrefix: (string|undefined), |
180 | 181 | * withCredentials: (boolean|undefined)}} options - |
181 | 182 | * url The url to which the request is sent. |
182 | 183 | * method The HTTP method to use, default is GET. |
|
204 | 205 | }); |
205 | 206 | }.bind(this)) |
206 | 207 |
|
| 208 | + xhr.addEventListener('readystatechange', function () { |
| 209 | + if (xhr.readyState === 2 && options.async !== false) { |
| 210 | + // Headers have been received. |
| 211 | + var jsonPrefix = xhr.getResponseHeader('X-JSON-Prefix') || |
| 212 | + options.jsonPrefix; |
| 213 | + var handleAs = options.handleAs; |
| 214 | + |
| 215 | + // If a JSON prefix is present, the responseType must be 'text' or the |
| 216 | + // browser won’t be able to parse the response. |
| 217 | + if (!!jsonPrefix || !handleAs) { |
| 218 | + handleAs = 'text'; |
| 219 | + } |
| 220 | + // In IE, `xhr.responseType` is an empty string when the response |
| 221 | + // returns. Hence, caching it as `xhr._responseType`. |
| 222 | + xhr.responseType = xhr._responseType = handleAs; |
| 223 | + |
| 224 | + // Cache the JSON prefix, if it exists. |
| 225 | + if (!!jsonPrefix) { |
| 226 | + xhr._jsonPrefix = jsonPrefix; |
| 227 | + } |
| 228 | + } |
| 229 | + }.bind(this)); |
| 230 | + |
207 | 231 | xhr.addEventListener('error', function (error) { |
208 | 232 | this._setErrored(true); |
209 | 233 | this._updateStatus(); |
|
269 | 293 | ); |
270 | 294 | }, this); |
271 | 295 |
|
272 | | - var body = this._encodeBodyObject(options.body, headers['content-type']); |
273 | | - |
274 | | - // In IE, `xhr.responseType` is an empty string when the response |
275 | | - // returns. Hence, caching it as `xhr._responseType`. |
276 | | - if (options.async !== false) { |
277 | | - xhr.responseType = xhr._responseType = (options.handleAs || 'text'); |
278 | | - } |
279 | 296 | xhr.withCredentials = !!options.withCredentials; |
280 | 297 | xhr.timeout = options.timeout; |
281 | 298 |
|
282 | | - |
| 299 | + var body = this._encodeBodyObject(options.body, headers['content-type']); |
283 | 300 |
|
284 | 301 | xhr.send( |
285 | 302 | /** @type {ArrayBuffer|ArrayBufferView|Blob|Document|FormData| |
|
301 | 318 | var xhr = this.xhr; |
302 | 319 | var responseType = xhr.responseType || xhr._responseType; |
303 | 320 | var preferResponseText = !this.xhr.responseType; |
| 321 | + var prefixHeader = xhr.getResponseHeader('X-JSON-Prefix'); |
| 322 | + if (prefixHeader) { |
| 323 | + // If a JSON prefix header is set, the response must be interpretted as |
| 324 | + // text so that the prefix can be stripped. Otherwise the browser will |
| 325 | + // try and fail to. |
| 326 | + responseType = 'text'; |
| 327 | + } |
| 328 | + var prefixLen = (prefixHeader && prefixHeader.length) || |
| 329 | + (xhr._jsonPrefix && xhr._jsonPrefix.length) || 0; |
304 | 330 |
|
305 | 331 | try { |
306 | 332 | switch (responseType) { |
|
315 | 341 | // That is to say, we try to parse as JSON, but if anything goes |
316 | 342 | // wrong return null. |
317 | 343 | try { |
318 | | - return JSON.parse(xhr.responseText);; |
| 344 | + return JSON.parse(xhr.responseText); |
319 | 345 | } catch (_) { |
320 | 346 | return null; |
321 | 347 | } |
|
329 | 355 | case 'arraybuffer': |
330 | 356 | return xhr.response; |
331 | 357 | case 'text': |
332 | | - default: |
| 358 | + default: { |
| 359 | + // If `prefixLen` is set, it implies the response should be parsed |
| 360 | + // as JSON once the prefix of length `prefixLen` is stripped from |
| 361 | + // it. Emulate the behavior above where null is returned on failure |
| 362 | + // to parse. |
| 363 | + if (prefixLen) { |
| 364 | + try { |
| 365 | + return JSON.parse(xhr.responseText.substring(prefixLen)); |
| 366 | + } catch (_) { |
| 367 | + return null; |
| 368 | + } |
| 369 | + } |
333 | 370 | return xhr.responseText; |
| 371 | + } |
334 | 372 | } |
335 | 373 | } catch (e) { |
336 | 374 | this.rejectCompletes(new Error('Could not parse response. ' + e.message)); |
|
0 commit comments