Skip to content

Commit ffb337f

Browse files
committed
feat(headers): Add default headers and merging of request headers.
1 parent d086135 commit ffb337f

File tree

7 files changed

+173
-62
lines changed

7 files changed

+173
-62
lines changed

bower.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{
22
"name": "angular-sails",
3-
"version": "1.1.0",
3+
"version": "2.0.0-beta.2",
44
"authors": [
5-
"Jan-Oliver Pantel <[email protected]>"
5+
"Jan-Oliver Pantel <[email protected]>",
6+
"Evan Sharp <[email protected]>"
67
],
78
"description": "An angular provider for using the sails socket.io api",
89
"main": "./dist/angular-sails.js",
@@ -16,7 +17,7 @@
1617
"api"
1718
],
1819
"license": "MIT",
19-
"homepage": "https://github.com/kyjan/angular-sails",
20+
"homepage": "https://github.com/janpantel/angular-sails",
2021
"dependencies": {
2122
"angular": ">=1.2.*",
2223
"socket.io-client": ">=1.3.0"

mock/socket-io.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ function createMockSocketObject() {
6060
delete this._listeners[ev];
6161
}
6262
},
63+
off: function(ev, fn) {
64+
if (fn) {
65+
var index = this._listeners[ev].indexOf(fn);
66+
if (index > -1) {
67+
this._listeners[ev].splice(index, 1);
68+
}
69+
} else {
70+
delete this._listeners[ev];
71+
}
72+
},
6373
removeAllListeners: function(ev) {
6474
if (ev) {
6575
delete this._listeners[ev];

package.json

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
11
{
22
"name": "angular-sails",
33
"private": true,
4-
"version": "1.1.0",
4+
"version": "2.0.0-beta.2",
55
"description": "An angular provider for using the sails socket.io api",
66
"scripts": {
7-
"build": "gulp build-js",
7+
"build": "gulp build",
88
"test": "gulp test"
99
},
10+
"main": "dist/angular-sails.js",
1011
"repository": {
1112
"type": "git",
1213
"url": "https://github.com/kyjan/angular-sails.git"
1314
},
14-
"author": "Jan-Oliver Pantel <[email protected]>",
15+
"author": "Jan-Oliver Pantel <[email protected]>",
16+
"contributors": [
17+
"Jan-Oliver Pantel <[email protected]>",
18+
"Evan Sharp <[email protected]>"
19+
],
1520
"license": "MIT",
1621
"bugs": {
17-
"url": "https://github.com/kyjan/angular-sails/issues"
22+
"url": "https://github.com/janpantel/angular-sails/issues"
1823
},
19-
"homepage": "https://github.com/kyjan/angular-sails",
24+
"homepage": "https://github.com/janpantel/angular-sails",
2025
"devDependencies": {
2126
"chai": "^1.10.0",
2227
"gulp": "^3.5.6",

src/service/$sails.js

Lines changed: 62 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
/* jshint newcap: false */
44
/* global headersGetter: true,
5+
mergeHeaders: true,
56
arrIndexOf: true,
67
isFile: true,
78
isBlob: true
@@ -26,9 +27,9 @@ function $sails($sailsInterceptorProvider, $sailsIoProvider) {
2627
};
2728

2829
provider.defaults = {
29-
transformResponse: [],
30-
transformRequest: [],
31-
headers: {} // TODO: default headers
30+
transformResponse: [],
31+
transformRequest: [],
32+
headers: {} // TODO: what should the default default headers
3233
};
3334

3435
provider.interceptors = $sailsInterceptorProvider.interceptors = [
@@ -42,17 +43,17 @@ function $sails($sailsInterceptorProvider, $sailsIoProvider) {
4243
}*/
4344
];
4445

45-
this.$get = function($q, $log, $timeout, $sailsIo, $sailsInterceptor) {
46+
this.$get = function($rootScope, $q, $log, $timeout, $sailsIo, $sailsInterceptor) {
4647
var socket = new $sailsIo(provider.socket || provider.url, provider.config);
47-
var socketFunctions = ['connect','disconnect','isConnected'];
48+
var socketFunctions = ['connect', 'disconnect', 'isConnected'];
4849

4950
function $sails(config) {
5051
return $sails[config.method](config.url, config);
5152
}
5253

5354
$sails._socket = socket;
5455

55-
function exposeSocketFunction(fnName){
56+
function exposeSocketFunction(fnName) {
5657
$sails[fnName] = socket[fnName].bind(socket);
5758
}
5859

@@ -62,8 +63,7 @@ function $sails($sailsInterceptorProvider, $sailsIoProvider) {
6263
var config = {
6364
method: methodName,
6465
transformRequest: provider.defaults.transformRequest,
65-
transformResponse: provider.defaults.transformResponse,
66-
headers: {}// TODO: default headers
66+
transformResponse: provider.defaults.transformResponse
6767
};
6868

6969
requestConfig = requestConfig || {};
@@ -76,9 +76,14 @@ function $sails($sailsInterceptorProvider, $sailsIoProvider) {
7676
requestConfig.data = data;
7777
}
7878

79-
angular.extend(config, requestConfig);
79+
config = angular.extend({}, config, requestConfig);
80+
config.headers = mergeHeaders(requestConfig, provider.defaults.headers);
8081
config.url = (provider.urlPrefix || '') + (url || config.url);
81-
config.method = (config.method || methodName).toUpperCase();
82+
config.method = angular.uppercase(config.method || methodName);
83+
84+
if (angular.isUndefined(config.withCredentials) && !angular.isUndefined(provider.defaults.withCredentials)) {
85+
config.withCredentials = provider.defaults.withCredentials;
86+
}
8287

8388
var promise = $sailsInterceptor(socket[methodName].bind(socket), config);
8489

@@ -113,56 +118,62 @@ function $sails($sailsInterceptorProvider, $sailsIoProvider) {
113118
* Update a model on sails pushes
114119
* @param {String} name Sails model name
115120
* @param {Array} models Array with model objects
121+
* @returns {Function} Function to remove the model updater instance
116122
*/
117123
$sails.$modelUpdater = function(name, models) {
118124

119-
socket.on(name, function(message) {
120-
var i;
125+
var update = function(message) {
121126

122-
if (provider.debug) {
123-
$log.info('$sails ' + name + ' model ' + message.verb + ' id: ' + message.id, message.data);
124-
}
127+
$rootScope.$evalAsync(function() {
128+
var i;
125129

126-
switch (message.verb) {
130+
switch (message.verb) {
127131

128-
case "created":
129-
// create new model item
130-
models.push(message.data);
131-
break;
132+
case "created":
133+
// create new model item
134+
models.push(message.data);
135+
break;
132136

133-
case "updated":
134-
var obj;
135-
for (i = 0; i < models.length; i++) {
136-
if (models[i].id === message.id) {
137-
obj = models[i];
138-
break;
137+
case "updated":
138+
var obj;
139+
for (i = 0; i < models.length; i++) {
140+
if (models[i].id === message.id) {
141+
obj = models[i];
142+
break;
143+
}
139144
}
140-
}
141-
142-
// cant update if the angular-model does not have the item and the
143-
// sails message does not give us the previous record
144-
if (!obj && !message.previous) return;
145-
146-
if (!obj) {
147-
// sails has given us the previous record, create it in our model
148-
obj = message.previous;
149-
models.push(obj);
150-
}
151-
152-
// update the model item
153-
angular.extend(obj, message.data);
154-
break;
155-
156-
case "destroyed":
157-
for (i = 0; i < models.length; i++) {
158-
if (models[i].id === message.id) {
159-
models.splice(i, 1);
160-
break;
145+
146+
// cant update if the angular-model does not have the item and the
147+
// sails message does not give us the previous record
148+
if (!obj && !message.previous) return;
149+
150+
if (!obj) {
151+
// sails has given us the previous record, create it in our model
152+
obj = message.previous;
153+
models.push(obj);
161154
}
162-
}
163-
break;
164-
}
165-
});
155+
156+
// update the model item
157+
angular.extend(obj, message.data);
158+
break;
159+
160+
case "destroyed":
161+
for (i = 0; i < models.length; i++) {
162+
if (models[i].id === message.id) {
163+
models.splice(i, 1);
164+
break;
165+
}
166+
}
167+
break;
168+
}
169+
});
170+
};
171+
172+
socket._socket.on(name, update);
173+
174+
return function() {
175+
socket._socket.off(name, update);
176+
};
166177
};
167178

168179
$sails.defaults = this.defaults;

src/service/$sailsIo.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ function $sailsIo() {
8585

8686
SailsIo.prototype._send = function(req, res) {
8787
var self = this;
88-
var sailsEndpoint = req.method.toLowerCase();
88+
var sailsEndpoint = angular.lowercase(req.method);
8989

9090
self.connectDefer.promise.then(function sendRequest() {
9191
if (provider.debug) {
@@ -132,7 +132,7 @@ function $sailsIo() {
132132
req.url = buildUrl(req.url.replace(/^(.+)\/*\s*$/, '$1'), req.params);
133133
req.headers = req.headers || {};
134134
req.data = req.data || {};
135-
req.method = req.method.toUpperCase();
135+
req.method = angular.uppercase(req.method);
136136

137137
if (typeof req.url !== 'string') {
138138
throw new Error('Invalid or missing URL!');

src/util.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,67 @@ function parseHeaders(headers) {
1616
return parsed;
1717
}
1818

19+
function executeHeaderFns(headers, config) {
20+
var headerContent, processedHeaders = {};
21+
22+
angular.forEach(headers, function(headerFn, header) {
23+
if (angular.isFunction(headerFn)) {
24+
headerContent = headerFn(config);
25+
if (headerContent != null) {
26+
processedHeaders[header] = headerContent;
27+
}
28+
} else {
29+
processedHeaders[header] = headerFn;
30+
}
31+
});
32+
33+
return processedHeaders;
34+
}
35+
36+
function mergeHeaders(config, defHeaders) {
37+
var reqHeaders = angular.extend({}, config.headers),
38+
defHeaderName, lowercaseDefHeaderName, reqHeaderName;
39+
40+
defHeaders = angular.extend({}, defHeaders.common, defHeaders[angular.lowercase(config.method)]);
41+
42+
// using for-in instead of forEach to avoid unecessary iteration after header has been found
43+
defaultHeadersIteration:
44+
for (defHeaderName in defHeaders) {
45+
lowercaseDefHeaderName = angular.lowercase(defHeaderName);
46+
47+
for (reqHeaderName in reqHeaders) {
48+
if (angular.lowercase(reqHeaderName) === lowercaseDefHeaderName) {
49+
continue defaultHeadersIteration;
50+
}
51+
}
52+
53+
reqHeaders[defHeaderName] = defHeaders[defHeaderName];
54+
}
55+
56+
// execute if header value is a function for merged headers
57+
return executeHeaderFns(reqHeaders, shallowCopy(config));
58+
}
59+
60+
function shallowCopy(src, dst) {
61+
if (angular.isArray(src)) {
62+
dst = dst || [];
63+
64+
for (var i = 0, ii = src.length; i < ii; i++) {
65+
dst[i] = src[i];
66+
}
67+
} else if (angular.isObject(src)) {
68+
dst = dst || {};
69+
70+
for (var key in src) {
71+
if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
72+
dst[key] = src[key];
73+
}
74+
}
75+
}
76+
77+
return dst || src;
78+
}
79+
1980
function trim(value) {
2081
return angular.isString(value) ? value.trim() : value;
2182
}

test/angular-sails-service.spec.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,11 @@ describe('Agnular Sails service', function() {
232232

233233
var models;
234234
var modelResponse;
235+
var removeUpdater;
235236

236237
beforeEach(function() {
237238
models = [];
238-
$sails.$modelUpdater('user', models);
239+
removeUpdater = $sails.$modelUpdater('user', models);
239240
modelResponse = {
240241
created:{
241242
data: {
@@ -291,6 +292,28 @@ describe('Agnular Sails service', function() {
291292
expect(models[0].name).to.equal(modelResponse.updated.data.name);
292293
});
293294

295+
describe('returned function', function(){
296+
it('should remove the socket listener', function () {
297+
removeUpdater();
298+
$scope.$digest();
299+
mockIoSocket.emit('user', modelResponse.created);
300+
$scope.$digest();
301+
expect(models).to.be.empty();
302+
});
303+
304+
it('should remove only the socket listener it is called on', function () {
305+
var tasks = [];
306+
$sails.$modelUpdater('tasks', tasks);
307+
removeUpdater();
308+
$scope.$digest();
309+
mockIoSocket.emit('user', modelResponse.created);
310+
mockIoSocket.emit('tasks', modelResponse.created);
311+
$scope.$digest();
312+
expect(tasks).to.contain(modelResponse.created.data);
313+
expect(models).to.be.empty();
314+
});
315+
});
316+
294317
});
295318

296319
});

0 commit comments

Comments
 (0)