Skip to content

Commit

Permalink
Refactor _payload handling. Closes #1215
Browse files Browse the repository at this point in the history
  • Loading branch information
Eran Hammer committed Dec 14, 2013
1 parent a2eb526 commit cdf15b7
Show file tree
Hide file tree
Showing 16 changed files with 226 additions and 245 deletions.
4 changes: 2 additions & 2 deletions lib/payload.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,14 +315,14 @@ internals.Replay = function (headers, payload) {

Stream.Readable.call(this);
this.headers = headers;
this._payload = payload;
this._data = payload;
};

Utils.inherits(internals.Replay, Stream.Readable);


internals.Replay.prototype._read = function (size) {

this.push(this._payload);
this.push(this._data);
this.push(null);
};
3 changes: 2 additions & 1 deletion lib/response/buffer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Load modules

var Generic = require('./generic');
var Payload = require('./payload');
var Utils = require('../utils');


Expand All @@ -24,6 +25,6 @@ Utils.inherits(internals.Buffer, Generic);

internals.Buffer.prototype._prepare = function (request, callback) {

this._payload.push(this.source);
this._payload = new Payload(this.source);
return Generic.prototype._prepare.call(this, request, callback);
};
3 changes: 2 additions & 1 deletion lib/response/cached.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Load modules

var Generic = require('./generic');
var Payload = require('./payload');
var Utils = require('../utils');


Expand Down Expand Up @@ -30,6 +31,6 @@ Utils.inherits(internals.Cached, Generic);

internals.Cached.prototype._prepare = function (request, callback) {

this._payload = [this._source.payload];
this._payload = new Payload(this._source.payload);
return Generic.prototype._prepare.call(this, request, callback);
};
12 changes: 4 additions & 8 deletions lib/response/directory.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
var Fs = require('fs');
var Path = require('path');
var Async = require('async');
var Generic = require('./generic');
var Redirection = require('./redirection');
var Text = require('./text');
var Boom = require('boom');
Expand All @@ -16,30 +15,27 @@ var Utils = require('../utils');
var internals = {};


// File response (Generic -> Directory)
// Directory response

exports = module.exports = internals.Directory = function (paths, options) {

Utils.assert(this.constructor === internals.Directory, 'Directory must be instantiated using new');
Utils.assert(options, 'Options must exist');

Generic.call(this);
this.isHapiResponse = true;

this.variety = 'directory';
this.varieties.directory = true;
this.varieties = { directory: true };

this.paths = paths;
this.settings = options;
};

Utils.inherits(internals.Directory, Generic);


internals.Directory.prototype._prepare = function (request, callback) {

var self = this;

this._wasPrepared = true;

var settings = this.settings;
this._index = settings.index === false ? false : true; // Defaults to true
this._listing = !!settings.listing; // Defaults to false
Expand Down
6 changes: 2 additions & 4 deletions lib/response/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ internals.File.prototype._prepare = function (request, callback) {

var self = this;

this._wasPrepared = true;

var filePath = Path.normalize(this.path);
Fs.stat(filePath, function (err, stat) {

Expand Down Expand Up @@ -86,16 +84,16 @@ internals.File.prototype._prepare = function (request, callback) {
}

var fileStream = Fs.createReadStream(filePath);
self.stream = fileStream;

if (!self.settings.lookupCompressed) {
self._setStream(fileStream);
return StreamResponse.prototype._prepare.call(self, request, callback);
}

var gzFile = filePath + '.gz';
Fs.stat(gzFile, function (err, stat) {

self._setStream(fileStream, !err && !stat.isDirectory() ? Fs.createReadStream(gzFile) : null);
self.gzipped = (!err && !stat.isDirectory() ? Fs.createReadStream(gzFile) : null);
return StreamResponse.prototype._prepare.call(self, request, callback);
});
});
Expand Down
167 changes: 7 additions & 160 deletions lib/response/generic.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
// Load modules

var Stream = require('stream');
var Async = require('async');
var Negotiator = require('negotiator');
var Zlib = require('zlib');
var Headers = require('./headers');
var Payload = require('./payload');
var Utils = require('../utils');
var Boom = require('boom');


// Declare internals
Expand All @@ -26,18 +23,13 @@ exports = module.exports = internals.Generic = function () {
this.varieties = {};
this.varieties.generic = true;

this.source = null;

this._flags = {}; // Cached
this._states = {}; // Not cached
this._wasPrepared = false;

this._code = 200;
this._headers = {};

this._payload = [];
this._stream = null;
this._gzipped = null;
this._payload = null; // Readable stream

this._preview = new internals.Peek();
};
Expand Down Expand Up @@ -126,33 +118,16 @@ internals.Generic.prototype._prepare = function (request, callback) {

this._wasPrepared = true;

var length = 0;
for (var i = 0, il = this._payload.length; i < il; ++i) {
var chunk = this._payload[i];
this._payload = this._payload || new Payload();

if (Buffer.isBuffer(chunk)) {
length += chunk.length;
}
else {
length += Buffer.byteLength(chunk, this._flags.encoding || 'utf-8');
}
}
if (request.jsonp &&
this._payload.jsonp) {

if (request.jsonp) {
this.header('content-type', 'text/javascript');
length += request.jsonp.length + 3;

var payload = [request.jsonp, '('];
for (i = 0, il = this._payload.length; i < il; ++i) {
var chunk = this._payload[i];
payload.push(Buffer.isBuffer(chunk) ? chunk : chunk.replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029'));
}

payload.push(');');
this._payload = payload;
this._payload.jsonp(request.jsonp);
}

this.header('content-length', length);
this.header('content-length', this._payload.size(this._flags.encoding));

if (this._flags.location) {
this._headers.location = Headers.location(this._flags.location, request);
Expand All @@ -175,115 +150,6 @@ internals.Generic.prototype._prepare = function (request, callback) {
};


internals.Generic.prototype._transmit = function (request, callback) {

var self = this;

var source = this._stream || new internals.BufferStream(this._payload);

// Content encoding

var encoder = null;
if (!this._headers['content-encoding']) {
var negotiator = new Negotiator(request.raw.req);
var encoding = negotiator.preferredEncoding(['gzip', 'deflate', 'identity']);
if (encoding === 'deflate' || encoding === 'gzip') {
var keys = Object.keys(this._headers);
for (var i = 0, il = keys.length; i < il; ++i) {
var key = keys[i];
if (/content\-length/i.test(key)) { // Can be lowercase when coming from proxy
delete self._headers[key];
}
}

this.header('content-encoding', encoding);
this.header('vary', 'accept-encoding', true);

if (this._gzipped && encoding === 'gzip') {
source = this._gzipped;
}
else {
encoder = (encoding === 'gzip' ? Zlib.createGzip() : Zlib.createDeflate());
}
}
}

// Headers

var headers = Object.keys(this._headers);
for (var h = 0, hl = headers.length; h < hl; ++h) {
var header = headers[h];
request.raw.res.setHeader(header, self._headers[header]);
}

request.raw.res.writeHead(this._code);

// Payload

if (request.method === 'head') {
self._preview.once('finish', function () {

request.raw.res.end();
callback();
});

self._preview.end();
return;
}

var previewFinished = false;
var hasEnded = false;
var end = function (err, aborted) {

if (!hasEnded) {
hasEnded = true;

if (!aborted) {
request.raw.res.end();
}

var finalize = function () {

request.raw.req.removeListener('close', end);
request.raw.req.removeListener('aborted', end);
self._preview.removeAllListeners();
source.removeAllListeners();

callback();
};

if (previewFinished) {
return finalize();
}

self._preview.once('finish', finalize);
self._preview.end();
}
};

source.once('error', end);

request.raw.req.once('close', end);
request.raw.req.once('aborted', function () {

end(null, true);
});

request.raw.res.once('close', end);
request.raw.res.once('error', end);
request.raw.res.once('finish', end);

self._preview.once('finish', function () {

previewFinished = true;
});

var preview = source.pipe(this._preview);
var encoded = (encoder ? preview.pipe(encoder) : preview);
encoded.pipe(request.raw.res);
};


internals.Generic.prototype.code = function (statusCode) {

this._code = statusCode;
Expand Down Expand Up @@ -324,22 +190,3 @@ internals.Peek.prototype._transform = function (chunk, encoding, callback) {
this.push(chunk);
callback();
};


internals.BufferStream = function (payload) {

Stream.Readable.call(this);
this._payload = payload;
};

Utils.inherits(internals.BufferStream, Stream.Readable);


internals.BufferStream.prototype._read = function (size) {

for (var i = 0, il = this._payload.length; i < il; ++i) {
this.push(this._payload[i]);
}

this.push(null);
};
4 changes: 4 additions & 0 deletions lib/response/headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ exports.content = function (response, request) {
return;
}

if (!type.match(/^(?:text\/)|(?:application\/(?:json)|(?:javascript))/)) {
return;
}

var hasParams = (type.indexOf(';') !== -1);
if (hasParams &&
type.match(/[; ]charset=/)) {
Expand Down
Loading

0 comments on commit cdf15b7

Please sign in to comment.