OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library json_rpc_2.server; | 5 library json_rpc_2.server; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
10 | 10 |
(...skipping 25 matching lines...) Expand all Loading... |
36 /// | 36 /// |
37 /// These are tried in order until one of them doesn't throw a | 37 /// These are tried in order until one of them doesn't throw a |
38 /// [RpcException.methodNotFound] exception. | 38 /// [RpcException.methodNotFound] exception. |
39 final _fallbacks = new Queue<Function>(); | 39 final _fallbacks = new Queue<Function>(); |
40 | 40 |
41 /// Returns a [Future] that completes when the connection is closed. | 41 /// Returns a [Future] that completes when the connection is closed. |
42 /// | 42 /// |
43 /// This is the same future that's returned by [listen]. | 43 /// This is the same future that's returned by [listen]. |
44 Future get done => _streams.done; | 44 Future get done => _streams.done; |
45 | 45 |
| 46 /// Whether the connection is closed. |
| 47 bool get isClosed => _streams.isClosed; |
| 48 |
46 /// Creates a [Server] that reads requests from [requests] and writes | 49 /// Creates a [Server] that reads requests from [requests] and writes |
47 /// responses to [responses]. | 50 /// responses to [responses]. |
48 /// | 51 /// |
49 /// If [requests] is a [StreamSink] as well as a [Stream] (for example, a | 52 /// If [requests] is a [StreamSink] as well as a [Stream] (for example, a |
50 /// `WebSocket`), [responses] may be omitted. | 53 /// `WebSocket`), [responses] may be omitted. |
51 /// | 54 /// |
52 /// Note that the server won't begin listening to [requests] until | 55 /// Note that the server won't begin listening to [requests] until |
53 /// [Server.listen] is called. | 56 /// [Server.listen] is called. |
54 Server(Stream<String> requests, [StreamSink<String> responses]) { | 57 Server(Stream<String> requests, [StreamSink<String> responses]) { |
55 _streams = new TwoWayStream("Server", requests, "requests", | 58 _streams = new TwoWayStream("Server", requests, "requests", |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 if (request.isEmpty) { | 137 if (request.isEmpty) { |
135 return new RpcException(error_code.INVALID_REQUEST, 'A batch must ' | 138 return new RpcException(error_code.INVALID_REQUEST, 'A batch must ' |
136 'contain at least one request.').serialize(request); | 139 'contain at least one request.').serialize(request); |
137 } | 140 } |
138 | 141 |
139 return Future.wait(request.map(_handleSingleRequest)).then((results) { | 142 return Future.wait(request.map(_handleSingleRequest)).then((results) { |
140 var nonNull = results.where((result) => result != null); | 143 var nonNull = results.where((result) => result != null); |
141 return nonNull.isEmpty ? null : nonNull.toList(); | 144 return nonNull.isEmpty ? null : nonNull.toList(); |
142 }); | 145 }); |
143 }).then((response) { | 146 }).then((response) { |
144 if (response != null) _streams.add(response); | 147 if (!_streams.isClosed && response != null) _streams.add(response); |
145 }); | 148 }); |
146 } | 149 } |
147 | 150 |
148 /// Handles an individual parsed request. | 151 /// Handles an individual parsed request. |
149 Future _handleSingleRequest(request) { | 152 Future _handleSingleRequest(request) { |
150 return syncFuture(() { | 153 return syncFuture(() { |
151 _validateRequest(request); | 154 _validateRequest(request); |
152 | 155 |
153 var name = request['method']; | 156 var name = request['method']; |
154 var method = _methods[name]; | 157 var method = _methods[name]; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 return syncFuture(() => iterator.current(params)).catchError((error) { | 247 return syncFuture(() => iterator.current(params)).catchError((error) { |
245 if (error is! RpcException) throw error; | 248 if (error is! RpcException) throw error; |
246 if (error.code != error_code.METHOD_NOT_FOUND) throw error; | 249 if (error.code != error_code.METHOD_NOT_FOUND) throw error; |
247 return _tryNext(); | 250 return _tryNext(); |
248 }); | 251 }); |
249 } | 252 } |
250 | 253 |
251 return _tryNext(); | 254 return _tryNext(); |
252 } | 255 } |
253 } | 256 } |
OLD | NEW |