index.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /**
  2. * Koa unless middleware. Attach to any middleware and configure it to prevent/permit the
  3. * middleware in question to be executed.
  4. *
  5. * @module koa-unless
  6. */
  7. 'use strict';
  8. var url = require('url');
  9. /** Creates a wrapper middleware that verifies if the original middleware should be skipped. */
  10. module.exports = function (options) {
  11. var originalMiddleware = this;
  12. // If a custom function was passed directly, creates a new object literal that holds it as a property called custom.
  13. var opts = typeof options === 'function' ? { custom: options } : options;
  14. opts.useOriginalUrl = (typeof opts.useOriginalUrl === 'undefined') ? true : opts.useOriginalUrl;
  15. // Returns the middleware that wraps the original one.
  16. return function (ctx, next) {
  17. var requestedUrl = url.parse((opts.useOriginalUrl ? ctx.originalUrl : ctx.url) || '', true);
  18. // any match means 'skip original middleware'
  19. if (matchesCustom(ctx, opts) || matchesPath(requestedUrl, opts) ||
  20. matchesExtension(requestedUrl, opts) || matchesMethod(ctx.method, opts)) {
  21. return next();
  22. }
  23. return originalMiddleware(ctx, next);
  24. };
  25. };
  26. /**
  27. * Returns boolean indicating whether the custom function returns true.
  28. *
  29. * @param ctx - Koa context
  30. * @param opts - unless configuration
  31. * @returns {boolean}
  32. */
  33. function matchesCustom(ctx, opts) {
  34. if (opts.custom) {
  35. return opts.custom(ctx);
  36. }
  37. return false;
  38. }
  39. /**
  40. * Returns boolean indicating whether the requestUrl matches against the paths configured.
  41. *
  42. * @param requestedUrl - url requested by user
  43. * @param opts - unless configuration
  44. * @returns {boolean}
  45. */
  46. function matchesPath(requestedUrl, opts) {
  47. var paths = !opts.path || Array.isArray(opts.path) ?
  48. opts.path : [opts.path];
  49. if (paths) {
  50. return paths.some(function (p) {
  51. return (typeof p === 'string' && p === requestedUrl.pathname) ||
  52. (p instanceof RegExp && !!p.exec(requestedUrl.pathname));
  53. });
  54. }
  55. return false;
  56. }
  57. /**
  58. * Returns boolean indicating whether the requestUrl ends with the configured extensions.
  59. *
  60. * @param requestedUrl - url requested by user
  61. * @param opts - unless configuration
  62. * @returns {boolean}
  63. */
  64. function matchesExtension(requestedUrl, opts) {
  65. var exts = !opts.ext || Array.isArray(opts.ext) ?
  66. opts.ext : [opts.ext];
  67. if (exts) {
  68. return exts.some(function(ext) {
  69. return requestedUrl.pathname.substr(ext.length * -1) === ext;
  70. });
  71. }
  72. }
  73. /**
  74. * Returns boolean indicating whether the request method matches the configured methods.
  75. *
  76. * @param method - method used (GET, POST, ...)
  77. * @param opts - unless configuration
  78. * @returns {boolean}
  79. */
  80. function matchesMethod(method, opts) {
  81. var methods = !opts.method || Array.isArray(opts.method) ?
  82. opts.method : [opts.method];
  83. if (methods) {
  84. return !!~methods.indexOf(method);
  85. }
  86. }