22
33import org .javawebstack .http .router .Exchange ;
44import org .javawebstack .http .router .HTTPMethod ;
5+ import org .javawebstack .http .router .HTTPRoutingOptions ;
56import org .javawebstack .http .router .handler .AfterRequestHandler ;
67import org .javawebstack .http .router .handler .RequestHandler ;
78import org .javawebstack .http .router .transformer .route .RouteParamTransformerProvider ;
@@ -21,37 +22,40 @@ public class Route {
2122 private List <RequestHandler > handlers ;
2223 private List <AfterRequestHandler > afterHandlers ;
2324
24- public Route (RouteParamTransformerProvider routeParamTransformerProvider , HTTPMethod method , String pattern , List <RequestHandler > handlers ) {
25- this (routeParamTransformerProvider , method , pattern , ":" , handlers );
25+ public Route (RouteParamTransformerProvider routeParamTransformerProvider , HTTPMethod method , String pattern , HTTPRoutingOptions options , List <RequestHandler > handlers ) {
26+ this (routeParamTransformerProvider , method , pattern , options , ":" , handlers );
2627 }
2728
28- public Route (RouteParamTransformerProvider routeParamTransformerProvider , HTTPMethod method , String pattern , String variableDelimiter , List <RequestHandler > handlers ) {
29+ public Route (RouteParamTransformerProvider routeParamTransformerProvider , HTTPMethod method , String pattern , HTTPRoutingOptions options , String variableDelimiter , List <RequestHandler > handlers ) {
2930 this .handlers = handlers ;
3031 this .method = method ;
3132 this .routeParamTransformerProvider = routeParamTransformerProvider ;
3233 pattern = pattern .toLowerCase (Locale .ENGLISH );
33- if (pattern .endsWith ("/" ))
34- pattern = pattern .substring (0 , pattern .length () - 1 );
34+ if (options .isIgnoreTrailingSlash ()) {
35+ if (pattern .endsWith ("/" ))
36+ pattern = pattern .substring (0 , pattern .length () - 1 );
37+ }
3538 if (!pattern .startsWith ("/" ))
3639 pattern = "/" + pattern ;
3740 int pos = 0 ;
3841 StringBuilder sb = new StringBuilder ();
3942 StringBuilder text = new StringBuilder ();
4043 boolean inVar = false ;
4144 while (pos < pattern .length ()) {
42- if (pattern .charAt (pos ) == '{' ) {
45+ char c = pattern .charAt (pos );
46+ if (c == '{' ) {
4347 if (inVar ) {
4448 throw new RuntimeException ("Unexpected character '{' in route at position " + pos );
4549 }
4650 if (text .length () > 0 ) {
47- sb .append ("(" + regexEscape ( text .toString ()) + ")" );
51+ sb .append ("(" + prepareRegex ( options , text .toString ()) + ")" );
4852 text = new StringBuilder ();
4953 }
5054 inVar = true ;
5155 pos ++;
5256 continue ;
5357 }
54- if (pattern . charAt ( pos ) == '}' ) {
58+ if (c == '}' ) {
5559 if (!inVar ) {
5660 throw new RuntimeException ("Unexpected character '}' in route at position " + pos );
5761 }
@@ -74,14 +78,17 @@ public Route(RouteParamTransformerProvider routeParamTransformerProvider, HTTPMe
7478 pos ++;
7579 continue ;
7680 }
77- text .append (pattern . charAt ( pos ) );
81+ text .append (c );
7882 pos ++;
7983 }
8084 if (inVar ) {
8185 throw new RuntimeException ("Unexpected end in route" );
8286 }
8387 if (text .length () > 0 ) {
84- sb .append ("(" + regexEscape (text .toString ()) + ")" );
88+ sb .append ("(" + prepareRegex (options , text .toString ()) + ")" );
89+ }
90+ if (options .isIgnoreTrailingSlash ()) {
91+ sb .append ("/?" );
8592 }
8693 this .pattern = Pattern .compile (sb .toString ());
8794 }
@@ -117,6 +124,28 @@ public List<AfterRequestHandler> getAfterHandlers() {
117124 return afterHandlers ;
118125 }
119126
127+ private static String prepareRegex (HTTPRoutingOptions options , String text ) {
128+ text = regexEscape (text );
129+ if (options .isCaseInsensitive ())
130+ text = ignoreCase (text );
131+ return text ;
132+ }
133+
134+ private static String ignoreCase (String s ) {
135+ StringBuilder sb = new StringBuilder ();
136+ for (char c : s .toCharArray ()) {
137+ if (Character .isAlphabetic (c )) {
138+ char inverted = Character .isUpperCase (c ) ? Character .toLowerCase (c ) : Character .toUpperCase (c );
139+ if (c != inverted ) {
140+ sb .append ("[" ).append (c ).append (inverted ).append ("]" );
141+ continue ;
142+ }
143+ }
144+ sb .append (c );
145+ }
146+ return sb .toString ();
147+ }
148+
120149 private static String regexEscape (String s ) {
121150 for (char c : "\\ <([{^-=$!|]})?*+.>" .toCharArray ()) {
122151 s = s .replace (String .valueOf (c ), "\\ " + c );
0 commit comments