diff --git a/lib/request.js b/lib/request.js index 19ecca3..be90cf8 100644 --- a/lib/request.js +++ b/lib/request.js @@ -27,7 +27,7 @@ var Request = module.exports = function (xhr, params) { }); } - var res = new Response; + var res = new Response(xhr); res.on('ready', function () { self.emit('response', res); }); diff --git a/lib/response.js b/lib/response.js index ae2844b..e168787 100644 --- a/lib/response.js +++ b/lib/response.js @@ -1,6 +1,7 @@ var EventEmitter = require('events').EventEmitter; -var Response = module.exports = function (res) { +var Response = module.exports = function (xhr) { + this.xhr = xhr; this.offset = 0; }; @@ -11,8 +12,8 @@ var capable = { status2 : true }; -function parseHeaders (res) { - var lines = res.getAllResponseHeaders().split(/\r?\n/); +function parseHeaders (xhr) { + var lines = xhr.getAllResponseHeaders().split(/\r?\n/); var headers = {}; for (var i = 0; i < lines.length; i++) { var line = lines[i]; @@ -43,14 +44,20 @@ function parseHeaders (res) { } Response.prototype.getHeader = function (key) { - return this.headers[key.toLowerCase()]; + var header = this.headers[key.toLowerCase()]; + + // Work around Mozilla bug #608735 [https://bugzil.la/608735], which causes + // getAllResponseHeaders() to return {} if the response is a CORS request. + // xhr.getHeader still works correctly. + return header || this.xhr.getResponseHeader(key); }; -Response.prototype.handle = function (res) { - if (res.readyState === 2 && capable.status2) { +Response.prototype.handle = function () { + var xhr = this.xhr; + if (xhr.readyState === 2 && capable.status2) { try { - this.statusCode = res.status; - this.headers = parseHeaders(res); + this.statusCode = xhr.status; + this.headers = parseHeaders(xhr); } catch (err) { capable.status2 = false; @@ -60,40 +67,41 @@ Response.prototype.handle = function (res) { this.emit('ready'); } } - else if (capable.streaming && res.readyState === 3) { + else if (capable.streaming && xhr.readyState === 3) { try { if (!this.statusCode) { - this.statusCode = res.status; - this.headers = parseHeaders(res); + this.statusCode = xhr.status; + this.headers = parseHeaders(xhr); this.emit('ready'); } } catch (err) {} try { - this.write(res); + this.write(); } catch (err) { capable.streaming = false; } } - else if (res.readyState === 4) { + else if (xhr.readyState === 4) { if (!this.statusCode) { - this.statusCode = res.status; + this.statusCode = xhr.status; this.emit('ready'); } - this.write(res); + this.write(); - if (res.error) { - this.emit('error', res.responseText); + if (xhr.error) { + this.emit('error', xhr.responseText); } else this.emit('end'); } }; -Response.prototype.write = function (res) { - if (res.responseText.length > this.offset) { - this.emit('data', res.responseText.slice(this.offset)); - this.offset = res.responseText.length; +Response.prototype.write = function () { + var xhr = this.xhr; + if (xhr.responseText.length > this.offset) { + this.emit('data', xhr.responseText.slice(this.offset)); + this.offset = xhr.responseText.length; } };