137 lines
3.8 KiB
JavaScript
137 lines
3.8 KiB
JavaScript
|
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;
|