Skip to content

Commit 5bada09

Browse files
authored
Let filter take a promise form. (#341)
1 parent 2ccbe82 commit 5bada09

File tree

4 files changed

+154
-15
lines changed

4 files changed

+154
-15
lines changed

app/steps/filterUserRequest.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
3+
// No-op version of filter. Allows everything!
4+
5+
function defaultFilter(proxyReqOptBuilder, userReq) { // eslint-disable-line
6+
return true;
7+
}
8+
9+
function filterUserRequest(container) {
10+
var resolverFn = container.options.filter || defaultFilter;
11+
12+
return Promise
13+
.resolve(resolverFn(container.proxy.reqBuilder, container.user.req))
14+
.then(function (shouldIContinue) {
15+
if (shouldIContinue) {
16+
return Promise.resolve(container);
17+
} else {
18+
return Promise.reject(); // reject with no args should simply call next()
19+
}
20+
});
21+
}
22+
23+
module.exports = filterUserRequest;
24+

index.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
// * Uses Promises to support async.
55
// * Uses a quasi-Global called Container to tidy up the argument passing between the major work-flow steps.
66

7-
87
var ScopeContainer = require('./lib/scopeContainer');
98
var assert = require('assert');
109
var debug = require('debug')('express-http-proxy');
@@ -15,7 +14,8 @@ var decorateProxyReqBody = require('./app/steps/decorateProxyReqBody');
1514
var decorateProxyReqOpts = require('./app/steps/decorateProxyReqOpts');
1615
var decorateUserRes = require('./app/steps/decorateUserRes');
1716
var decorateUserResHeaders = require('./app/steps/decorateUserResHeaders');
18-
var handleProxyErrors = require('./app/steps/handleProxyErrors');
17+
var filterUserRequest = require('./app/steps/filterUserRequest');
18+
var handleProxyErrors = require('./app/steps/handleProxyErrors');
1919
var maybeSkipToNextHandler = require('./app/steps/maybeSkipToNextHandler');
2020
var prepareProxyReq = require('./app/steps/prepareProxyReq');
2121
var resolveProxyHost = require('./app/steps/resolveProxyHost');
@@ -33,9 +33,10 @@ module.exports = function proxy(host, userOptions) {
3333
// Skip proxy if filter is falsey. Loose equality so filters can return
3434
// false, null, undefined, etc.
3535

36-
if (!container.options.filter(req, res)) { return next(); }
36+
//if (!container.options.filter(req, res)) { return next(); }
3737

38-
buildProxyReq(container)
38+
filterUserRequest(container)
39+
.then(buildProxyReq)
3940
.then(resolveProxyHost)
4041
.then(decorateProxyReqOpts)
4142
.then(resolveProxyReqPath)
@@ -48,10 +49,17 @@ module.exports = function proxy(host, userOptions) {
4849
.then(decorateUserRes)
4950
.then(sendUserRes)
5051
.catch(function (err) {
51-
var resolver = (container.options.proxyErrorHandler) ?
52-
container.options.proxyErrorHandler :
53-
handleProxyErrors;
54-
resolver(err, res, next);
52+
// I sometimes reject without an error to shortcircuit the remaining
53+
// steps and return control to the host application.
54+
55+
if (err) {
56+
var resolver = (container.options.proxyErrorHandler) ?
57+
container.options.proxyErrorHandler :
58+
handleProxyErrors;
59+
resolver(err, res, next);
60+
} else {
61+
next();
62+
}
5563
});
5664
};
5765
};

lib/resolveOptions.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ function resolveOptions(options) {
5050
userResDecorator: options.userResDecorator || options.intercept,
5151
userResHeaderDecorator: options.userResHeaderDecorator,
5252
proxyErrorHandler: options.proxyErrorHandler,
53-
filter: options.filter || defaultFilter,
53+
filter: options.filter,
5454
// For backwards compatability, we default to legacy behavior for newly added settings.
5555

5656
parseReqBody: isUnset(options.parseReqBody) ? true : options.parseReqBody,
@@ -76,10 +76,4 @@ function resolveOptions(options) {
7676
return resolved;
7777
}
7878

79-
function defaultFilter() {
80-
// No-op version of filter. Allows everything!
81-
82-
return true;
83-
}
84-
8579
module.exports = resolveOptions;

test/filter.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
'use strict';
2+
3+
var express = require('express');
4+
var request = require('supertest');
5+
var proxy = require('../');
6+
var proxyTarget = require('../test/support/proxyTarget');
7+
var proxyRouteFn = [{
8+
method: 'get',
9+
path: '/',
10+
fn: function (req, res) {
11+
return res.status(209).send('Proxy Server');
12+
}
13+
}];
14+
15+
function nextMethod(req, res, next) {
16+
res.status(201).send('Client Application');
17+
next();
18+
}
19+
20+
describe('filter', function () {
21+
var app = express();
22+
var proxyServer;
23+
24+
beforeEach(function () {
25+
proxyServer = proxyTarget(12346, 100, proxyRouteFn);
26+
app = express();
27+
});
28+
29+
afterEach(function () {
30+
proxyServer.close();
31+
});
32+
33+
describe('when filter function returns true', function () {
34+
it('continues route processing', function (done) {
35+
// should capture every possible path
36+
37+
app.use(proxy('localhost:12346', {
38+
filter: function () { return true; }
39+
}));
40+
41+
// because prior line should *always* fire and return, we should never get here.
42+
43+
app.use(nextMethod);
44+
45+
request(app)
46+
.get('/')
47+
.expect(209)
48+
.end(done);
49+
});
50+
});
51+
52+
describe('when filter function returns false', function () {
53+
54+
it('hanldes route processing', function (done) {
55+
// should capture every possible path
56+
57+
app.use(proxy('localhost:12346', {
58+
filter: function () { return false; }
59+
}));
60+
61+
// because prior line should *always* fire skip, we should get here.
62+
63+
app.use(nextMethod);
64+
65+
request(app)
66+
.get('/')
67+
.expect(201)
68+
.end(done);
69+
});
70+
});
71+
72+
describe('promise form', function () {
73+
describe('when filter function returns true', function () {
74+
it('continues route processing', function (done) {
75+
// should capture every possible path
76+
77+
app.use(proxy('localhost:12346', {
78+
filter: function () { return new Promise(function (resolve) { resolve(true); }); }
79+
}));
80+
81+
// because prior line should *always* fire and return, we should never get here.
82+
83+
app.use(nextMethod);
84+
85+
request(app)
86+
.get('/')
87+
.expect(209)
88+
.end(done);
89+
});
90+
});
91+
92+
describe('when filter function returns false', function () {
93+
94+
it('hanldes route processing', function (done) {
95+
// should capture every possible path
96+
97+
app.use(proxy('localhost:12346', {
98+
filter: function () { return new Promise(function (resolve) { resolve(false); }); }
99+
}));
100+
101+
// because prior line should *always* fire skip, we should get here.
102+
103+
app.use(nextMethod);
104+
105+
request(app)
106+
.get('/')
107+
.expect(201)
108+
.end(done);
109+
});
110+
});
111+
});
112+
113+
});

0 commit comments

Comments
 (0)