diff --git a/express/server.js b/express/server.js index e16faae..7350083 100755 --- a/express/server.js +++ b/express/server.js @@ -36,7 +36,7 @@ app.use(bodyParser.json()); /* ======== home ======== */ function handle_timestamp (req, res) { - res.set({'Content-Type': 'text/json'}); + res.set({'Content-Type': 'application/json'}); var timestamp = { timestamp: moment().unix()}; return res.json(timestamp); } @@ -88,3 +88,5 @@ server.listen(app.get('port'), function () { server.on('error', function (error) { console.log({ 'server error': error }); }); + +module.exports = app; diff --git a/lib/ExpressRedisCache/route.js b/lib/ExpressRedisCache/route.js index 4491501..bb636b9 100644 --- a/lib/ExpressRedisCache/route.js +++ b/lib/ExpressRedisCache/route.js @@ -31,6 +31,12 @@ module.exports = (function () { var options = arguments; + /** Listner for request finished event + * + * @type Function + */ + var onFinished = require('on-finished'); + /** The domain handler * * @type Domain @@ -66,9 +72,9 @@ module.exports = (function () { file: __fileName, line: __line }); - + res.use_express_redis_cache = res.expressRedisCache; - + } // If cache is disabled, call next() @@ -77,7 +83,7 @@ module.exports = (function () { } // If the cache isn't connected, call next() - + if ( self.connected === false || self.client.connected === false ) { return next(); } @@ -154,6 +160,9 @@ module.exports = (function () { var expirationPolicy = require('./expire')(expire); + /** build response into single string before caching **/ + var buf = ''; + /** attempt to get cache **/ self.get(name, domain.bind(function (error, cache) { @@ -166,46 +175,39 @@ module.exports = (function () { /** if it's cached, display cache **/ if ( cache.length ) { - res.contentType(cache[0].type || "text/html"); - if(binary){ //Convert back to binary buffer - res.send(new Buffer(cache[0].body, 'base64')); - }else{ - res.send(cache[0].body); - } + res.socket.write(cache[0].body); + res.end(); } /** otherwise, cache request **/ else { + var _write = res.socket.write.bind(res.socket); - /** wrap res.send **/ - var send = res.send.bind(res); - - res.send = function (body) { - + res.socket.write = function redisCacheWrite (body) { /** send output to HTTP client **/ - var ret = send(body); + _write.apply(_write, Array.prototype.slice.call(arguments)); /** convert binary to base64 string **/ if(binary && typeof body !== 'string'){ body = new Buffer(body).toString('base64'); } - /** save only strings to cache **/ - if ( typeof body !== 'string' ) { - return ret; - } - - /** Create the new cache **/ - self.add(name, body, { - type: this._headers['content-type'], - expire: expirationPolicy(res.statusCode) - }, - domain.intercept(function (name, cache) {})); - - return ret; - + // add to the cache entry being built + buf += body; }; + /** wait for response to finish streaming, then cache it **/ + onFinished(res, function (err) { + if (!err) { + /** Create the new cache **/ + self.add(name, buf, { + type: res._headers['content-type'], + expire: expirationPolicy(res.statusCode) + }, + domain.intercept(function (name, cache) {})); + } + }); + return next(); } diff --git a/package.json b/package.json index 8ab028f..e678c51 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "dependencies": { "async": "~1.5.0", "colors": "^1.1.2", + "on-finished": "^2.3.0", "redis": "^2.4.2" }, "directories": { @@ -66,11 +67,12 @@ }, "devDependencies": { "body-parser": "~1.14.1", - "method-override": "~2.3.5", - "request": "~2.67.0", "express": "~4.13.3", + "method-override": "~2.3.5", "mocha": "~2.3.4", + "moment": "^2.10.6", + "request": "~2.67.0", "should": "~8.0.1", - "moment": "^2.10.6" + "supertest": "^1.2.0" } } diff --git a/test/express.js b/test/express.js index 3a06750..78182d4 100644 --- a/test/express.js +++ b/test/express.js @@ -5,55 +5,35 @@ var mocha = require('mocha'); var should = require('should'); var request = require('request'); var util = require('util'); - -var prefix = process.env.EX_RE_CA_PREFIX || 'erct:'; -var host = process.env.EX_RE_CA_HOST || 'localhost'; -var port = process.env.EX_RE_CA_PORT || 6379; - -var spawn, - express_port, - home; +var supertest = require('supertest'); +var request; describe ( 'test with small express server', function () { before(function (done) { this.timeout(5000); - spawn = require('child_process') - .spawn('express/server.js', [], {}); - - spawn.on('error', function (error) { - throw error; - }); - - spawn.on('exit', function (status) { - console.log('Express Server exit with status ' + status); - }); - - spawn.stdout.on('data', function (data) { - console.log(data.toString()); - if ( /express-redis-cache test server started on port/.test(data.toString()) ) { - - express_port = data.toString().split(' ').pop().trim(); - - done(); - } - }); + request = supertest(require('../express/server')); + done(); }); it ( 'should have a / route', function (done) { - request('http://localhost:' + express_port, - function (error, response, body) { - if ( error ) { - throw error; + request + .get('/') + .end( + function (error, response, body) { + if ( error ) { + throw error; + } + response.statusCode.should.equal(200); + done(); } - response.statusCode.should.equal(200); - done(); - }); + ); }); it ( 'should not have /foobar route', function (done) { - request('http://localhost:' + express_port + "/foobar", - function (error, response, body) { + request + .get('/foobar') + .end(function (error, response) { if ( error ) { throw error; } @@ -63,18 +43,18 @@ describe ( 'test with small express server', function () { }); it ( '/1sec route should return json with a timestamp property', function (done) { - var url = 'http://localhost:' + express_port + "/1sec"; - request(url, - function (error, response, body) { + var url = '/1sec'; + request.get(url) + .end(function (error, response) { if ( error ) { throw error; } - var p_body = JSON.parse(body); + // Some Mocha weirdness requires a try/catch // or an AssertionError will crash the mocha process on error try { response.statusCode.should.equal(200); - p_body.should.have.property('timestamp'); + should(response.body).have.property('timestamp'); done(); } catch (e) { done(e); @@ -83,18 +63,18 @@ describe ( 'test with small express server', function () { }); it ( '/default_expire route should return json with a timestamp property', function (done) { - var url = 'http://localhost:' + express_port + "/default_expire"; - request(url, - function (error, response, body) { + var url = '/default_expire'; + request.get(url) + .end(function (error, response) { if ( error ) { throw error; } - var p_body = JSON.parse(body); + // Some Mocha weirdness requires a try/catch // or an AssertionError will crash the mocha process on error try { response.statusCode.should.equal(200); - p_body.should.have.property('timestamp'); + should(response.body).have.property('timestamp'); done(); } catch (e) { done(e); @@ -103,18 +83,18 @@ describe ( 'test with small express server', function () { }); it ( '/never_expire route should return json with a timestamp property', function (done) { - var url = 'http://localhost:' + express_port + "/never_expire"; - request(url, - function (error, response, body) { + var url = '/never_expire'; + request.get(url) + .end(function (error, response) { if ( error ) { throw error; } - var p_body = JSON.parse(body); + // Some Mocha weirdness requires a try/catch // or an AssertionError will crash the mocha process on error try { response.statusCode.should.equal(200); - p_body.should.have.property('timestamp'); + should(response.body).have.property('timestamp'); done(); } catch (e) { done(e); @@ -124,13 +104,13 @@ describe ( 'test with small express server', function () { it ( '/1sec route data should expire after 1 seconds', function (done) { setTimeout(function () { - var url = 'http://localhost:' + express_port + "/1sec"; - request(url, - function (error, response, body) { + var url = '/1sec'; + request.get(url) + .end(function (error, response) { if ( error ) { throw error; } - var p_body = JSON.parse(body), + var p_body = JSON.parse(response.text), timestamp = p_body.timestamp, now_timestamp = Math.floor(Date.now() / 1000); @@ -152,13 +132,13 @@ describe ( 'test with small express server', function () { it ( '/default_expire route data should expire after 3 seconds', function (done) { this.timeout(4000); // allow 5 secs to execute setTimeout(function () { - var url = 'http://localhost:' + express_port + "/default_expire"; - request(url, - function (error, response, body) { + var url = '/default_expire'; + request.get(url) + .end(function (error, response) { if ( error ) { throw error; } - var p_body = JSON.parse(body), + var p_body = JSON.parse(response.text), timestamp = p_body.timestamp, now_timestamp = Math.floor(Date.now() / 1000); @@ -178,13 +158,13 @@ describe ( 'test with small express server', function () { it ( '/never_expire route data should not expire after 3 seconds', function (done) { this.timeout(4000); // allow 5 secs to execute setTimeout(function () { - var url = 'http://localhost:' + express_port + "/never_expire"; - request(url, - function (error, response, body) { + var url = '/never_expire'; + request.get(url) + .end(function (error, response) { if ( error ) { throw error; } - var p_body = JSON.parse(body), + var p_body = JSON.parse(response.text), timestamp = p_body.timestamp, now_timestamp = Math.floor(Date.now() / 1000); @@ -202,9 +182,9 @@ describe ( 'test with small express server', function () { }); it ( '/never_expire/delete route data should be deleted', function (done) { - var url = 'http://localhost:' + express_port + "/delete_never_expire"; - request(url, - function (error, response, body) { + var url = '/delete_never_expire'; + request.get(url) + .end(function (error, response) { if ( error ) { throw error; } @@ -212,7 +192,7 @@ describe ( 'test with small express server', function () { // or an AssertionError will crash the mocha process on error try { response.statusCode.should.equal(200); - body.should.equal("count:1"); + should(response.text).equal("count:1"); done(); } catch (e) { done(e); @@ -220,10 +200,4 @@ describe ( 'test with small express server', function () { }); }); - - after(function (done) { - process.kill(spawn.pid); - done(); - }); - -}); \ No newline at end of file +}); diff --git a/test/route.js b/test/route.js index f94f1c1..950277a 100644 --- a/test/route.js +++ b/test/route.js @@ -30,7 +30,10 @@ var res = { statusCode: 200, send: function (body) { - + this.socket.write(body); + }, + socket: { + write: function () {} }, _headers: { 'content-type': 'text/plain'