adonis-framework
Version:
Adonis framework makes it easy for you to write webapps with less code
251 lines (234 loc) • 5.69 kB
JavaScript
/**
* adonis-framework
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
const _ = require('lodash')
const Ioc = require('adonis-fold').Ioc
const CE = require('../Exceptions')
let globalMiddleware = []
let namedMiddleware = {}
/**
* composes a closure to an object for consistent behaviour
*
* @method _composeFunction
*
* @param {Function} middleware
*
* @return {Object}
*
* @private
*/
const _composeFunction = function (middleware) {
return {instance: null, method: middleware, parameters: []}
}
/**
* composes a consistent object from the actual
* middleware object
*
* @method _composeObject
*
* @param {Object} middleware
*
* @return {Object}
*
* @private
*/
const _composeObject = function (middleware) {
const instance = middleware.instance || null
const method = instance ? instance[middleware.method] : middleware.method
return {instance, method, parameters: middleware.parameters}
}
/**
* Http middleware layer to register and resolve middleware
* for a given HTTP request.
* @module Middleware
*/
let Middleware = exports = module.exports = {}
/**
* clears off all global and named middleware
*
* @method new
*
* @public
*/
Middleware.new = function () {
globalMiddleware = []
namedMiddleware = {}
}
/**
* registers a new global or named middleware. If second
* parameter is empty, middleware will be considered
* global.
*
* @method register
*
* @param {String} [key] - unqiue key for named middleware
* @param {String} namespace - Reference to the binding of Ioc container
*
* @example
* Middleware.register('App/Http/Middleware/Auth')
* Middleware.register('app', 'App/Http/Middleware/Auth')
*
* @public
*/
Middleware.register = function (key, namespace) {
if (!namespace) {
globalMiddleware.push(key)
return
}
namedMiddleware[key] = namespace
}
/**
* concats a array of middleware inside global list.
*
* @method global
*
* @param {Array} arrayOfMiddleware
*
* @example
* Middleware.global(['App/Http/Middleware/Auth', '...'])
*
* @public
*/
Middleware.global = function (arrayOfMiddleware) {
globalMiddleware = globalMiddleware.concat(_.uniq(arrayOfMiddleware))
}
/**
* adds an object of middleware to named list.
*
* @method named
*
* @param {Object} namedMiddleware
*
* @example
* Middleware.named({'auth': 'App/Http/Middleware/Auth'}, {...})
*
* @public
*/
Middleware.named = function (namedMiddleware) {
_.each(namedMiddleware, (namespace, key) => Middleware.register(key, namespace))
}
/**
* returns list of global middleware
*
* @method getGlobal
*
* @return {Array}
*
* @public
*/
Middleware.getGlobal = function () {
return globalMiddleware
}
/**
* returns list of named middleware
*
* @method getNamed
*
* @return {Object}
*
* @public
*/
Middleware.getNamed = function () {
return namedMiddleware
}
/**
* fetch params defined next to named middleware while
* consuming them.
*
* @method fetchParams
*
* @param {String|Undefined} params
* @return {Array}
*
* @public
*/
Middleware.fetchParams = function (params) {
return params ? params.split(',') : []
}
/**
* returning an object of named middleware by
* parsing them.
*
* @method formatNamedMiddleware
*
* @param {Array} keys
* @return {Object}
*
* @example
* Middleware.formatNamedMiddleware(['auth:basic,jwt'])
* returns
* {'Adonis/Middleware/Auth': ['basic', 'jwt']}
*
* @throws {RunTimeException} If named middleware for a given
* key is not registered.
* @public
*/
Middleware.formatNamedMiddleware = function (keys) {
return _.reduce(keys, (structured, key) => {
const tokens = key.split(':')
const middlewareNamespace = namedMiddleware[tokens[0]]
if (!middlewareNamespace) {
throw CE.RuntimeException.missingNamedMiddleware(tokens[0])
}
structured[middlewareNamespace] = Middleware.fetchParams(tokens[1])
return structured
}, {})
}
/**
* resolves an array of middleware namespaces from
* ioc container
*
* @method resolve
*
* @param {Object} namedMiddlewareHash
* @param {Boolean} [includeGlobal=false]
*
* @return {Array}
*
* @example
* Middleware.resolve({}, true) // all global
* Middleware.resolve(Middleware.formatNamedMiddleware(['auth:basic', 'acl:user']))
*
* @public
*/
Middleware.resolve = function (namedMiddlewareHash, includeGlobal) {
const finalSet = includeGlobal ? Middleware.getGlobal().concat(_.keys(namedMiddlewareHash)) : _.keys(namedMiddlewareHash)
return _.map(finalSet, (item) => {
const func = Ioc.makeFunc(`${item}.handle`)
func.parameters = namedMiddlewareHash[item] || []
return func
})
}
/**
* composes middleware and calls them in sequence something similar
* to koa-compose.
*
* @method compose
*
* @param {Array} Middleware - Array of middleware resolved from Ioc container
* @param {Object} request - Http request object
* @param {Object} response - Http response object
*
* @public
*/
Middleware.compose = function (middlewareList, request, response) {
function * noop () {}
return function * (next) {
next = next || noop()
_(middlewareList)
.map((middleware) => {
return typeof (middleware) === 'function' ? _composeFunction(middleware) : _composeObject(middleware)
})
.forEachRight((middleware) => {
const values = [request, response, next].concat(middleware.parameters)
next = middleware.method.apply(middleware.instance, values)
})
return yield * next
}
}