Skip to content

Commit 6e87c6e

Browse files
davidmartos96renancaraujoerickzanardotomarra
authored
feat: Support reuse of nested router (#393)
Co-authored-by: Renan <[email protected]> Co-authored-by: Erick <[email protected]> Co-authored-by: Tom Arra <[email protected]>
1 parent 08a2851 commit 6e87c6e

File tree

3 files changed

+60
-1
lines changed

3 files changed

+60
-1
lines changed

packages/dart_frog/lib/src/context.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,14 @@ This can happen if $T was not provided to the request context:
4242
}
4343
return (value as T Function())();
4444
}
45+
46+
/// Get URL parameters captured by the [Router.mount].
47+
/// They can be accessed from inside the mounted routes.
48+
Map<String, String> get mountedParams {
49+
final p = request._request.context['dart_frog/mountedParams'];
50+
if (p is Map<String, String>) {
51+
return UnmodifiableMapView(p);
52+
}
53+
return _emptyParams;
54+
}
4555
}

packages/dart_frog/lib/src/router.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,18 @@ class Router {
142142
effectivePath = urlPath;
143143
}
144144
final modifiedRequestContext = RequestContext._(
145-
request._request.change(path: effectivePath),
145+
request._request.change(
146+
path: effectivePath,
147+
context: {
148+
// Include the parameters captured here as mounted parameters.
149+
// We also include previous mounted params in case there is double
150+
// nesting of `mount`s
151+
'dart_frog/mountedParams': {
152+
...context.mountedParams,
153+
...params,
154+
},
155+
},
156+
),
146157
);
147158

148159
return await Function.apply(handler, [

packages/dart_frog/test/src/router_test.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,44 @@ void main() {
624624
expect(catchAllResponse.body, equals('catch-all-handler'));
625625
});
626626

627+
test('dynamic routes mountedParams', () async {
628+
final context = _MockRequestContext();
629+
630+
final usersRouter = () {
631+
final router = Router();
632+
633+
String getUser(RequestContext c) => c.mountedParams['user']!;
634+
635+
router.get(
636+
'/self',
637+
(RequestContext context) => Response(body: "I'm ${getUser(context)}"),
638+
);
639+
return router;
640+
}();
641+
642+
final app = Router()
643+
..mount('/users/<user>', (
644+
RequestContext context,
645+
String user,
646+
) {
647+
return usersRouter(context);
648+
});
649+
650+
server.mount((request) async {
651+
when(() => context.request).thenReturn(
652+
Request(request.method, request.requestedUri),
653+
);
654+
final response = await app.call(context);
655+
final body = await response.body();
656+
return shelf.Response(response.statusCode, body: body);
657+
});
658+
659+
final response = await http.get(
660+
Uri.parse('${server.url}/users/jack/self'),
661+
);
662+
expect(response.body, equals("I'm jack"));
663+
});
664+
627665
group('RouterEntry', () {
628666
void testPattern(
629667
String pattern, {

0 commit comments

Comments
 (0)