Skip to content

Commit

Permalink
feat: Support reuse of nested router (#393)
Browse files Browse the repository at this point in the history
Co-authored-by: Renan <[email protected]>
Co-authored-by: Erick <[email protected]>
Co-authored-by: Tom Arra <[email protected]>
  • Loading branch information
4 people authored Oct 31, 2023
1 parent 08a2851 commit 6e87c6e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 1 deletion.
10 changes: 10 additions & 0 deletions packages/dart_frog/lib/src/context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, String> get mountedParams {
final p = request._request.context['dart_frog/mountedParams'];
if (p is Map<String, String>) {
return UnmodifiableMapView(p);
}
return _emptyParams;
}
}
13 changes: 12 additions & 1 deletion packages/dart_frog/lib/src/router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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, [
Expand Down
38 changes: 38 additions & 0 deletions packages/dart_frog/test/src/router_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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/<user>', (
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, {
Expand Down

0 comments on commit 6e87c6e

Please sign in to comment.