/**
|
* Koa unless middleware. Attach to any middleware and configure it to prevent/permit the
|
* middleware in question to be executed.
|
*
|
* @module koa-unless
|
*/
|
|
'use strict';
|
var url = require('url');
|
|
/** Creates a wrapper middleware that verifies if the original middleware should be skipped. */
|
module.exports = function (options) {
|
var originalMiddleware = this;
|
|
// If a custom function was passed directly, creates a new object literal that holds it as a property called custom.
|
var opts = typeof options === 'function' ? { custom: options } : options;
|
opts.useOriginalUrl = (typeof opts.useOriginalUrl === 'undefined') ? true : opts.useOriginalUrl;
|
|
// Returns the middleware that wraps the original one.
|
return function (ctx, next) {
|
var requestedUrl = url.parse((opts.useOriginalUrl ? ctx.originalUrl : ctx.url) || '', true);
|
|
// any match means 'skip original middleware'
|
if (matchesCustom(ctx, opts) || matchesPath(requestedUrl, opts) ||
|
matchesExtension(requestedUrl, opts) || matchesMethod(ctx.method, opts)) {
|
return next();
|
}
|
|
return originalMiddleware(ctx, next);
|
};
|
};
|
|
/**
|
* Returns boolean indicating whether the custom function returns true.
|
*
|
* @param ctx - Koa context
|
* @param opts - unless configuration
|
* @returns {boolean}
|
*/
|
function matchesCustom(ctx, opts) {
|
if (opts.custom) {
|
return opts.custom(ctx);
|
}
|
return false;
|
}
|
|
/**
|
* Returns boolean indicating whether the requestUrl matches against the paths configured.
|
*
|
* @param requestedUrl - url requested by user
|
* @param opts - unless configuration
|
* @returns {boolean}
|
*/
|
function matchesPath(requestedUrl, opts) {
|
var paths = !opts.path || Array.isArray(opts.path) ?
|
opts.path : [opts.path];
|
|
if (paths) {
|
return paths.some(function (p) {
|
return (typeof p === 'string' && p === requestedUrl.pathname) ||
|
(p instanceof RegExp && !!p.exec(requestedUrl.pathname));
|
});
|
}
|
|
return false;
|
}
|
|
/**
|
* Returns boolean indicating whether the requestUrl ends with the configured extensions.
|
*
|
* @param requestedUrl - url requested by user
|
* @param opts - unless configuration
|
* @returns {boolean}
|
*/
|
function matchesExtension(requestedUrl, opts) {
|
var exts = !opts.ext || Array.isArray(opts.ext) ?
|
opts.ext : [opts.ext];
|
|
if (exts) {
|
return exts.some(function(ext) {
|
return requestedUrl.pathname.substr(ext.length * -1) === ext;
|
});
|
}
|
}
|
|
/**
|
* Returns boolean indicating whether the request method matches the configured methods.
|
*
|
* @param method - method used (GET, POST, ...)
|
* @param opts - unless configuration
|
* @returns {boolean}
|
*/
|
function matchesMethod(method, opts) {
|
var methods = !opts.method || Array.isArray(opts.method) ?
|
opts.method : [opts.method];
|
|
if (methods) {
|
return !!~methods.indexOf(method);
|
}
|
}
|