/// <summary> /// Remove action associated with path and method<br/> /// 删除路径和方法关联的Action函数<br/> /// </summary> public bool Remove(string path, string method) { var basePath = ParsePath(path, out var regex, out var parameters); if (regex == null) { // Normal action var key = Pair.Create(basePath, method); return(Actions.TryRemove(key, out var _)); } else { // Regex action RegexActionsLock.EnterReadLock(); try { var pattern = regex.ToString(); return(RegexActions.TryGetValue(basePath, out var descriptors) && descriptors.RemoveAll(d => d.Method == method && d.Regex.ToString() == pattern) > 0); } finally { RegexActionsLock.ExitReadLock(); } } }
/// <summary> /// Associate action with path and method<br/> /// 设置路径和方法关联的Action函数<br/> /// </summary> public void Set(string path, string method, Func <IActionResult> action, bool overrideExists) { // Parse path var basePath = ParsePath(path, out var pattern, out var parameters); // Duplicate check var key = Pair.Create(basePath, method); if (!overrideExists) { bool duplicated = false; if (pattern == null) { // No expression found, just check the key duplicated = Actions.ContainsKey(key); } else { // Check if there any descriptor have same method and regex RegexActionsLock.EnterReadLock(); try { duplicated = RegexActions.TryGetValue(basePath, out var descriptors) && descriptors.Any(d => d.Method == method && d.Pattern == pattern); } finally { RegexActionsLock.ExitReadLock(); } } if (duplicated) { throw new ArgumentException( $"Action for method '{method}' and path '{path}' already registered, " + "please use option `overrideExists` if you want to replace it"); } } // Register action if (pattern == null) { // Normal action Actions[key] = action; } else { // Regex action RegexActionsLock.EnterWriteLock(); try { if (!RegexActions.TryGetValue(basePath, out var descriptors)) { descriptors = new List <RegexActionDescriptor>(); RegexActions[basePath] = descriptors; } // Sort descriptors by pattern length descending var regex = new Regex(pattern); descriptors.Add(new RegexActionDescriptor(method, pattern, regex, parameters, action)); descriptors.Sort((x, y) => y.Pattern.Length - x.Pattern.Length); } finally { RegexActionsLock.ExitWriteLock(); } } }
/// <summary> /// Get action associated with path and method<br/> /// 获取路径和方法关联的Action函数<br/> /// </summary> public Func <IActionResult> Get(string path, string method) { // Search normal action var key = Pair.Create(path, method); if (Actions.TryGetValue(key, out var action)) { return(action); } // Search regex action // Matching from the lonest base path, for example: // rules: "get/some/{id}", "get/{id}" // "get/some/1" matches "get/some/{id}" // "get/1" matches "get/{id}" RegexActionsLock.EnterReadLock(); try { var nodes = RegexActions.Travel(path, false).Where(a => a.HasValue).Reverse(); foreach (var node in nodes) { foreach (var descriptor in node.Value) { // Check method first because all methods are using the same list if (descriptor.Method != method) { continue; } // Match pattern, descriptors should be sorted by pattern length descennding var match = descriptor.Regex.Match(path); if (!match.Success) { continue; } // Set custom parameters to request var request = HttpManager.CurrentContext.Request; for (var i = 0; i < descriptor.Parameters.Count; ++i) { var name = descriptor.Parameters[i]; var value = match.Groups[i + 1].Value; request.CustomParameters[name] = value; } return(descriptor.Action); } } } finally { RegexActionsLock.ExitReadLock(); } return(null); }