// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:async'; import 'package:async/async.dart'; import 'handler.dart'; import 'request.dart'; import 'response.dart'; import 'server.dart'; /// A connected pair of a [Server] and a [Handler]. /// /// Requests to the handler are sent to the server's mounted handler once it's /// available. This is used to expose a virtual [Server] that's actually one /// part of a larger URL-space. @Deprecated('Do not use. If you have a use case for this class add a comment ' 'at https://github.com/dart-lang/shelf/issues/205') class ServerHandler { /// The server. /// /// Once this has a handler mounted, it's passed all requests to [handler] /// until this server is closed. Server get server => _server; final _HandlerServer _server; /// The handler. /// /// This passes requests to [server]'s handler. If that handler isn't mounted /// yet, the requests are handled once it is. Handler get handler => _onRequest; /// Creates a new connected pair of a [Server] with the given [url] and a /// [Handler]. /// /// The caller is responsible for ensuring that requests to [url] or any URL /// beneath it are handled by [handler]. /// /// If [onClose] is passed, it's called when [server] is closed. It may return /// a [Future] or `null`; its return value is returned by [Server.close]. ServerHandler(Uri url, {Future? Function()? onClose}) : _server = _HandlerServer(url, onClose); /// Pipes requests to [server]'s handler. FutureOr _onRequest(Request request) { if (_server._closeMemo.hasRun) { throw StateError('Request received after the server was closed.'); } if (_server._handler != null) return _server._handler!(request); // Avoid async/await so that the common case of a handler already being // mounted doesn't involve any extra asynchronous delays. return _server._onMounted.then((_) => _server._handler!(request)); } } // ignore: deprecated_member_use_from_same_package /// The [Server] returned by [ServerHandler]. class _HandlerServer implements Server { @override final Uri url; /// The callback to call when [close] is called, or `null`. final ZoneCallback? _onClose; /// The mounted handler. /// /// This is `null` until [mount] is called. Handler? _handler; /// A future that fires once [mount] has been called. Future get _onMounted => _onMountedCompleter.future; final _onMountedCompleter = Completer(); _HandlerServer(this.url, this._onClose); @override void mount(Handler handler) { if (_handler != null) { throw StateError("Can't mount two handlers for the same server."); } _handler = handler; _onMountedCompleter.complete(); } @override Future close() => _closeMemo.runOnce(() { return _onClose == null ? null : _onClose(); }); final _closeMemo = AsyncMemoizer(); }