Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(563)

Side by Side Diff: lib/src/server_handler.dart

Issue 1411553006: Add a Server interface. (Closed) Base URL: git@github.com:dart-lang/shelf@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library shelf.server_handler;
6
7 import 'dart:async';
8
9 import 'package:async/async.dart';
10
11 import 'request.dart';
12 import 'handler.dart';
13 import 'server.dart';
14
15 /// A connected pair of a [Server] and a [Handler].
16 ///
17 /// Requests to the handler are sent to the server's mounted handler once it's
18 /// available. This is used to expose a virtual [Server] that's actually one
19 /// part of a larger URL-space.
20 class ServerHandler {
21 /// The server.
22 ///
23 /// Once this has a handler mounted, it's passed all requests to [handler]
24 /// until this server is closed.
25 Server get server => _server;
26 final _HandlerServer _server;
27
28 /// The handler.
29 ///
30 /// This passes requests to [server]'s handler. If that handler isn't mounted
31 /// yet, the requests are handled once it is.
32 Handler get handler => _onRequest;
33
34 /// Creates a new connected pair of a [Server] with the given [url] and a
35 /// [Handler].
36 ///
37 /// The caller is responsible for ensuring that requests to [url] or any URL
38 /// beneath it are handled by [handler].
39 ///
40 /// If [onClose] is passed, it's called when [server] is closed. It may return
41 /// a [Future] or `null`; its return value is returned by [Server.close].
42 ServerHandler(Uri url, {onClose()})
43 : _server = new _HandlerServer(url, onClose);
44
45 /// Pipes requests to [server]'s handler.
46 _onRequest(Request request) {
47 if (_server._closeMemo.hasRun) {
48 throw new StateError("Request received after the server was closed.");
49 }
50
51 if (_server._handler != null) return _server._handler(request);
52
53 // Avoid async/await so that the common case of a handler already being
54 // mounted doesn't involve any extra asynchronous delays.
55 return _server._onMounted.then((_) => _server._handler(request));
kevmoo 2015/10/22 00:44:26 Why don't you use awa...oh.
56 }
57 }
58
59 /// The [Server] returned by [ServerHandler].
60 class _HandlerServer implements Server {
61 final Uri url;
62
63 /// The callback to call when [close] is called, or `null`.
64 final ZoneCallback _onClose;
65
66 /// The mounted handler.
67 ///
68 /// This is `null` until [mount] is called.
69 Handler _handler;
70
71 /// A future that fires once [mount] has been called.
72 Future get _onMounted => _onMountedCompleter.future;
73 final _onMountedCompleter = new Completer();
74
75 _HandlerServer(this.url, this._onClose);
76
77 void mount(Handler handler) {
78 if (_handler != null) {
79 throw new StateError("Can't mount two handlers for the same server.");
80 }
81
82 _handler = handler;
83 _onMountedCompleter.complete();
84 }
85
86 Future close() => _closeMemo.runOnce(() {
87 return _onClose == null ? null : _onClose();
88 });
89 final _closeMemo = new AsyncMemoizer();
90 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698