Merge pull request #133 from strongloop/feature/app-install-middleware
Implement app.installMiddleware
This commit is contained in:
commit
57813cef56
|
@ -439,6 +439,131 @@ function tryReadConfig(cwd, fileName) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install all express middleware required by LoopBack.
|
||||
*
|
||||
* It is possible to inject your own middleware by listening on one of the
|
||||
* following events:
|
||||
*
|
||||
* - `middleware:preprocessors` is emitted after all other
|
||||
* request-preprocessing middleware was installed, but before any
|
||||
* request-handling middleware is configured.
|
||||
*
|
||||
* Usage:
|
||||
* ```js
|
||||
* app.on('middleware:preprocessors', function() {
|
||||
* app.use(loopback.limit('5.5mb'))
|
||||
* });
|
||||
* ```
|
||||
* - `middleware:handlers` is emitted when it's time to add your custom
|
||||
* request-handling middleware. Note that you should not install any
|
||||
* express routes at this point (express routes are discussed later).
|
||||
*
|
||||
* Usage:
|
||||
* ```js
|
||||
* app.on('middleware:handlers', function() {
|
||||
* app.use('/admin', adminExpressApp);
|
||||
* app.use('/custom', function(req, res, next) {
|
||||
* res.send(200, { url: req.url });
|
||||
* });
|
||||
* });
|
||||
* ```
|
||||
* - `middleware:error-loggers` is emitted at the end, before the loopback
|
||||
* error handling middleware is installed. This is the point where you
|
||||
* can install your own middleware to log errors.
|
||||
*
|
||||
* Notes:
|
||||
* - The middleware function must take four parameters, otherwise it won't
|
||||
* be called by express.
|
||||
*
|
||||
* - It should also call `next(err)` to let the loopback error handler convert
|
||||
* the error to an HTTP error response.
|
||||
*
|
||||
* Usage:
|
||||
* ```js
|
||||
* var bunyan = require('bunyan');
|
||||
* var log = bunyan.createLogger({name: "myapp"});
|
||||
* app.on('middleware:error-loggers', function() {
|
||||
* app.use(function(err, req, res, next) {
|
||||
* log.error(err);
|
||||
* next(err);
|
||||
* });
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Express routes should be added after `installMiddleware` was called.
|
||||
* This way the express router middleware is injected at the right place in the
|
||||
* middleware chain. If you add an express route before calling this function,
|
||||
* bad things will happen: Express will automatically add the router
|
||||
* middleware and since we haven't added request-preprocessing middleware like
|
||||
* cookie & body parser yet, your route handlers will receive raw unprocessed
|
||||
* requests.
|
||||
*
|
||||
* This is the correct order in which to call `app` methods:
|
||||
* ```js
|
||||
* app.boot(__dirname); // optional
|
||||
*
|
||||
* app.installMiddleware();
|
||||
*
|
||||
* // [register your express routes here]
|
||||
*
|
||||
* app.listen();
|
||||
* ```
|
||||
*/
|
||||
app.installMiddleware = function() {
|
||||
var loopback = require('../');
|
||||
|
||||
/*
|
||||
* Request pre-processing
|
||||
*/
|
||||
this.use(loopback.favicon());
|
||||
// TODO(bajtos) refactor to app.get('loggerFormat')
|
||||
var loggerFormat = this.get('env') === 'development' ? 'dev' : 'default';
|
||||
this.use(loopback.logger(loggerFormat));
|
||||
this.use(loopback.cookieParser(this.get('cookieSecret')));
|
||||
this.use(loopback.token({ model: this.models.accessToken }));
|
||||
this.use(loopback.bodyParser());
|
||||
this.use(loopback.methodOverride());
|
||||
|
||||
// Allow the app to install custom preprocessing middleware
|
||||
this.emit('middleware:preprocessors');
|
||||
|
||||
/*
|
||||
* Request handling
|
||||
*/
|
||||
|
||||
// LoopBack REST transport
|
||||
this.use(this.get('restApiRoot') || '/api', loopback.rest());
|
||||
|
||||
// Allow the app to install custom request handling middleware
|
||||
this.emit('middleware:handlers');
|
||||
|
||||
// Let express routes handle requests that were not handled
|
||||
// by any of the middleware registered above.
|
||||
// This way LoopBack REST and API Explorer take precedence over
|
||||
// express routes.
|
||||
this.use(this.router);
|
||||
|
||||
// The static file server should come after all other routes
|
||||
// Every request that goes through the static middleware hits
|
||||
// the file system to check if a file exists.
|
||||
this.use(loopback.static(path.join(__dirname, 'public')));
|
||||
|
||||
// Requests that get this far won't be handled
|
||||
// by any middleware. Convert them into a 404 error
|
||||
// that will be handled later down the chain.
|
||||
this.use(loopback.urlNotFound());
|
||||
|
||||
/*
|
||||
* Error handling
|
||||
*/
|
||||
|
||||
// Allow the app to install custom error logging middleware
|
||||
this.emit('middleware:error-handlers');
|
||||
|
||||
// The ultimate error handler.
|
||||
this.use(loopback.errorHandler());
|
||||
};
|
||||
|
||||
/**
|
||||
* Listen for connections and update the configured port.
|
||||
|
|
|
@ -197,6 +197,102 @@ describe('app', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe('installMiddleware()', function() {
|
||||
var app;
|
||||
beforeEach(function() { app = loopback(); });
|
||||
|
||||
it('installs loopback.token', function(done) {
|
||||
app.models.accessToken = loopback.AccessToken;
|
||||
|
||||
app.installMiddleware();
|
||||
|
||||
app.get('/', function(req, res) {
|
||||
res.send({ accessTokenId: req.accessToken && req.accessToken.id });
|
||||
});
|
||||
|
||||
app.models.accessToken.create({}, function(err, token) {
|
||||
if (err) done(err);
|
||||
request(app).get('/')
|
||||
.set('Authorization', token.id)
|
||||
.expect(200, { accessTokenId: token.id })
|
||||
.end(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('emits "middleware:preprocessors" before handlers are installed',
|
||||
function(done) {
|
||||
app.on('middleware:preprocessors', function() {
|
||||
this.use(function(req, res, next) {
|
||||
req.preprocessed = true;
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
app.installMiddleware();
|
||||
|
||||
app.get('/', function(req, res) {
|
||||
res.send({ preprocessed: req.preprocessed });
|
||||
});
|
||||
|
||||
request(app).get('/')
|
||||
.expect(200, { preprocessed: true})
|
||||
.end(done);
|
||||
}
|
||||
);
|
||||
|
||||
it('emits "middleware:handlers before installing express router',
|
||||
function(done) {
|
||||
app.on('middleware:handlers', function() {
|
||||
this.use(function(req, res, next) {
|
||||
res.send({ handler: 'middleware' });
|
||||
});
|
||||
});
|
||||
|
||||
app.installMiddleware();
|
||||
|
||||
app.get('/', function(req, res) {
|
||||
res.send({ handler: 'router' });
|
||||
});
|
||||
|
||||
request(app).get('/')
|
||||
.expect(200, { handler: 'middleware' })
|
||||
.end(done);
|
||||
}
|
||||
);
|
||||
|
||||
it('emits "middleware:error-handlers" after all request handlers',
|
||||
function(done) {
|
||||
var logs = [];
|
||||
app.on('middleware:error-handlers', function() {
|
||||
app.use(function(err, req, res, next) {
|
||||
logs.push(req.url);
|
||||
next(err);
|
||||
});
|
||||
});
|
||||
|
||||
app.installMiddleware();
|
||||
|
||||
request(app).get('/not-found')
|
||||
.expect(404)
|
||||
.end(function(err, res) {
|
||||
if (err) done(err);
|
||||
expect(logs).to.eql(['/not-found']);
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it('installs REST transport', function(done) {
|
||||
app.model(loopback.Application);
|
||||
app.set('restApiRoot', '/api');
|
||||
app.installMiddleware();
|
||||
|
||||
request(app).get('/api/applications')
|
||||
.expect(200, [])
|
||||
.end(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('listen()', function() {
|
||||
it('starts http server', function(done) {
|
||||
var app = loopback();
|
||||
|
|
Loading…
Reference in New Issue