123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- var AWS = require('../core');
- var EventEmitter = require('events').EventEmitter;
- require('../http');
- /**
- * @api private
- */
- AWS.XHRClient = AWS.util.inherit({
- handleRequest: function handleRequest(httpRequest, httpOptions, callback, errCallback) {
- var self = this;
- var endpoint = httpRequest.endpoint;
- var emitter = new EventEmitter();
- var href = endpoint.protocol + '//' + endpoint.hostname;
- if (endpoint.port !== 80 && endpoint.port !== 443) {
- href += ':' + endpoint.port;
- }
- href += httpRequest.path;
- var xhr = new XMLHttpRequest(), headersEmitted = false;
- httpRequest.stream = xhr;
- xhr.addEventListener('readystatechange', function() {
- try {
- if (xhr.status === 0) return; // 0 code is invalid
- } catch (e) { return; }
- if (this.readyState >= this.HEADERS_RECEIVED && !headersEmitted) {
- emitter.statusCode = xhr.status;
- emitter.headers = self.parseHeaders(xhr.getAllResponseHeaders());
- emitter.emit(
- 'headers',
- emitter.statusCode,
- emitter.headers,
- xhr.statusText
- );
- headersEmitted = true;
- }
- if (this.readyState === this.DONE) {
- self.finishRequest(xhr, emitter);
- }
- }, false);
- xhr.upload.addEventListener('progress', function (evt) {
- emitter.emit('sendProgress', evt);
- });
- xhr.addEventListener('progress', function (evt) {
- emitter.emit('receiveProgress', evt);
- }, false);
- xhr.addEventListener('timeout', function () {
- errCallback(AWS.util.error(new Error('Timeout'), {code: 'TimeoutError'}));
- }, false);
- xhr.addEventListener('error', function () {
- errCallback(AWS.util.error(new Error('Network Failure'), {
- code: 'NetworkingError'
- }));
- }, false);
- xhr.addEventListener('abort', function () {
- errCallback(AWS.util.error(new Error('Request aborted'), {
- code: 'RequestAbortedError'
- }));
- }, false);
- callback(emitter);
- xhr.open(httpRequest.method, href, httpOptions.xhrAsync !== false);
- AWS.util.each(httpRequest.headers, function (key, value) {
- if (key !== 'Content-Length' && key !== 'User-Agent' && key !== 'Host') {
- xhr.setRequestHeader(key, value);
- }
- });
- if (httpOptions.timeout && httpOptions.xhrAsync !== false) {
- xhr.timeout = httpOptions.timeout;
- }
- if (httpOptions.xhrWithCredentials) {
- xhr.withCredentials = true;
- }
- try { xhr.responseType = 'arraybuffer'; } catch (e) {}
- try {
- if (httpRequest.body) {
- xhr.send(httpRequest.body);
- } else {
- xhr.send();
- }
- } catch (err) {
- if (httpRequest.body && typeof httpRequest.body.buffer === 'object') {
- xhr.send(httpRequest.body.buffer); // send ArrayBuffer directly
- } else {
- throw err;
- }
- }
- return emitter;
- },
- parseHeaders: function parseHeaders(rawHeaders) {
- var headers = {};
- AWS.util.arrayEach(rawHeaders.split(/\r?\n/), function (line) {
- var key = line.split(':', 1)[0];
- var value = line.substring(key.length + 2);
- if (key.length > 0) headers[key.toLowerCase()] = value;
- });
- return headers;
- },
- finishRequest: function finishRequest(xhr, emitter) {
- var buffer;
- if (xhr.responseType === 'arraybuffer' && xhr.response) {
- var ab = xhr.response;
- buffer = new AWS.util.Buffer(ab.byteLength);
- var view = new Uint8Array(ab);
- for (var i = 0; i < buffer.length; ++i) {
- buffer[i] = view[i];
- }
- }
- try {
- if (!buffer && typeof xhr.responseText === 'string') {
- buffer = new AWS.util.Buffer(xhr.responseText);
- }
- } catch (e) {}
- if (buffer) emitter.emit('data', buffer);
- emitter.emit('end');
- }
- });
- /**
- * @api private
- */
- AWS.HttpClient.prototype = AWS.XHRClient.prototype;
- /**
- * @api private
- */
- AWS.HttpClient.streamsApiVersion = 1;
|