Skip to content

Commit a87f9cb

Browse files
committed
resolves #23
2 parents 7741ae9 + 872033e commit a87f9cb

File tree

8 files changed

+138
-120
lines changed

8 files changed

+138
-120
lines changed

scout-brain/lib/actions/token.js

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ var jwt = require('jsonwebtoken');
33
var boom = require('boom');
44
var debug = require('debug')('scout-brain:token');
55
var _ = require('underscore');
6-
var assert = require('assert');
76

87
var getDeployment = require('./deployment').get;
98
var createSession = require('./session').create;
@@ -26,6 +25,7 @@ function verify(token, fn) {
2625
}
2726

2827
function mount(tokenData, ctx, next) {
28+
debug('mounting token data');
2929
if (!tokenData.session_id) {
3030
return next(boom.badRequest('Bad token: missing session id'));
3131
}
@@ -57,23 +57,19 @@ function mount(tokenData, ctx, next) {
5757
'to `' + ctx.instance_id + '` but it is not in ' +
5858
'deployment `' + tokenData.deployment_id + '`'));
5959
}
60+
}
6061

61-
debug('getting connection for session', tokenData.session_id);
62-
getSession(tokenData.session_id, function(err, connection) {
63-
if (err) return next(err);
64-
65-
ctx.mongo = connection;
66-
return next();
67-
});
62+
debug('getting connection for session', tokenData.session_id);
63+
getSession(tokenData.session_id, function(err, connection) {
64+
if (err) return next(err);
6865

69-
} else {
70-
getSession(tokenData.session_id, function(err, connection) {
71-
if (err) return next(err);
66+
if (!connection) {
67+
return next(boom.forbidden('No session for this token.'));
68+
}
7269

73-
ctx.mongo = connection;
74-
return next();
75-
});
76-
}
70+
ctx.mongo = connection;
71+
return next();
72+
});
7773
});
7874
}
7975

scout-client/lib/client.js

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ Client.prototype.connect = function() {
124124
return this;
125125
}
126126
this.token = new Token(this.config)
127-
.on('readable', this.onTokenReadable.bind(this))
128-
.on('error', this.onTokenError.bind(this));
127+
.on('data', this.onTokenReadable.bind(this))
128+
.on('error', this.onError.bind(this));
129129
return this;
130130
};
131131

@@ -558,7 +558,7 @@ Client.prototype.read = function(path, params, fn) {
558558

559559
if (!this.readable) {
560560
debug('%s not readable. queueing read', this._id, path, params);
561-
return this.on('readable', this.read.bind(this, path, params, fn));
561+
return this.once('readable', this.read.bind(this, path, params, fn));
562562
}
563563

564564
if (typeof params === 'function') {
@@ -618,14 +618,14 @@ Client.prototype.ender = function(fn) {
618618
* @api private
619619
*/
620620
Client.prototype.onTokenReadable = function() {
621-
debug('token now readable');
622-
this.readable = true;
623-
this.context.set(this.token.session);
624621
if (!this.io) {
625622
this._initSocketio();
626623
}
627-
this.emit('readable', this.token.session);
628-
debug('emitted readable on client');
624+
debug('authenticating with scout-server socket.io transport...');
625+
this.io.emit('authenticate', {
626+
token: this.token.toString()
627+
});
628+
629629

630630
if (!this.original) {
631631
this.emit('change');
@@ -642,30 +642,27 @@ Client.prototype.onTokenReadable = function() {
642642
}
643643
};
644644

645-
/**
646-
* We couldn't get a token.
647-
*
648-
* @api private
649-
*/
650-
Client.prototype.onTokenError = function(err) {
651-
debug('Could not get token. Server not running?', err);
652-
this.emit('error', err);
653-
};
654-
655645
Client.prototype._initSocketio = function() {
656646
if (this.io) return;
657647

658-
this.io = socketio(this.config.scout, {
659-
query: 'token=' + this.token.toString()
660-
});
648+
this.io = socketio(this.config.scout);
661649
this.io.on('reconnecting', this.emit.bind(this, 'reconnecting'))
662650
.on('reconnect', this.onReconnect.bind(this))
663651
.on('reconnect_attempt', this.emit.bind(this, 'reconnect_attempt'))
664652
.on('reconnect_failed', this.emit.bind(this, 'reconnect_failed'))
665653
.on('disconnect', this.emit.bind(this, 'disconnect'));
666654
this.io.on('connect', function() {
667655
debug('connected to scout-server socket');
668-
});
656+
this.io.on('authenticated', function() {
657+
debug('Success! Now authenticated with scout-server socket.io transport');
658+
659+
this.readable = true;
660+
this.context.set(this.token.session);
661+
debug('now ready for use');
662+
this.emit('readable', this.token.session);
663+
}.bind(this));
664+
}.bind(this));
665+
this.io.on('error', this.onError.bind(this));
669666
};
670667

671668
/**
@@ -689,20 +686,19 @@ Client.prototype.onUnload = function() {
689686
* @param {Error} err
690687
* @api private
691688
*/
692-
Client.prototype.onTokenError = function(err) {
693-
this.dead = err;
694-
if (err >= 500) {
695-
this.dead.message += ' (scout-server dead at ' + this.config.scout + '?)';
689+
Client.prototype.onError = function(err) {
690+
if (err.message === 'Origin is not allowed by Access-Control-Allow-Origin') {
691+
err.message = 'scout-server not running at ' + this.config.scout + '?';
696692
}
693+
// @todo: Exponential back-off to retry connecting.
694+
this.dead = err;
697695
this.emit('error', err);
698696
};
699697

700698
Client.prototype.onReconnect = function() {
701699
debug('reconnected. getting new token');
702700
this.token = new Token(this.config)
703701
.on('readable', function() {
704-
this.readable = true;
705-
this.context.set(this.token.session);
706702
this._initSocketio();
707703
}.bind(this))
708704
.on('error', this.emit.bind(this, 'error'));
@@ -736,7 +732,7 @@ Client.prototype.createReadStream = function(_id, data) {
736732
return debug('proxy already transferred');
737733
}
738734
});
739-
this.on('readable', function() {
735+
this.once('readable', function() {
740736
debug('client readable');
741737
var src = client.createReadStream(_id, data);
742738
src.on('data', proxy.emit.bind(proxy, 'data'));
@@ -752,6 +748,10 @@ Client.prototype.createReadStream = function(_id, data) {
752748
data = data || {};
753749
var stream = ss.createStream(this.io);
754750
ss(this.io).emit(_id, stream, data);
755-
return stream.pipe(EJSON.createParseStream());
751+
752+
var parser = EJSON.createParseStream();
753+
var res = stream.pipe(parser);
754+
stream.on('error', res.emit.bind(res, 'error'));
755+
return res;
756756
}
757757
};

scout-client/lib/token.js

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,11 @@ function Token(config) {
1111
this.config = config;
1212
this.expirationRedLine = 15 * 1000;
1313
this.session = {};
14-
this.readable = false;
1514

1615
process.nextTick(function() {
17-
this.bake(function(err, res) {
16+
this.bake(function(err) {
1817
if (err) return this.emit('error', err);
19-
20-
this.session = res;
2118
this.schedule();
22-
23-
this.readable = true;
24-
debug('emit readable!');
25-
this.emit('readable');
2619
}.bind(this));
2720
}.bind(this));
2821
}
@@ -47,21 +40,22 @@ Token.prototype.close = function(fn) {
4740
clearTimeout(this.refreshTimeout);
4841
debug('closing token');
4942
request.del(this.config.scout + '/api/v1/token')
50-
.set('Accept', 'application/json')
51-
.set('Authorization', 'Bearer ' + this.session.token)
52-
.end(function(err, res) {
53-
debug('response from token close');
54-
fn(err, res);
55-
});
43+
.set('Accept', 'application/json')
44+
.set('Authorization', 'Bearer ' + this.session.token)
45+
.end(function(err, res) {
46+
debug('response from token close');
47+
fn(err, res);
48+
});
5649
};
5750

5851
Token.prototype.bake = function(done) {
5952
var payload = {
6053
seed: this.config.seed
6154
};
6255

63-
if (this.config.timeout)
56+
if (this.config.timeout) {
6457
payload.timeout = this.config.timeout;
58+
}
6559

6660
if (this.config.auth) {
6761
Object.keys(this.config.auth).map(function(name) {
@@ -73,36 +67,43 @@ Token.prototype.bake = function(done) {
7367
}
7468
debug('getting token for', this.config.seed, payload);
7569
request.post(this.config.scout + '/api/v1/token')
76-
.send(payload)
77-
.set('Accept', 'application/json')
78-
.end(function(err, res) {
79-
if (err) return done(err);
80-
81-
if (!err && res.status >= 400) {
82-
err = new Error(res.body ? res.body.message : res.text);
83-
err.code = res.status;
84-
Error.captureStackTrace(err, Token.prototype.bake);
85-
return done(err);
86-
}
87-
88-
if (!res.body.expires_at || !res.body.created_at) {
89-
return done(new Error('Malformed response. Missing expires_at or created_at'));
90-
}
91-
92-
if (new Date(res.body.expires_at) - Date.now() < (1 * 60 * 1000)) {
93-
return done(new Error('Got an expires that is less than a minute from now.'));
94-
}
95-
96-
done(null, res.body);
97-
}.bind(this));
70+
.send(payload)
71+
.set('Accept', 'application/json')
72+
.end(function(err, res) {
73+
if (err) {
74+
if (res && res.body) {
75+
err.message += ': ' + res.body.message;
76+
}
77+
console.error('Error getting token:', err);
78+
return done(err);
79+
}
80+
81+
if (!err && res.status >= 400) {
82+
err = new Error(res.body ? res.body.message : res.text);
83+
err.code = res.status;
84+
Error.captureStackTrace(err, Token.prototype.bake);
85+
return done(err);
86+
}
87+
88+
if (!res.body.expires_at || !res.body.created_at) {
89+
return done(new Error('Malformed response. Missing expires_at or created_at'));
90+
}
91+
92+
if (new Date(res.body.expires_at) - Date.now() < (1 * 60 * 1000)) {
93+
return done(new Error('Got an expires that is less than a minute from now.'));
94+
}
95+
96+
this.session = res.body;
97+
this.emit('data', this.session);
98+
99+
done(null, res.body);
100+
}.bind(this));
98101
};
99102

100103
Token.prototype.refresh = function() {
101-
this.bake(function(err, res) {
104+
this.bake(function(err) {
102105
if (err) return this.emit('error', err);
103-
if (!res) return this.emit('error', new Error('Empty response with no error'));
104106

105-
this.session = res;
106107
debug('token refreshed successfully');
107108
return this.schedule();
108109
}.bind(this));
@@ -114,5 +115,6 @@ Token.prototype.schedule = function() {
114115
return this;
115116
}
116117
var ms = (new Date(this.session.expires_at) - Date.now()) - this.expirationRedLine;
118+
debug('scheduling token refresh %dms from now', ms);
117119
this.refreshTimeout = setTimeout(this.refresh.bind(this), ms);
118120
};

scout-server/lib/index.js

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,30 @@ var urldecode = require('body-parser').urlencoded({
1414
app.server = require('http').createServer(app);
1515
app.config = require('mongoscope-config');
1616

17-
if (process.env.NODE_ENV = 'development') {
18-
app.use(require('connect-livereload')({
19-
port: 35729,
20-
include: ['./']
21-
}));
22-
var livereload = require('tiny-lr')();
23-
var watch = require('watch');
24-
25-
livereload.listen(35729, '127.0.0.1');
26-
27-
watch.watchTree(__dirname + '/../', {
28-
filter: function(filename) {
29-
return !(/node_modules/.test(filename));
30-
},
31-
ignoreDotFiles: true
32-
}, function(files) {
33-
livereload.changed({
34-
body: {
35-
files: files
36-
}
37-
});
38-
});
39-
}
17+
// @todo: this should be moved to scout-electron now.
18+
// if (process.env.NODE_ENV = 'development') {
19+
// app.use(require('connect-livereload')({
20+
// port: 35729,
21+
// include: ['./']
22+
// }));
23+
// var livereload = require('tiny-lr')();
24+
// var watch = require('watch');
25+
26+
// livereload.listen(35729, '127.0.0.1');
27+
28+
// watch.watchTree(__dirname + '/../', {
29+
// filter: function(filename) {
30+
// return !(/node_modules/.test(filename));
31+
// },
32+
// ignoreDotFiles: true
33+
// }, function(files) {
34+
// livereload.changed({
35+
// body: {
36+
// files: files
37+
// }
38+
// });
39+
// });
40+
// }
4041

4142

4243
app.use(require('./middleware/watch-event-loop-blocking'));

0 commit comments

Comments
 (0)