-
Notifications
You must be signed in to change notification settings - Fork 0
/
cacherp.js
204 lines (183 loc) · 6.71 KB
/
cacherp.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/**
* angular-hu-cacherp v1.1.0
* https://github.com/angular-hu/angular-hu
* (c) 2015 Telefónica I+D - http://www.tid.es
* @license MIT
*/
(function(angular) {
/**
* @ngdoc service
* @name huCacherpFactory
*
* @description
* Decorates {@link $cacheFactory $cacheFactory} allowing to remove some queryString parameters
* from an URL based key.
* This type of cache is meant to be used by $http or similar, and will
* put in the cache URL's as keys, but with the specified parameters names (and its values)
* removed.
* It's very useful to cache request to timestamped signed endpoints, where there
* are always variable parameters for security, but not for functionality: Ex: oauth1
*
* ```js
* var cache = huCacherpFactory('cacheId', {
* removableParams: [
* 'oauth_nonce',
* 'oauth_timestamp',
* 'oauth_signature'
* ]
* }, $cacheFactory);
* expect($cacheFactory.get('cacheId')).toBe(cache);
* expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
*
* cache.put('www.foo.com/a?oauth_nonce', 'value');
* cache.put('another key', 'another value');
*
* expect(cache.get('www.foo.com/a?oauth_nonce')).toBe('value');
* expect(cache.get('www.foo.com/a')).toBe('value');
* expect(cache.get('another key')).toBe('another value');
*
* expect(cache.info()).toEqual({id: 'cacheId', size: 2});
*
* ```
*
*
* @param {string} cacheId Name or id of the newly created cache.
* @param {object=} options Options object that specifies the cache behavior. It's forwarded
* to the $cacheFactory execution. Properties:
* - `{number=}` `removableParams` — removes the following param names from the key
* @param {function} [cacheFactory] Optional cache Factory function. A function method
* with a $cacheFactory compatible API
*
* @returns {object} Newly created cache object with the following set of methods:
*
* - `{object}` `info()` — Returns id, size, and options of cache.
* - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns it.
* - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
* - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
* - `{void}` `removeAll()` — Removes all cached values.
* - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
*
*/
angular.module('httpu.cacherp', [])
.factory('huCacherpFactory', httpuCacheRemovableParamsFactory)
.factory('huCacherp', httpuCacheRemovableParams);
httpuCacheRemovableParamsFactory.$inject = ['$injector', 'huCacherp'];
function httpuCacheRemovableParamsFactory($injector, huCacherp) {
return function httpuCacheRemovableParamsFactory(cacheName, options, cacheFactory) {
cacheFactory = cacheFactory || $injector.get('$cacheFactory');
var cache = cacheFactory(cacheName, options),
removableParams = (options && options.removableParams) || [];
return huCacherp(cache, removableParams);
};
}
httpuCacheRemovableParams.$inject = ['$document'];
function httpuCacheRemovableParams($document) {
'use strict';
//URL Parser according to VanillaJS
//http://vanilla-js.com/
var parser = $document[0].createElement('a');
return httpuCacheRemovableParamsDecorator;
//////////////////////////
/**
* Converts an assignment in to a key, value object
* @param {String} param in form of 'key=value'
* @returns {{key: *, value: *}}
* @private
*/
function toKeyValue(param) {
var split = param.split('=');
return {
key: split[0],
value: split[1]
};
}
/**
* Check if the key of an object is suitable for removal
*
* @param {Array.<String>} removableParameters
* @param {{key: *, value: *}} obj
* @returns {boolean}
* @private
*/
function isRemovable(removableParameters, obj) {
return removableParameters.indexOf(obj.key) < 0;
}
/**
* Concats in an Array a key, value object converted to a equality
* of type 'key=value'
*
* @param {Array} memo The original array
* @param {{key: *, value: *}} obj The object to convert
* @returns {Array} The memo array with the 'key=value' item concatenated
* @private
*/
function toEquality(memo, obj) {
var param = typeof obj.value === 'undefined' ?
obj.key :
obj.key + '=' + obj.value;
return memo.concat(param);
}
/**
* Sort iterator for key, value objects
*
* @param {{key: *, value: *}} a
* @param {{key: *, value: *}} b
* @returns {Number}
* @private
*/
function sortByKey(a, b) {
return a.key > b.key ? 1 : -1;
}
/**
* Removes the specified parameters names an its values from an url
*
* @param {Array({String})} removableParameters The parameters names
* to remove from the URL
* @param {String} url The original url
* @returns {String} The URL without specified parameters
* @private
*/
function removeParamsFromUrl(removableParameters, url) {
parser.href = url;
var search = parser.search.indexOf('?') === 0 ?
parser.search.substring(1) :
parser.search;
if (search) {
parser.search = search
.split('&')
.map(toKeyValue)
.filter(angular.bind(null, isRemovable, removableParameters))
.sort(sortByKey)
.reduce(toEquality, [])
.join('&');
}
//safari adds '?' to the href when search !== null,
//but other browsers don't. Remove trailing ?
return parser.href.substr(parser.href.length - 1) === '?' ?
parser.href.substring(0, parser.href.length - 1) :
parser.href;
}
function httpuCacheRemovableParamsDecorator(cache, removableParams) {
var originalCacheGet = cache.get,
originalCachePut = cache.put,
originalCacheRemove = cache.remove,
originalCacheInfo = cache.info,
cleanUrl = angular.bind(null, removeParamsFromUrl, removableParams);
cache.get = function huCacherpGet(url) {
return originalCacheGet.call(cache, cleanUrl(url));
};
cache.put = function huCacherpPut(url, data) {
return originalCachePut.call(cache, cleanUrl(url), data);
};
cache.remove = function huCacherpRemove(url) {
return originalCacheRemove.call(cache, cleanUrl(url));
};
cache.info = function huCacherpInfo() {
return angular.extend(originalCacheInfo.call(cache), {
removableParams: removableParams
});
};
return cache;
}
}
})(window.angular);