fromExtractor<T extends Object> function

Middleware fromExtractor<T extends Object>(
  1. FromRequestParts<T> extractor
)

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}),
          );
      }
    };
  };
}