2626package robaho .net .httpserver ;
2727
2828import java .util .*;
29+ import java .util .concurrent .ConcurrentHashMap ;
2930import java .util .concurrent .CopyOnWriteArrayList ;
3031
3132class ContextList {
3233
3334 private final List <HttpContextImpl > list = new CopyOnWriteArrayList <>();
35+ private final Map <CacheKey ,HttpContextImpl > cache = new ConcurrentHashMap <>();
36+ private record CacheKey (String protocol ,String path ){}
3437
3538 public synchronized void add (HttpContextImpl ctx ) {
3639 assert ctx .getPath () != null ;
@@ -53,15 +56,24 @@ public int size() {
5356 * Context with longest prefix matches (currently case-sensitive)
5457 */
5558 HttpContextImpl findContext (String protocol , String path ) {
56- return findContext (protocol , path , false );
59+ CacheKey key = new CacheKey (protocol ,path );
60+ var ctx = cache .get (key );
61+ if (ctx !=null ) return ctx ;
62+ ctx = findContext (protocol , path , false );
63+ // only cache exact matches, otherwise path parameters will
64+ // explode memory
65+ if (ctx !=null && ctx .getPath ().equals (path )) {
66+ cache .put (key ,ctx );
67+ }
68+ return ctx ;
5769 }
5870
5971 HttpContextImpl findContext (String protocol , String path , boolean exact ) {
60- protocol = protocol .toLowerCase (Locale .ROOT );
72+ String _protocol = protocol .toLowerCase (Locale .ROOT );
6173 String longest = "" ;
6274 HttpContextImpl lc = null ;
6375 for (HttpContextImpl ctx : list ) {
64- if (!ctx .getProtocol ().equals (protocol )) {
76+ if (!ctx .getProtocol ().equals (_protocol )) {
6577 continue ;
6678 }
6779 String cpath = ctx .getPath ();
0 commit comments