Merge pull request #787 from strongloop/feature/app-middleware-v2
Implement app.middlewareFromConfig
This commit is contained in:
commit
beb55ee9f4
|
@ -1,3 +1,4 @@
|
|||
var assert = require('assert');
|
||||
var express = require('express');
|
||||
var merge = require('util')._extend;
|
||||
var PhaseList = require('loopback-phase').PhaseList;
|
||||
|
@ -12,6 +13,47 @@ module.exports = function loopbackExpress() {
|
|||
return app;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register a middleware using a factory function and a JSON config.
|
||||
*
|
||||
* **Example**
|
||||
*
|
||||
* ```js
|
||||
* app.middlewareFromConfig(compression, {
|
||||
* enabled: true,
|
||||
* phase: 'initial',
|
||||
* config: {
|
||||
* threshold: 128
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param {function} factory The factory function creating a middleware handler.
|
||||
* Typically a result of `require()` call, e.g. `require('compression')`.
|
||||
* @param {Array|*} config The configuration. Either an array of arguments
|
||||
* to pass to the factory function, or the value of the first argument
|
||||
* when the factory expects a single argument only.
|
||||
*/
|
||||
proto.middlewareFromConfig = function(factory, config) {
|
||||
assert(typeof factory === 'function', '"factory" must be a function');
|
||||
assert(typeof config === 'object', '"config" must be an object');
|
||||
assert(typeof config.phase === 'string' && config.phase,
|
||||
'"config.phase" must be a non-empty string');
|
||||
|
||||
if (config.enabled === false)
|
||||
return;
|
||||
|
||||
var args = config.config;
|
||||
if (args === undefined) {
|
||||
args = [];
|
||||
} else if (!Array.isArray(args)) {
|
||||
args = [args];
|
||||
}
|
||||
|
||||
var handler = factory.apply(null, args);
|
||||
this.middleware(config.phase, handler);
|
||||
};
|
||||
|
||||
/**
|
||||
* Register a middleware handler to be executed in a given phase.
|
||||
* @param {string} name The phase name, e.g. "init" or "routes".
|
||||
|
@ -23,6 +65,9 @@ module.exports = function loopbackExpress() {
|
|||
proto.middleware = function(name, handler) {
|
||||
this.lazyrouter();
|
||||
|
||||
assert(typeof name === 'string' && name, '"name" must be a non-empty string');
|
||||
assert(typeof handler === 'function', '"handler" must be a function');
|
||||
|
||||
var fullName = name;
|
||||
var handlerName = handler.name || '(anonymous)';
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
var path = require('path');
|
||||
|
||||
var http = require('http');
|
||||
var loopback = require('../');
|
||||
var PersistedModel = loopback.PersistedModel;
|
||||
|
@ -27,7 +28,7 @@ describe('app', function() {
|
|||
});
|
||||
app.use(namedHandler('main'));
|
||||
|
||||
executeHandlers(function(err) {
|
||||
executeMiddlewareHandlers(app, function(err) {
|
||||
if (err) return done(err);
|
||||
expect(steps).to.eql([
|
||||
'initial', 'session', 'auth', 'parse',
|
||||
|
@ -42,7 +43,7 @@ describe('app', function() {
|
|||
app.middleware('routes:after', namedHandler('routes:after'));
|
||||
app.use(namedHandler('main'));
|
||||
|
||||
executeHandlers(function(err) {
|
||||
executeMiddlewareHandlers(app, function(err) {
|
||||
if (err) return done(err);
|
||||
expect(steps).to.eql(['routes:before', 'main', 'routes:after']);
|
||||
done();
|
||||
|
@ -64,7 +65,7 @@ describe('app', function() {
|
|||
next();
|
||||
});
|
||||
|
||||
executeHandlers(function(err) {
|
||||
executeMiddlewareHandlers(app, function(err) {
|
||||
if (err) return done(err);
|
||||
expect(steps).to.eql(['initial', 'error']);
|
||||
done();
|
||||
|
@ -78,7 +79,7 @@ describe('app', function() {
|
|||
next(expectedError);
|
||||
});
|
||||
|
||||
executeHandlers(function(err) {
|
||||
executeMiddlewareHandlers(app, function(err) {
|
||||
expect(err).to.equal(expectedError);
|
||||
done();
|
||||
});
|
||||
|
@ -90,18 +91,59 @@ describe('app', function() {
|
|||
next();
|
||||
};
|
||||
}
|
||||
|
||||
function executeHandlers(callback) {
|
||||
var server = http.createServer(function(req, res) {
|
||||
app.handle(req, res, callback);
|
||||
});
|
||||
|
||||
request(server)
|
||||
.get('/test/url')
|
||||
.end(function(err) {
|
||||
if (err) return callback(err);
|
||||
describe.onServer('.middlewareFromConfig', function() {
|
||||
it('provides API for loading middleware from JSON config', function(done) {
|
||||
var steps = [];
|
||||
var expectedConfig = { key: 'value' };
|
||||
|
||||
var handlerFactory = function() {
|
||||
var args = Array.prototype.slice.apply(arguments);
|
||||
return function(req, res, next) {
|
||||
steps.push(args);
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
||||
// Config as an object (single arg)
|
||||
app.middlewareFromConfig(handlerFactory, {
|
||||
enabled: true,
|
||||
phase: 'session',
|
||||
config: expectedConfig
|
||||
});
|
||||
|
||||
// Config as a value (single arg)
|
||||
app.middlewareFromConfig(handlerFactory, {
|
||||
enabled: true,
|
||||
phase: 'session:before',
|
||||
config: 'before'
|
||||
});
|
||||
|
||||
// Config as a list of args
|
||||
app.middlewareFromConfig(handlerFactory, {
|
||||
enabled: true,
|
||||
phase: 'session:after',
|
||||
config: ['after', 2]
|
||||
});
|
||||
|
||||
// Disabled by configuration
|
||||
app.middlewareFromConfig(handlerFactory, {
|
||||
enabled: false,
|
||||
phase: 'initial',
|
||||
config: null
|
||||
});
|
||||
|
||||
executeMiddlewareHandlers(app, function(err) {
|
||||
if (err) return done(err);
|
||||
expect(steps).to.eql([
|
||||
['before'],
|
||||
[expectedConfig],
|
||||
['after', 2]
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('app.model(Model)', function() {
|
||||
|
@ -470,3 +512,15 @@ describe('app', function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
function executeMiddlewareHandlers(app, callback) {
|
||||
var server = http.createServer(function(req, res) {
|
||||
app.handle(req, res, callback);
|
||||
});
|
||||
|
||||
request(server)
|
||||
.get('/test/url')
|
||||
.end(function(err) {
|
||||
if (err) return callback(err);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue