From 6e87c6ecb301394973166b1d9a7f73a338ac5fec Mon Sep 17 00:00:00 2001 From: David Martos Date: Tue, 31 Oct 2023 15:51:29 +0100 Subject: [PATCH] feat: Support reuse of nested router (#393) Co-authored-by: Renan <6718144+renancaraujo@users.noreply.github.com> Co-authored-by: Erick Co-authored-by: Tom Arra --- packages/dart_frog/lib/src/context.dart | 10 ++++++ packages/dart_frog/lib/src/router.dart | 13 ++++++- packages/dart_frog/test/src/router_test.dart | 38 ++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/packages/dart_frog/lib/src/context.dart b/packages/dart_frog/lib/src/context.dart index 3a0a85fae..10a1fb582 100644 --- a/packages/dart_frog/lib/src/context.dart +++ b/packages/dart_frog/lib/src/context.dart @@ -42,4 +42,14 @@ This can happen if $T was not provided to the request context: } return (value as T Function())(); } + + /// Get URL parameters captured by the [Router.mount]. + /// They can be accessed from inside the mounted routes. + Map get mountedParams { + final p = request._request.context['dart_frog/mountedParams']; + if (p is Map) { + return UnmodifiableMapView(p); + } + return _emptyParams; + } } diff --git a/packages/dart_frog/lib/src/router.dart b/packages/dart_frog/lib/src/router.dart index b34998d78..3e0a54ce7 100644 --- a/packages/dart_frog/lib/src/router.dart +++ b/packages/dart_frog/lib/src/router.dart @@ -142,7 +142,18 @@ class Router { effectivePath = urlPath; } final modifiedRequestContext = RequestContext._( - request._request.change(path: effectivePath), + request._request.change( + path: effectivePath, + context: { + // Include the parameters captured here as mounted parameters. + // We also include previous mounted params in case there is double + // nesting of `mount`s + 'dart_frog/mountedParams': { + ...context.mountedParams, + ...params, + }, + }, + ), ); return await Function.apply(handler, [ diff --git a/packages/dart_frog/test/src/router_test.dart b/packages/dart_frog/test/src/router_test.dart index 57f81c9ef..685148918 100644 --- a/packages/dart_frog/test/src/router_test.dart +++ b/packages/dart_frog/test/src/router_test.dart @@ -624,6 +624,44 @@ void main() { expect(catchAllResponse.body, equals('catch-all-handler')); }); + test('dynamic routes mountedParams', () async { + final context = _MockRequestContext(); + + final usersRouter = () { + final router = Router(); + + String getUser(RequestContext c) => c.mountedParams['user']!; + + router.get( + '/self', + (RequestContext context) => Response(body: "I'm ${getUser(context)}"), + ); + return router; + }(); + + final app = Router() + ..mount('/users/', ( + RequestContext context, + String user, + ) { + return usersRouter(context); + }); + + server.mount((request) async { + when(() => context.request).thenReturn( + Request(request.method, request.requestedUri), + ); + final response = await app.call(context); + final body = await response.body(); + return shelf.Response(response.statusCode, body: body); + }); + + final response = await http.get( + Uri.parse('${server.url}/users/jack/self'), + ); + expect(response.body, equals("I'm jack")); + }); + group('RouterEntry', () { void testPattern( String pattern, {