Skip to content

Commit d3aa9b4

Browse files
authored
Merge pull request #39 from andrewmaillet/optional-middleware-continuation
Add option to continue middleware execution
2 parents 83086af + c5b6fc9 commit d3aa9b4

File tree

4 files changed

+112
-18
lines changed

4 files changed

+112
-18
lines changed

Readme.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,28 @@ app.use(function(req, res) {
3434

3535
app.listen(3000);
3636
```
37+
38+
## Options
39+
40+
```
41+
var options = {
42+
useErrorHandler: false,
43+
continueMiddleWare: false,
44+
}
45+
```
46+
* `useErrorHandler`
47+
(_type: boolean_ default: false)
48+
49+
If false, an error response will be rendered by this component.
50+
Set this value to true to allow your own express error handler to handle the error.
51+
52+
* `continueMiddleware`
53+
(_type: boolean default: false_)
54+
55+
The `authorize()` and `token()` middlewares will both render their
56+
result to the response and end the pipeline.
57+
next() will only be called if this is set to true.
58+
59+
**Note:** You cannot modify the response since the headers have already been sent.
60+
61+
`authenticate()` does not modify the response and will always call next()

index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ function ExpressOAuthServer(options) {
2525
this.useErrorHandler = options.useErrorHandler ? true : false;
2626
delete options.useErrorHandler;
2727

28+
this.continueMiddleware = options.continueMiddleware ? true : false;
29+
delete options.continueMiddleware;
30+
2831
this.server = new NodeOAuthServer(options);
2932
}
3033

@@ -78,6 +81,9 @@ ExpressOAuthServer.prototype.authorize = function(options) {
7881
})
7982
.tap(function(code) {
8083
res.locals.oauth = { code: code };
84+
if (this.continueMiddleware) {
85+
next();
86+
}
8187
})
8288
.then(function() {
8389
return handleResponse.call(this, req, res, response);
@@ -109,6 +115,9 @@ ExpressOAuthServer.prototype.token = function(options) {
109115
})
110116
.tap(function(token) {
111117
res.locals.oauth = { token: token };
118+
if (this.continueMiddleware) {
119+
next();
120+
}
112121
})
113122
.then(function() {
114123
return handleResponse.call(this, req, res, response);

test/integration/index_test.js

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ var bodyparser = require('body-parser');
1111
var express = require('express');
1212
var request = require('supertest');
1313
var should = require('should');
14+
var sinon = require('sinon');
1415

1516
/**
1617
* Test `ExpressOAuthServer`.
@@ -91,17 +92,21 @@ describe('ExpressOAuthServer', function() {
9192
var oauth = new ExpressOAuthServer({ model: model });
9293

9394
app.use(oauth.authenticate());
94-
95-
app.use(function(req, res, next) {
95+
96+
var spy = sinon.spy(function(req, res, next) {
9697
res.locals.oauth.token.should.equal(token);
9798

9899
next();
99100
});
101+
app.use(spy);
100102

101103
request(app.listen())
102104
.get('/')
103105
.set('Authorization', 'Bearer foobar')
104-
.end(done);
106+
.expect(200, function(){
107+
spy.called.should.be.true;
108+
done();
109+
});
105110
});
106111
});
107112

@@ -119,21 +124,24 @@ describe('ExpressOAuthServer', function() {
119124
return code;
120125
}
121126
};
122-
var oauth = new ExpressOAuthServer({ model: model });
127+
var oauth = new ExpressOAuthServer({ model: model, continueMiddleware: true });
123128

124129
app.use(oauth.authorize());
125130

126-
app.use(function(req, res, next) {
131+
var spy = sinon.spy(function(req, res, next) {
127132
res.locals.oauth.code.should.equal(code);
128-
129133
next();
130134
});
135+
app.use(spy);
131136

132137
request(app.listen())
133138
.post('/?state=foobiz')
134139
.set('Authorization', 'Bearer foobar')
135140
.send({ client_id: 12345, response_type: 'code' })
136-
.end(done);
141+
.expect(200, function(){
142+
spy.called.should.be.true;
143+
done();
144+
});
137145
});
138146

139147
it('should return a `location` header with the error', function(done) {
@@ -210,21 +218,24 @@ describe('ExpressOAuthServer', function() {
210218
return token;
211219
}
212220
};
213-
var oauth = new ExpressOAuthServer({ model: model });
221+
var oauth = new ExpressOAuthServer({ model: model, continueMiddleware: true });
214222

215223
app.use(oauth.token());
216-
217-
app.use(function(req, res, next) {
224+
var spy = sinon.spy(function(req, res, next) {
218225
res.locals.oauth.token.should.equal(token);
219226

220227
next();
221228
});
229+
app.use(spy);
222230

223231
request(app.listen())
224232
.post('/')
225233
.send('client_id=foo&client_secret=bar&grant_type=password&username=qux&password=biz')
226234
.expect({ access_token: 'foobar', token_type: 'Bearer' })
227-
.end(done);
235+
.expect(200, function(){
236+
spy.called.should.be.true;
237+
done();
238+
});
228239
});
229240

230241
it('should return an `access_token`', function(done) {
@@ -239,10 +250,10 @@ describe('ExpressOAuthServer', function() {
239250
return { accessToken: 'foobar', client: {}, user: {} };
240251
}
241252
};
242-
var oauth = new ExpressOAuthServer({ model: model });
253+
var spy = sinon.spy();
254+
var oauth = new ExpressOAuthServer({ model: model, continueMiddleware: true });
243255

244256
app.use(oauth.token());
245-
246257
request(app.listen())
247258
.post('/')
248259
.send('client_id=foo&client_secret=bar&grant_type=password&username=qux&password=biz')

test/unit/index_test.js

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,20 @@ describe('ExpressOAuthServer', function() {
6161
oauth.server.authenticate.firstCall.args[1].should.be.an.instanceOf(Response);
6262
oauth.server.authenticate.firstCall.args[2].should.eql({options: true});
6363
oauth.server.authenticate.restore();
64-
6564
done();
6665
});
6766
});
6867
});
6968

7069
describe('authorize()', function() {
71-
it('should call `authorize()`', function(done) {
70+
it('should call `authorize()` and end middleware execution', function(done) {
71+
var nextMiddleware = sinon.spy()
7272
var oauth = new ExpressOAuthServer({ model: {} });
7373

7474
sinon.stub(oauth.server, 'authorize').returns({});
7575

7676
app.use(oauth.authorize());
77+
app.use(nextMiddleware);
7778

7879
request(app.listen())
7980
.get('/')
@@ -84,7 +85,31 @@ describe('ExpressOAuthServer', function() {
8485
oauth.server.authorize.firstCall.args[1].should.be.an.instanceOf(Response);
8586
should.not.exist(oauth.server.authorize.firstCall.args[2]);
8687
oauth.server.authorize.restore();
88+
nextMiddleware.called.should.be.false();
89+
done();
90+
});
91+
});
92+
93+
it('should call `authorize()` and continue middleware chain', function(done) {
94+
var nextMiddleware = sinon.spy()
95+
var oauth = new ExpressOAuthServer({ model: {}, continueMiddleware: true });
8796

97+
sinon.stub(oauth.server, 'authorize').returns({});
98+
99+
app.use(oauth.authorize());
100+
app.use(nextMiddleware);
101+
102+
request(app.listen())
103+
.get('/')
104+
.end(function() {
105+
oauth.server.authorize.callCount.should.equal(1);
106+
oauth.server.authorize.firstCall.args.should.have.length(3);
107+
oauth.server.authorize.firstCall.args[0].should.be.an.instanceOf(Request);
108+
oauth.server.authorize.firstCall.args[1].should.be.an.instanceOf(Response);
109+
should.not.exist(oauth.server.authorize.firstCall.args[2]);
110+
oauth.server.authorize.restore();
111+
nextMiddleware.called.should.be.true();
112+
nextMiddleware.args[0].length.should.eql(3);
88113
done();
89114
});
90115
});
@@ -105,19 +130,20 @@ describe('ExpressOAuthServer', function() {
105130
oauth.server.authorize.firstCall.args[1].should.be.an.instanceOf(Response);
106131
oauth.server.authorize.firstCall.args[2].should.eql({options: true});
107132
oauth.server.authorize.restore();
108-
109133
done();
110134
});
111135
});
112136
});
113137

114138
describe('token()', function() {
115-
it('should call `token()`', function(done) {
139+
it('should call `token()` and end middleware chain', function(done) {
140+
var nextMiddleware = sinon.spy()
116141
var oauth = new ExpressOAuthServer({ model: {} });
117142

118143
sinon.stub(oauth.server, 'token').returns({});
119144

120145
app.use(oauth.token());
146+
app.use(nextMiddleware);
121147

122148
request(app.listen())
123149
.get('/')
@@ -128,7 +154,31 @@ describe('ExpressOAuthServer', function() {
128154
oauth.server.token.firstCall.args[1].should.be.an.instanceOf(Response);
129155
should.not.exist(oauth.server.token.firstCall.args[2]);
130156
oauth.server.token.restore();
157+
nextMiddleware.called.should.be.false();
158+
done();
159+
});
160+
});
131161

162+
it('should call `token()` and continue middleware chain', function(done) {
163+
var nextMiddleware = sinon.spy()
164+
var oauth = new ExpressOAuthServer({ model: {}, continueMiddleware: true });
165+
166+
sinon.stub(oauth.server, 'token').returns({});
167+
168+
app.use(oauth.token());
169+
app.use(nextMiddleware);
170+
171+
request(app.listen())
172+
.get('/')
173+
.end(function() {
174+
oauth.server.token.callCount.should.equal(1);
175+
oauth.server.token.firstCall.args.should.have.length(3);
176+
oauth.server.token.firstCall.args[0].should.be.an.instanceOf(Request);
177+
oauth.server.token.firstCall.args[1].should.be.an.instanceOf(Response);
178+
should.not.exist(oauth.server.token.firstCall.args[2]);
179+
oauth.server.token.restore();
180+
nextMiddleware.called.should.be.true();
181+
nextMiddleware.args[0].length.should.eql(3);
132182
done();
133183
});
134184
});
@@ -149,7 +199,6 @@ describe('ExpressOAuthServer', function() {
149199
oauth.server.token.firstCall.args[1].should.be.an.instanceOf(Response);
150200
oauth.server.token.firstCall.args[2].should.eql({options: true});
151201
oauth.server.token.restore();
152-
153202
done();
154203
});
155204
});

0 commit comments

Comments
 (0)