@@ -19,7 +19,7 @@ import 'package:http_methods/http_methods.dart';
1919import 'package:meta/meta.dart' show sealed;
2020import 'package:shelf/shelf.dart' ;
2121
22- import 'router_entry.dart' show RouterEntry;
22+ import 'router_entry.dart' show ParamInfo, RouterEntry;
2323
2424/// Get a URL parameter captured by the [Router] .
2525@Deprecated ('Use Request.params instead' )
@@ -167,7 +167,7 @@ class Router {
167167 prefix + '<$pathParam |[^]*>' ,
168168 (Request request, RouterEntry route) {
169169 // Remove path param from extracted route params
170- final paramsList = [...route.params ]..removeLast ();
170+ final paramsList = [...route.paramInfos ]..removeLast ();
171171 return _invokeMountedHandler (request, handler, path, paramsList);
172172 },
173173 mounted: true ,
@@ -176,15 +176,16 @@ class Router {
176176 _all (
177177 prefix,
178178 (Request request, RouterEntry route) {
179- return _invokeMountedHandler (request, handler, path, route.params);
179+ return _invokeMountedHandler (
180+ request, handler, path, route.paramInfos);
180181 },
181182 mounted: true ,
182183 );
183184 _all (
184185 prefix + '/<$pathParam |[^]*>' ,
185186 (Request request, RouterEntry route) {
186187 // Remove path param from extracted route params
187- final paramsList = [...route.params ]..removeLast ();
188+ final paramsList = [...route.paramInfos ]..removeLast ();
188189 return _invokeMountedHandler (
189190 request, handler, path + '/' , paramsList);
190191 },
@@ -194,13 +195,14 @@ class Router {
194195 }
195196
196197 Future <Response > _invokeMountedHandler (Request request, Function handler,
197- String path, List <String > paramsList ) async {
198+ String path, List <ParamInfo > paramInfos ) async {
198199 final params = _getParamsFromRequest (request);
199- final resolvedPath = _replaceParamsInPath (request, path, params);
200+ final resolvedPath =
201+ _replaceParamsInPath (request, path, params, paramInfos);
200202
201203 return await Function .apply (handler, [
202204 request.change (path: resolvedPath),
203- ...paramsList .map ((n ) => params[n ]),
205+ ...paramInfos .map ((info ) => params[info.name ]),
204206 ]) as Response ;
205207 }
206208
@@ -214,15 +216,37 @@ class Router {
214216 Request request,
215217 String path,
216218 Map <String , String > params,
219+ List <ParamInfo > paramInfos,
217220 ) {
218- // TODO(davidmartos96): Maybe this could be done in a different way
219- // to avoid replacing the path N times, N being the number of params
220- var resolvedPath = path;
221- for (final paramEntry in params.entries) {
222- resolvedPath =
223- resolvedPath.replaceFirst ('<${paramEntry .key }>' , paramEntry.value);
221+ // we iterate the non-resolved path and we write to a StringBuffer
222+ // resolving ther parameters along the way
223+ final resolvedPathBuff = StringBuffer ();
224+ var paramIndex = 0 ;
225+ var charIndex = 0 ;
226+ while (charIndex < path.length) {
227+ if (paramIndex < paramInfos.length) {
228+ final paramInfo = paramInfos[paramIndex];
229+ if (charIndex < paramInfo.startIdx - 1 ) {
230+ // Add up until the param slot starts
231+ final part = path.substring (charIndex, paramInfo.startIdx - 1 );
232+ resolvedPathBuff.write (part);
233+ charIndex += part.length;
234+ } else {
235+ // Add the resolved value of the parameter
236+ final paramName = paramInfo.name;
237+ final paramValue = params[paramName]! ;
238+ resolvedPathBuff.write (paramValue);
239+ charIndex = paramInfo.endIdx - 1 ;
240+ paramIndex++ ;
241+ }
242+ } else {
243+ // All params looped, so add up until the end of the path
244+ final part = path.substring (charIndex, path.length);
245+ resolvedPathBuff.write (part);
246+ charIndex += part.length;
247+ }
224248 }
225-
249+ var resolvedPath = resolvedPathBuff. toString ();
226250 return resolvedPath;
227251 }
228252
0 commit comments