APIドキュメントがWebSocketハンドラーの登録を推奨する方法は次のとおりです。
server
.where((request) => request.uri.path == "/ws")
.transform(new WebSocketTransformer()).listen((webSocket) => ...);
ただし、サーバーは単一サブスクリプションストリームです。alisten
をアタッチすると、他のリスナーをアタッチできなくなります。
私が本当に望んでいるのは、何かがイベントを見て、それを処理できるかどうかを判断し、処理できる場合は、別のストリームにルーティングすることです。それ以外の場合は、それを渡します。このようにして、イベント(この場合はHttpRequestオブジェクト)は、処理されるまでチェーンに沿って渡されます。
を拡張するTakeAndRoute
クラスを作成しましたStreamEventTransformer
。はTakeAndRoute
関数を使用して、イベントを取得して別のストリームにルーティングするか、単に転送するかを決定します。
これが私が思いついたものです:
import 'dart:io';
import 'dart:async';
handleWebSocket(WebSocket webSocket) {
webSocket.listen((event) {
if (event is MessageEvent) {
/* Handle message. */
} else if (event is CloseEvent) {
/* Handle closed. */
}
});
}
typedef bool ShouldTake(e);
typedef void RouteTo(Stream stream);
typedef void HandleEvent(e);
class TakeAndRoute<S, T> extends StreamEventTransformer<S, T> {
ShouldTake shouldTake;
RouteTo routeTo;
StreamController controller = new StreamController();
HandleEvent handler;
TakeAndRoute(this.shouldTake, {this.routeTo, this.handler}) {
if (routeTo != null) routeTo(controller.stream);
}
handleData(event, StreamSink sink) {
print("handling");
if (shouldTake(event)) {
if (routeTo != null) {
controller.add(event);
}
if (handler != null) {
handler(event);
}
} else {
sink.add(event);
}
}
}
main() {
HttpServer.bind('127.0.0.1', 8888)
.then((HttpServer server) {
server
.transform(new TakeAndRoute<HttpRequest, HttpRequest>(
(req) => req.uri.path == '/ws',
routeTo: (stream) => stream.transform(new WebSocketTransformer()).listen(handleWebSocket)))
.transform(new TakeAndRoute<HttpRequest, HttpRequest>(
(req) => req.uri.path == '/foo',
handler: (req) {
print('got foo');
req.response.addString("foo");
req.response.close();
}))
.listen((req) {
print("got 404 for ${req.uri}");
req.response.statusCode = 404;
req.response.close();
});
});
}
確かに、これはやり過ぎかもしれません。