fromExtractor<T extends Object> function
Runs extractor as middleware, and passes its value on to the handler.
The counterpart to axum's middleware::from_extractor. A layer can pass a
request on or answer it, so an extractor used as one needs somewhere to put
what it produced: it goes in the request context, and Extension reads it
back.
final admin = Router()
..routeLayer(fromExtractor(const RequireScope('admin')))
..route('/orders', get(listOrders));
Two things this buys over naming the extractor in every handler. The work happens once for a request rather than once per handler that wants the value. And a route added later cannot forget it, which turns a code review into a compile-time arrangement.
Pair it with routeLayer rather than layer for a guard: a path that does
not exist should answer 404, not 401.
Implementation
Middleware fromExtractor<T extends Object>(FromRequestParts<T> extractor) {
return (Handler inner) {
return (Request request) async {
switch (await extractor.extract(request)) {
case Err(:final error):
return error.intoResponse();
case Ok(:final value):
return inner(
request.change(context: {extensionKeyFor<T>(): value}),
);
}
};
};
}