You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.1 KiB

4 years ago
  1. var _ = require('lodash')
  2. var url = require('url')
  3. var isGlob = require('is-glob')
  4. var micromatch = require('micromatch')
  5. var ERRORS = require('./errors')
  6. module.exports = {
  7. match: matchContext
  8. }
  9. function matchContext(context, uri, req) {
  10. // single path
  11. if (isStringPath(context)) {
  12. return matchSingleStringPath(context, uri)
  13. }
  14. // single glob path
  15. if (isGlobPath(context)) {
  16. return matchSingleGlobPath(context, uri)
  17. }
  18. // multi path
  19. if (Array.isArray(context)) {
  20. if (context.every(isStringPath)) {
  21. return matchMultiPath(context, uri)
  22. }
  23. if (context.every(isGlobPath)) {
  24. return matchMultiGlobPath(context, uri)
  25. }
  26. throw new Error(ERRORS.ERR_CONTEXT_MATCHER_INVALID_ARRAY)
  27. }
  28. // custom matching
  29. if (_.isFunction(context)) {
  30. var pathname = getUrlPathName(uri)
  31. return context(pathname, req)
  32. }
  33. throw new Error(ERRORS.ERR_CONTEXT_MATCHER_GENERIC)
  34. }
  35. /**
  36. * @param {String} context '/api'
  37. * @param {String} uri 'http://example.org/api/b/c/d.html'
  38. * @return {Boolean}
  39. */
  40. function matchSingleStringPath(context, uri) {
  41. var pathname = getUrlPathName(uri)
  42. return pathname.indexOf(context) === 0
  43. }
  44. function matchSingleGlobPath(pattern, uri) {
  45. var pathname = getUrlPathName(uri)
  46. var matches = micromatch(pathname, pattern)
  47. return matches && matches.length > 0
  48. }
  49. function matchMultiGlobPath(patternList, uri) {
  50. return matchSingleGlobPath(patternList, uri)
  51. }
  52. /**
  53. * @param {String} contextList ['/api', '/ajax']
  54. * @param {String} uri 'http://example.org/api/b/c/d.html'
  55. * @return {Boolean}
  56. */
  57. function matchMultiPath(contextList, uri) {
  58. for (var i = 0; i < contextList.length; i++) {
  59. var context = contextList[i]
  60. if (matchSingleStringPath(context, uri)) {
  61. return true
  62. }
  63. }
  64. return false
  65. }
  66. /**
  67. * Parses URI and returns RFC 3986 path
  68. *
  69. * @param {String} uri from req.url
  70. * @return {String} RFC 3986 path
  71. */
  72. function getUrlPathName(uri) {
  73. return uri && url.parse(uri).pathname
  74. }
  75. function isStringPath(context) {
  76. return _.isString(context) && !isGlob(context)
  77. }
  78. function isGlobPath(context) {
  79. return isGlob(context)
  80. }