The sample project generated with the cli will make use of middleware bundled with the stack. You will see where the handler uses them, injects them. You can also write your own and bundle them in too.
Middleware, extended from base middleware is ran in order, first to last in... then the controller is ran, then first to last out. You can inject in as an array or individually using the auto or specific methods.
The following bundled middleware classes already exist in cerberus-mvc...
A great way to get cors working right away, utlises the client global proeprty to find the client origin for return.
Use as the last middleware in the chain, ensures your knex service dsiconnects from the database after any responses, so you dont have to do it on each query/model method.
Middleware needs injecting into the appplication instance form the handler. You can use the following methods to do this in teh handler.
Middleware can be passed in as a large array or teh commands can be called over and over adding middleware to the stack.
'use strict';
const Application = require('cerberus-mvc/System/Application');
const CorsMiddleware = require('cerberus-mvc/Middleware/Cors');
const KnexMiddleware = require('cerberus-mvc/Middleware/Knex');
const KnexService = require('cerberus-mvc/Service/Knex');
exports.run = (event, context, callback) => {
const app = new Application('aws');
const corsMiddleware = new CorsMiddleware();
const knexMiddleware = new KnexMiddleware();
const yourDBKnexService = new KnexService('postgres', '192.168.1.10', 5432, 'your_db', 'your_user', 'your_password');
app.service(yourDBKnexService);
app.middleware(corsMiddleware);
app.middleware(knexMiddleware);
app.run(event).then((response) => callback(null, response))
};
Middleware in will take in a request and should pass back out a request/modified request either directly or as a promise chain that returns it. Example below of authentication middleware, calling an authorization service (not bundled)
'use strict';
const Middleware = require('cerberus-mvc/Base/Middleware');
const RestError = require('cerberus-mvc/Error/Rest');
/**
* @namespace API/Middleware
* @class Auth
* @extends Middleware
* @description Middleware class providing authentication actions in all incomming requests
* @author Paul Smith (ulsmith)
* @copyright 2020 Paul Smith (ulsmith) all rights reserved
* @license MIT
*/
class Auth extends Middleware {
/**
* @public @method constructor
* @description Base method when instantiating class
*/
constructor() {
super();
}
/**
* @public @method in
* @description Invoke middleware for incomming event
* @param {Object} request The incoming request
*/
in(request) {
// is this an internal message from aws?
if (request.source === 'event') {
// incoming only
if (this.$client.origin) throw new RestError('Origin cannot be set on message, access denied', 401);
// public access, do not authorize
if (request.access !== request.context.service) throw new RestError('No access to this function for [' + request.context.service + '], access denied', 401);
return request;
}
// API GATEWAY API REQUEST
// incoming only
if (!this.$client.origin) throw new RestError('Origin is not set, access denied', 401);
// origin failed to auth to white list
if (this.$environment.API_CORS_LIST.replace(' ', '').split(',').indexOf(this.$client.origin) < 0) throw new RestError('Origin [' + this.$client.origin + '] is not allowed, access denied', 401);
// public access, do not authorize, gets from controllers getter that matches method
if (request.access === 'public') return request;
// missing token
if (!request.headers.Authorization) throw new RestError('Missing Authorization Token, invalid', 401);
// get token bits
if (request.headers.Authorization.split(' ')[0].toLowerCase() !== 'bearer') throw new RestError('Malformed Token due to missing "Bearer", invalid', 401);
// verify against auth service, throws restError on failure
return this.$services.auth.verify(request.headers.Authorization, request.headers['User-Agent']).then(() => request);
}
}
module.exports = Auth;
Middleware out will pass in a response and should pass back out the response/modified response eithe rdirectly or as a promise chain returning it. Example below of cors middleware (bundled)
'use strict';
const Middleware = require('cerberus-mvc/Base/Middleware');
/**
* @namespace MVC/Middleware
* @class Cors
* @extends Middleware
* @description Middleware class providing cors patching to outgoing response
* @author Paul Smith (ulsmith)
* @copyright 2020 Paul Smith (ulsmith) all rights reserved
* @license MIT
*/
class Cors extends Middleware {
/**
* @public @method constructor
* @description Base method when instantiating class
*/
constructor() {
super();
}
/**
* @public @method out
* @description Invoke middleware for outgoing response
* @param {Object} response The outgoing response to API Gateway
* @param {Object} context The lambda context
*/
out(response) {
// update headers on way back out, for all requests that are not options (handled by API gateway directly)
response.headers['Access-Control-Allow-Origin'] = this.$client.origin;
response.headers['Access-Control-Allow-Credentials'] = 'true';
response.headers['Access-Control-Allow-Headers'] = 'Accept, Cache-Control, Content-Type, Content-Length, Authorization, Pragma, Expires';
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS, PATCH';
response.headers['Access-Control-Expose-Headers'] = 'Cache-Control, Content-Type, Authorization, Pragma, Expires';
return response;
}
}
module.exports = Cors;