1 module hunt.http.routing.impl.AbstractPatternMatcher; 2 3 import hunt.http.routing.Matcher; 4 import hunt.http.routing.Router; 5 6 import hunt.Exceptions; 7 import hunt.collection; 8 9 import hunt.logging; 10 import hunt.text; 11 12 import std.conv; 13 import std.regex; 14 import std.array; 15 16 /** 17 * 18 */ 19 abstract class AbstractPatternMatcher : Matcher { 20 21 protected Map!(PatternRule, Set!(Router)) _patternMap; 22 23 protected static class PatternRule { 24 string rule; 25 Pattern pattern; 26 27 protected this(string rule) { 28 this.rule = rule; 29 string[] rules = rule.split("*").array; 30 pattern = Pattern.compile(rule, "*"); 31 } 32 33 override 34 bool opEquals(Object o) { 35 if (this is o) return true; 36 PatternRule that = cast(PatternRule) o; 37 if(that is null) return false; 38 return rule == that.rule; 39 } 40 41 override 42 size_t toHash() @trusted nothrow { 43 return hashOf(rule); 44 } 45 } 46 47 this() 48 { 49 _patternMap = new HashMap!(PatternRule, Set!(Router))(); 50 } 51 52 // protected Map!(PatternRule, Set!(Router)) patternMap() { 53 // if (_patternMap is null) { 54 // _patternMap = new HashMap!(PatternRule, Set!(Router))(); 55 // } 56 // return _patternMap; 57 // } 58 59 abstract MatchType getMatchType() { implementationMissing(); return MatchType.PATH; } 60 61 void add(string rule, Router router) { 62 _patternMap.computeIfAbsent(new PatternRule(rule), k => new HashSet!Router()).add(router); 63 //trace("_patternMap size: ", _patternMap.size()) ; 64 } 65 66 MatchResult match(string v) { 67 if (_patternMap is null) { 68 return null; 69 } 70 71 Set!Router routers = new HashSet!Router(); 72 Map!(Router, Map!(string, string)) parameters = new HashMap!(Router, Map!(string, string))(); 73 74 foreach(PatternRule rule, Set!(Router) routerSet; _patternMap) 75 { 76 // tracef("v=%s, pattern=%s", v, rule.rule); 77 string[] strings = rule.pattern.match(v); 78 if (strings.length == 0) 79 continue; 80 81 routers.addAll(routerSet); 82 Map!(string, string) param = new HashMap!(string, string)(); 83 84 int i=0; 85 foreach(string item; strings) { 86 // tracef("%d => %s", i, item); 87 // FIXME: Needing refactor or cleanup -@zhangxueping at 2020-03-09T19:24:20+08:00 88 // check this 89 // param.put("param" ~ i.to!string(), item); 90 i++; 91 } 92 93 foreach(router; routerSet) { 94 parameters.put(router, param); 95 } 96 97 } 98 if (routers.isEmpty()) { 99 return null; 100 } else { 101 return new MatchResult(routers, parameters, getMatchType()); 102 } 103 } 104 105 }