diff --git a/lib/response/generic.js b/lib/response/generic.js index cee3159a0..0000979ec 100755 --- a/lib/response/generic.js +++ b/lib/response/generic.js @@ -1,8 +1,10 @@ // Load modules var NodeUtil = require('util'); +var Zlib = require('zlib'); var Base = require('./base'); var Utils = require('../utils'); +var Err = require('../error'); // Declare internals @@ -31,10 +33,51 @@ NodeUtil.inherits(internals.Generic, Base); internals.Generic.prototype._transmit = function (request, callback) { - request.raw.res.writeHead(this._code, this.headers); - request.raw.res.end(request.method !== 'head' ? this._payload : ''); + var self = this; + var isHeadMethod = request.method === 'head'; - return callback(); + var processGzip = function() { + + if (!self._payload || isHeadMethod) { + return send(); + } + + var rawReq = (request && request.raw && request.raw.req) ? request.raw.req : null; + var acceptEncoding = rawReq && rawReq.headers ? rawReq.headers['accept-encoding'] : null; + var isGzip = acceptEncoding && acceptEncoding.indexOf('gzip') !== -1; + + if(!isGzip) { + return send(); + } + + Zlib.gzip(new Buffer(self._payload), function(err, result) { + + if (err) { + var errorResponse = Err.internal('Unable to gzip payload', err).toResponse(); + + self._code = errorResponse.code; + self._payload = errorResponse.payload; + } + else if (result) { + self._payload = result; + self.header('Content-Encoding', 'gzip'); + self.header('Vary', 'Accept-Encoding'); + self.header('Content-Length', result.length); + } + + return send(); + }); + }; + + var send = function() { + + request.raw.res.writeHead(self._code, self.headers); + request.raw.res.end(!isHeadMethod ? self._payload : ''); + + return callback(); + }; + + processGzip(); }; @@ -71,4 +114,4 @@ internals.Generic.prototype.ttl = function (ttl) { this.options.ttl = ttl; return this; -}; +}; \ No newline at end of file diff --git a/test/integration/gzip.js b/test/integration/gzip.js index e30bf1415..9c0d1f871 100755 --- a/test/integration/gzip.js +++ b/test/integration/gzip.js @@ -4,11 +4,12 @@ var expect = require('chai').expect; var libPath = process.env.TEST_COV ? '../../lib-cov/' : '../../lib/'; var Hapi = require(libPath + 'hapi'); var Zlib = require('zlib'); +var Request = require('request'); describe('Payload', function () { - var server = new Hapi.Server('0.0.0.0', 8080); + var server = new Hapi.Server('0.0.0.0', 17080); var message = { 'msg': 'This message is going to be gzipped.' }; var badMessage = '{ this is just wrong }'; @@ -18,7 +19,7 @@ describe('Payload', function () { config: { handler: function (req) { - req.reply(req.payload) + req.reply(req.payload); } } }; @@ -70,7 +71,7 @@ describe('Payload', function () { expect(res.result).to.exist; expect(res.result).to.deep.equal(message); done(); - });; + }); }); it('returns error if given non-JSON gzipped payload when expecting gzip', function (done) { @@ -97,5 +98,38 @@ describe('Payload', function () { }); }); }); -}); + it('returns a gzip response when accept-encoding: gzip is requested', function(done) { + + var rawBody = '{"test":"true"}'; + + Zlib.gzip(new Buffer(rawBody), function(err, zippedBody) { + + server.start(function() { + + Request.post({ url: 'http://localhost:17080', headers: { 'accept-encoding': 'gzip' }, body: rawBody }, function(err, res, body) { + + expect(body).to.equal(zippedBody.toString()); + done(); + }); + }); + }); + }); + + it('returns a gzip response when accept-encoding: deflate,gzip is requested', function(done) { + + var rawBody = '{"test":"true"}'; + + Zlib.gzip(new Buffer(rawBody), function(err, zippedBody) { + + server.start(function() { + + Request.post({ url: 'http://localhost:17080', headers: { 'accept-encoding': 'deflate, gzip' }, body: rawBody }, function(err, res, body) { + + expect(body).to.equal(zippedBody.toString()); + done(); + }); + }); + }); + }); +}); \ No newline at end of file