diff --git a/README.md b/README.md index 23cf042..1869273 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,15 @@ If instead you want to allow everything to be cached, except your "/api/users" a httpRequestInterceptorCacheBusterProvider.setMatchlist([/.*orders.*/,/.*users.*/],true); }); +If you need custom logic instead of regular expression matching, you can supply a match function instead of a matchlist. The second boolean argument "blacklist" operates the same. The match function is called with a single url argument. Return a truthy value if the url matches: + + angular.module('yourApp', ['ngCacheBuster']) + .config(function(httpRequestInterceptorCacheBusterProvider){ + httpRequestInterceptorCacheBusterProvider.setMatchFunction(function(url) { + return url.length % 2; + },true); + }); + # use That's it! All your resource calls will have a cache buster added for anything not in the whitelist, or if you specified "blacklist", for everything matching the blacklist, diff --git a/angular-cache-buster.js b/angular-cache-buster.js index a368a50..cfe1a05 100644 --- a/angular-cache-buster.js +++ b/angular-cache-buster.js @@ -2,61 +2,70 @@ angular.module('ngCacheBuster', []) .config(['$httpProvider', function($httpProvider) { return $httpProvider.interceptors.push('httpRequestInterceptorCacheBuster'); }]) - .provider('httpRequestInterceptorCacheBuster', function() { - - this.matchlist = [/.*partials.*/, /.*views.*/ ]; - this.logRequests = false; - - //Default to whitelist (i.e. block all except matches) - this.black=false; - - //Select blacklist or whitelist, default to whitelist - this.setMatchlist = function(list,black) { - this.black = typeof black != 'undefined' ? black : false - this.matchlist = list; - }; - - - this.setLogRequests = function(logRequests) { - this.logRequests = logRequests; - }; - - this.$get = ['$q', '$log', function($q, $log) { - var matchlist = this.matchlist; - var logRequests = this.logRequests; - var black = this.black; - if (logRequests) { - $log.log("Blacklist? ",black); - } - return { - 'request': function(config) { - //Blacklist by default, match with whitelist - var busted= !black; - - for(var i=0; i< matchlist.length; i++){ - if(config.url.match(matchlist[i])) { - busted=black; break; - } - } - - //Bust if the URL was on blacklist or not on whitelist - if (busted) { - var d = new Date(); - config.url = config.url.replace(/[?|&]cacheBuster=\d+/,''); - //Some url's allready have '?' attached - config.url+=config.url.indexOf('?') === -1 ? '?' : '&' - config.url += 'cacheBuster=' + d.getTime(); - } - - if (logRequests) { - var log='request.url =' + config.url - busted ? $log.warn(log) : $log.info(log) - } - - return config || $q.when(config); - } - } - }]; - }); + .provider('httpRequestInterceptorCacheBuster', function() { + + this.matchlist = [/.*partials.*/, /.*views.*/ ]; + this.logRequests = false; + + //Default to whitelist (i.e. block all except matches) + this.black=false; + + //Select blacklist or whitelist, default to whitelist + this.setMatchlist = function(list, black) { + this.black = typeof black != 'undefined' ? black : false; + this.matchlist = list; + }; + + this.setMatchFunction = function(matchFn, black) { + this.black = typeof black != 'undefined' ? black : false; + this.matchFn = matchFn; + }; + this.setLogRequests = function(logRequests) { + this.logRequests = logRequests; + }; + this.$get = ['$q', '$log', function($q, $log) { + var matchlist = this.matchlist; + var matchFn = this.matchFn; + var logRequests = this.logRequests; + var black = this.black; + if (logRequests) { + $log.log("Blacklist? ", black); + } + return { + 'request': function(config) { + //Blacklist by default, match with whitelist + var busted = !black; + + if (typeof matchFn === 'function') { + if (matchFn(config.url)) { + busted = black; + } + } else { + for(var i = 0; i < matchlist.length; i++){ + if (config.url.match(matchlist[i])) { + busted = black; break; + } + } + } + + //Bust if the URL was on blacklist or not on whitelist + if (busted) { + var d = new Date(); + config.url = config.url.replace(/[?|&]cacheBuster=\d+/, ''); + //Some url's allready have '?' attached + config.url += config.url.indexOf('?') === -1 ? '?' : '&' + config.url += 'cacheBuster=' + d.getTime(); + } + + if (logRequests) { + var log = 'request.url =' + config.url + busted ? $log.warn(log) : $log.info(log) + } + + return config || $q.when(config); + } + } + }]; + }); diff --git a/package.json b/package.json index 5f1c7b3..6bbc584 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,10 @@ "ie9" ], "author": "saintmac (Martin Saint-Macary, http://vyte.in)", - "contributors": ["Alfred Bratterud "], + "contributors": [ + "Alfred Bratterud ", + "Donovan Mikrot " + ], "license": "MIT", "bugs": { "url": "https://github.com/saintmac/angular-cache-buster/issues" @@ -38,6 +41,7 @@ "requirejs": "~2.1.11", "karma-requirejs": "~0.2.1", "karma-phantomjs-launcher": "~0.1.2", - "karma": "~0.12.15" + "karma": "~0.12.15", + "karma-junit-reporter": "~0.3.3" } } diff --git a/test/test.js b/test/test.js index 1a0d6b6..7cd8839 100644 --- a/test/test.js +++ b/test/test.js @@ -6,7 +6,7 @@ describe('ngCacheBuster', function () { beforeEach(inject(function($injector) { $httpBackend = $injector.get('$httpBackend'); - $http = $injector.get('$http'); + $http = $injector.get('$http'); })); afterEach(function() { @@ -62,7 +62,7 @@ describe('ngCacheBuster', function () { $httpBackend.verifyNoOutstandingExpectation(); $httpBackend.verifyNoOutstandingRequest(); }); - + //Whitelist, views describe('with a views request', function() { it('should add a cache buster', function() { @@ -176,7 +176,7 @@ describe('ngCacheBuster', function () { $httpBackend.flush(); }); }); - + //Blacklist, other describe('with any other request', function() { it('should not add a cache buster', function() { @@ -186,7 +186,90 @@ describe('ngCacheBuster', function () { $httpBackend.flush(); }); }); - - + }); + + //Match function + describe('configuring the provider with a match function', function() { + beforeEach(function() { + var matchlist = [/.*users.*/, /.*orders.*/]; + module('ngCacheBuster'); + module(function(httpRequestInterceptorCacheBusterProvider){ + httpRequestInterceptorCacheBusterProvider.setMatchFunction(function (url) { + for(var i = 0; i < matchlist.length; i++){ + if (url.match(matchlist[i])) { + return true; + } + } + return false; + }, true); + httpRequestInterceptorCacheBusterProvider.setLogRequests(true); + }); + }); + + beforeEach(inject(function($injector) { + $httpBackend = $injector.get('$httpBackend'); + $http = $injector.get('$http'); + })); + + afterEach(function() { + $httpBackend.verifyNoOutstandingExpectation(); + $httpBackend.verifyNoOutstandingRequest(); + }); + + //Match function, users + describe('with an api/users request', function() { + it('should add a cache buster', function() { + var req = '/api/users/654645'; + var regex_friendly_req = req.replace(/\//g, '\\/'); + var expected = new RegExp(regex_friendly_req + '\\?cacheBuster=[0-9]+') + $httpBackend.expectGET(expected).respond(200); + $http.get(req); + $httpBackend.flush(); + }); + }); + + //Match function, api/orders + describe('with an api/orders request', function() { + it('should add a cache buster', function() { + var req = '/api/orders/654645'; + var regex_friendly_req = req.replace(/\//g, '\\/'); + var expected = new RegExp(regex_friendly_req + '\\?cacheBuster=[0-9]+') + $httpBackend.expectGET(expected).respond(200); + $http.get(req); + $httpBackend.flush(); + }); + }); + + //Match function, with existing query params + describe('with an api/orders request with existing query-string parameter', function() { + it('should add a cache buster, but not break existing params', function() { + var req = '/api/orders/654645?orderid=115'; + var regex_friendly_req = req.replace(/\//g, '\\/').replace(/\?/g,'\\?') + var expected = new RegExp(regex_friendly_req + '&cacheBuster=[0-9]+') + $httpBackend.expectGET(expected).respond(200); + $http.get(req); + $httpBackend.flush(); + }); + }); + + //Match function, partials + describe('with a partials request', function() { + it('should not add a cache buster', function() { + var req = '/bower_components/mymodule/partials/home.html'; + $httpBackend.expectGET(req).respond(200); + $http.get(req); + $httpBackend.flush(); + }); + }); + + //Match function, other + describe('with any other request', function() { + it('should not add a cache buster', function() { + var req = '/task/1234'; + $httpBackend.expectGET(req).respond(200); + $http.get(req); + $httpBackend.flush(); + }); + }); }); });