@@ -19,7 +19,7 @@ import 'package:http_methods/http_methods.dart';
19
19
import 'package:meta/meta.dart' show sealed;
20
20
import 'package:shelf/shelf.dart' ;
21
21
22
- import 'router_entry.dart' show RouterEntry;
22
+ import 'router_entry.dart' show ParamInfo, RouterEntry;
23
23
24
24
/// Get a URL parameter captured by the [Router] .
25
25
@Deprecated ('Use Request.params instead' )
@@ -167,7 +167,7 @@ class Router {
167
167
prefix + '<$pathParam |[^]*>' ,
168
168
(Request request, RouterEntry route) {
169
169
// Remove path param from extracted route params
170
- final paramsList = [...route.params ]..removeLast ();
170
+ final paramsList = [...route.paramInfos ]..removeLast ();
171
171
return _invokeMountedHandler (request, handler, path, paramsList);
172
172
},
173
173
mounted: true ,
@@ -176,15 +176,16 @@ class Router {
176
176
_all (
177
177
prefix,
178
178
(Request request, RouterEntry route) {
179
- return _invokeMountedHandler (request, handler, path, route.params);
179
+ return _invokeMountedHandler (
180
+ request, handler, path, route.paramInfos);
180
181
},
181
182
mounted: true ,
182
183
);
183
184
_all (
184
185
prefix + '/<$pathParam |[^]*>' ,
185
186
(Request request, RouterEntry route) {
186
187
// Remove path param from extracted route params
187
- final paramsList = [...route.params ]..removeLast ();
188
+ final paramsList = [...route.paramInfos ]..removeLast ();
188
189
return _invokeMountedHandler (
189
190
request, handler, path + '/' , paramsList);
190
191
},
@@ -194,13 +195,14 @@ class Router {
194
195
}
195
196
196
197
Future <Response > _invokeMountedHandler (Request request, Function handler,
197
- String path, List <String > paramsList ) async {
198
+ String path, List <ParamInfo > paramInfos ) async {
198
199
final params = _getParamsFromRequest (request);
199
- final resolvedPath = _replaceParamsInPath (request, path, params);
200
+ final resolvedPath =
201
+ _replaceParamsInPath (request, path, params, paramInfos);
200
202
201
203
return await Function .apply (handler, [
202
204
request.change (path: resolvedPath),
203
- ...paramsList .map ((n ) => params[n ]),
205
+ ...paramInfos .map ((info ) => params[info.name ]),
204
206
]) as Response ;
205
207
}
206
208
@@ -214,15 +216,37 @@ class Router {
214
216
Request request,
215
217
String path,
216
218
Map <String , String > params,
219
+ List <ParamInfo > paramInfos,
217
220
) {
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
+ }
224
248
}
225
-
249
+ var resolvedPath = resolvedPathBuff. toString ();
226
250
return resolvedPath;
227
251
}
228
252
0 commit comments