response.js | |
---|---|
The | var Content = require("./content")
, HeaderMixins = require("./mixins/headers")
, CookieJarLib = require( "cookiejar" )
, Cookie = CookieJarLib.Cookie
; |
Browser doesn't have zlib. | var zlib = null;
try {
zlib = require('zlib');
} catch (e) {
console.warn("no zlib library");
} |
Iconv doesn't work in browser | var Iconv = null;
try {
Iconv = require('iconv-lite');
} catch (e) {
console.warn("no iconv library");
} |
Construct a | var Response = function(raw, request, callback) {
var response = this;
this._raw = raw; |
The | this._setHeaders.call(this,raw.headers);
|
store any cookies | if (request.cookieJar && this.getHeader('set-cookie')) {
var cookieStrings = this.getHeader('set-cookie');
var cookieObjs = []
, cookie;
for (var i = 0; i < cookieStrings.length; i++) {
var cookieString = cookieStrings[i];
if (!cookieString) {
continue;
}
if (!cookieString.match(/domain\=/i)) {
cookieString += '; domain=' + request.host;
}
if (!cookieString.match(/path\=/i)) {
cookieString += '; path=' + request.path;
}
try {
cookie = new Cookie(cookieString);
if (cookie) {
cookieObjs.push(cookie);
}
} catch (e) {
console.warn("Tried to set bad cookie: " + cookieString);
}
}
request.cookieJar.setCookies(cookieObjs);
}
this.request = request;
this.client = request.client;
this.log = this.request.log; |
Stream the response content entity and fire the callback when we're done. Store the incoming data in a array of Buffers which we concatinate into one buffer at the end. We need to use buffers instead of strings here in order to preserve binary data. | var chunkBuffers = [];
var dataLength = 0;
raw.on("data", function(chunk) {
chunkBuffers.push(chunk);
dataLength += chunk.length;
});
raw.on("end", function() {
var body;
if (typeof Buffer === 'undefined') { |
Just concatinate into a string | body = chunkBuffers.join('');
} else { |
Initialize new buffer and add the chunks one-at-a-time. | body = new Buffer(dataLength);
for (var i = 0, pos = 0; i < chunkBuffers.length; i++) {
chunkBuffers[i].copy(body, pos);
pos += chunkBuffers[i].length;
}
}
var setBodyAndFinish = function (body) {
response._body = new Content({
body: body,
type: response.getHeader("Content-Type")
});
callback(response);
}
if (zlib && response.getHeader("Content-Encoding") === 'gzip'){
zlib.gunzip(body, function (err, gunzippedBody) {
if (Iconv && response.request.encoding){
body = Iconv.fromEncoding(gunzippedBody,response.request.encoding);
} else {
body = gunzippedBody.toString();
}
setBodyAndFinish(body);
})
}
else{
if (response.request.encoding){
body = Iconv.fromEncoding(body,response.request.encoding);
}
setBodyAndFinish(body);
}
});
}; |
The | Response.prototype = {
inspect: function() {
var response = this;
var headers = this.format_headers();
var summary = ["<Shred Response> ", response.status].join(" ")
return [ summary, "- Headers:", headers].join("\n");
},
format_headers: function () {
var array = []
var headers = this.headers
for (var key in headers) {
if (headers.hasOwnProperty(key)) {
var value = headers[key]
array.push("\t" + key + ": " + value);
}
}
return array.join("\n");
}
}; |
| Object.defineProperties(Response.prototype, {
|
| status: {
get: function() { return this._raw.statusCode; },
enumerable: true
}, |
| body: {
get: function() { return this._body; }
},
content: {
get: function() { return this.body; },
enumerable: true
},
headers: {
get: function() {
return this._headers;
},
enumerable: true
}, |
| isRedirect: {
get: function() {
return (this.status>299
&&this.status<400
&&this.getHeader("Location"));
},
enumerable: true
}, |
| isError: {
get: function() {
return (this.status === 0 || this.status > 399)
},
enumerable: true
}
}); |
Add in the getters for accessing the normalized headers. | HeaderMixins.getters(Response);
HeaderMixins.privateSetters(Response); |
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. | var getHeader = Response.prototype.getHeader;
Response.prototype.getHeader = function (name) {
return (getHeader.call(this,name) ||
(typeof this._raw.getHeader === 'function' && this._raw.getHeader(name)));
};
module.exports = Response;
|