| var _ = require('lodash') |
| var url = require('url') |
| var isGlob = require('is-glob') |
| var micromatch = require('micromatch') |
| var ERRORS = require('./errors') |
| |
| module.exports = { |
| match: matchContext |
| } |
| |
| function matchContext(context, uri, req) { |
| // single path |
| if (isStringPath(context)) { |
| return matchSingleStringPath(context, uri) |
| } |
| |
| // single glob path |
| if (isGlobPath(context)) { |
| return matchSingleGlobPath(context, uri) |
| } |
| |
| // multi path |
| if (Array.isArray(context)) { |
| if (context.every(isStringPath)) { |
| return matchMultiPath(context, uri) |
| } |
| if (context.every(isGlobPath)) { |
| return matchMultiGlobPath(context, uri) |
| } |
| |
| throw new Error(ERRORS.ERR_CONTEXT_MATCHER_INVALID_ARRAY) |
| } |
| |
| // custom matching |
| if (_.isFunction(context)) { |
| var pathname = getUrlPathName(uri) |
| return context(pathname, req) |
| } |
| |
| throw new Error(ERRORS.ERR_CONTEXT_MATCHER_GENERIC) |
| } |
| |
| /** |
| * @param {String} context '/api' |
| * @param {String} uri 'http://example.org/api/b/c/d.html' |
| * @return {Boolean} |
| */ |
| function matchSingleStringPath(context, uri) { |
| var pathname = getUrlPathName(uri) |
| return pathname.indexOf(context) === 0 |
| } |
| |
| function matchSingleGlobPath(pattern, uri) { |
| var pathname = getUrlPathName(uri) |
| var matches = micromatch(pathname, pattern) |
| return matches && matches.length > 0 |
| } |
| |
| function matchMultiGlobPath(patternList, uri) { |
| return matchSingleGlobPath(patternList, uri) |
| } |
| |
| /** |
| * @param {String} contextList ['/api', '/ajax'] |
| * @param {String} uri 'http://example.org/api/b/c/d.html' |
| * @return {Boolean} |
| */ |
| function matchMultiPath(contextList, uri) { |
| for (var i = 0; i < contextList.length; i++) { |
| var context = contextList[i] |
| if (matchSingleStringPath(context, uri)) { |
| return true |
| } |
| } |
| return false |
| } |
| |
| /** |
| * Parses URI and returns RFC 3986 path |
| * |
| * @param {String} uri from req.url |
| * @return {String} RFC 3986 path |
| */ |
| function getUrlPathName(uri) { |
| return uri && url.parse(uri).pathname |
| } |
| |
| function isStringPath(context) { |
| return _.isString(context) && !isGlob(context) |
| } |
| |
| function isGlobPath(context) { |
| return isGlob(context) |
| } |