constructors/request/params-parser.js

/**
 * @function ParamsParser
 * @memberof RequestModule
 * @param {string} value
 * @param {string} pattern
 * @param {object} [opts]
 * @param {object} [opts.cache] object where reg expressions will be cached
 * @param {function} [opts.mapper] function that will decode value, default is decodeURIComponent
 * @param {string} [opts.boud="\x02\x00\x00\x03"] function that will decode value, default is decodeURIComponent
 * @param {object} [opts.ret] object to be updated with found params
 * @param {string[]} [opts.tableIndex] list of parameters' names ( @experimental )
 * @param {string} [opts.pRegExp="\\:([a-z][a-z0-9]+)"] RegExp params' chars
 * @param {string} [opts.matchGroup="([^\\/]+)"] RegExp value
 * @param {string} [opts.fixedEnd=true] RegExp value
 * @returns {Object<string,string>}
 */

var paramsParse	= function (v, s, opts) {
	opts	= (opts || {});
	var cache = (opts.cache || null);
	var r	= (opts.ret || {});
	var mapper	= opts.mapper || function decodeURLReference(v) {
		var err, val = v;
		try {
			val = decodeURIComponent((v || '') + '');
		} catch (err) {
			val = unescape((v || '') + '');
		}
		return val;
	};
	var tableIndex, matchRule, cacheKey = s;
	if (cache && (cacheKey in cache)) {
		tableIndex = cache[cacheKey].tableIndex;
		matchRule = cache[cacheKey].matchRule;
	} else {
		var boud	= (opts.boud || '\x02\x00\x00\x03');
		tableIndex	= (opts.tableIndex || []);
		var pRegExp	= new RegExp(opts.pRegExp || "\\:([a-z][a-z0-9]+)", "gi");
		var fixedEnd = ( opts.fixedEnd === false ? false : true );
		var pCleaner	= function (idx, parts) {
			idx.push(parts[1]);
			return true;
		};
		var matchGroup	= opts.matchGroup || '([^\/]+)';
		if (typeof(opts.pCleaner) === "function") {
			pCleaner	= opts.pCleaner;
		};
		s = s.replace(new RegExp(matchGroup.toHex().replace(/(.{2})/g,'\\x$1'), "g"), boud);
		s = s.replace(pRegExp, function () {
			var p	= pCleaner(tableIndex, arguments);
			if (p === true) {
				return matchGroup;
			} else if (typeof(p) === "string") {
				return p;
			} else {
				return arguments[0];
			}
		});
		var rboud	= new RegExp(boud.toHex().replace(/(.{2})/g,'\\x$1'), "g")
		matchRule = new RegExp(
			s.split(matchGroup).map(function (v) {
				return v.replace(rboud, matchGroup).toHex().replace(/(.{2})/g,'\\x$1');
			}).join(matchGroup) + ( fixedEnd ? "$" : ""),
			""
		);

		if (cache) {
			cache[cacheKey] = {
				matchRule: matchRule,
				tableIndex: tableIndex
			};
		}
	}
	var matches = v.match(matchRule);
	if (!matches) return null;
	tableIndex.forEach(function (v, k) {
		r[v]	= mapper(matches[k+1]);
	});
	return r;
};


module.exports  = paramsParse;

paramsParse.test    = function () {
	var testString	= "/login/:service/:action/test%20";

	console.log(paramsParse("/api/test%20value/", "/api/:name/"));
	console.log(paramsParse("/login/google/login/test",testString));
};