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) }