diff --git a/README.md b/README.md index 403cb84..6dcfc41 100644 --- a/README.md +++ b/README.md @@ -111,14 +111,15 @@ If null will be given, the body will be served as string. #### `timeout {number} ` Set a timeout (in milliseconds) for the request. -#### `cache {{ cache: boolean, expires: number }}` +#### `cache {{ cache: boolean, expires: number, cachedFirst: boolean }}` Requistify has built-in Redis based caching mechanism. For using this feature, set the cache property to true using the following object: ```javascript requestify.get('http://examples.com/api/foo', { cache: { cache: true, // Will set caching to true for this request. - expires: 3600 // Time for cache to expire in milliseconds + expires: 3600, // Time for cache to expire in milliseconds + cachedFirst: false // Will return cached data before updating cache } }); ``` diff --git a/lib/requestify.js b/lib/requestify.js index a595099..cb994a2 100644 --- a/lib/requestify.js +++ b/lib/requestify.js @@ -158,6 +158,14 @@ var Requestify = (function() { cache.get(request.getFullUrl()) .then(function(data) { if (!data || (expirationTime(data) <= new Date().getTime())) { + // cachedFirst indicates if we should return the cached data + // before updating it + if (request.cache.cachedFirst) { + // return cached data + defer.resolve(new Response(data.code, data.headers, data.body)); + } + + // make request and update cache call(request, defer); return; } @@ -180,7 +188,15 @@ var Requestify = (function() { /** * Execute HTTP request based on the given method and body * @param {string} url - The URL to execute - * @param {{ method: string, dataType: string, headers: object, body: object, cookies: object, auth: object }} options + * @param {{ + * method: string, + * dataType: string, + * headers: object, + * body: object, + * cookies: object, + * auth: object, + * cache: object + * }} options * @returns {Q.promise} - Returns a promise, once resolved || rejected, Response object is given */ request: function(url, options) { diff --git a/package.json b/package.json index 7e4f43c..c526a79 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "description": "Simplifies node HTTP request making (HTTP client) with caching support.", "version": "0.2.3", "scripts": { - "test": "mocha -R spec test/**/*.js test/*.js" + "test": "mocha -R spec test/**/*.js test/*.js", + "test-watch": "mocha --watch -R spec test/**/*.js test/*.js" }, "license": "MIT", "tags": [ diff --git a/test/requestify-spec.js b/test/requestify-spec.js index 7b73897..3b237ce 100644 --- a/test/requestify-spec.js +++ b/test/requestify-spec.js @@ -5,22 +5,31 @@ var mocha = require('mocha'), expect = require('chai').expect, rewire = require('rewire'), requestify = rewire('../lib/requestify.js'), - Q = require('q'); + Q = require('q'), + Response = require('../lib/response'); describe('Requestify', function() { - var cacheStub; + var cacheStub, + cachedDataStub; afterEach(function() { requestify.responseEncoding('utf8'); }); beforeEach(function() { + cachedDataStub = { + created: new Date().getTime(), + code: 200, + headers: 'Content-Type:application/javascript; charset=utf-8', + body: {rock: "yeah!"} + }; cacheStub = { setCacheTransporter: sinon.stub(), - get: sinon.stub(), + get: sinon.stub().returns(Q.resolve(cachedDataStub)), + // get: sinon.stub(), set: sinon.stub(), purge: sinon.stub(), - isTransportAvailable: sinon.stub() + isTransportAvailable: function() { return true } }; requestify.__set__('cache', cacheStub); @@ -41,18 +50,19 @@ describe('Requestify', function() { describe('#request()', function() { var httpStub, - httpsStub, - cacheStub; + httpsStub; beforeEach(function() { httpStub = sinon.stub().returns({ on: function() {}, - end: function() {} + end: function() {}, + abort: function() {} }); httpsStub = sinon.stub().returns({ on: function() {}, - end: function() {} + end: function() {}, + abort: function() {} }); requestify.__set__('http', { @@ -97,6 +107,28 @@ describe('Requestify', function() { method: 'POST' })).to.have.property('then'); }); + + it('Should return cached response before updating cache', function(done) { + var success = sinon.spy(); + requestify.cacheTransporter(); + var response = new Response(cachedDataStub.code, cachedDataStub.headers, cachedDataStub.body); + + requestify.request('http://wix.com', { + method: 'GET', + cache: { + cache: true, + cachedFirst: true, + expires: -1 // force update + } + }).then(function(response) { + try { + expect(response).to.eql(response); + done(); + } catch (e) { + done(e); + } + }); + }); }); describe('Method specific public methods', function() {