6

(我正在使用 dart:io 的新 lib v2 版本。)

我想为 HttpServer 注册多个处理程序,特别是 WebSocketTransformer 和其他任意处理程序。像这样的东西:

// pseudo-code

var server = HttpServer;
server.register('/foo', someHandlerFunction);        // 1
server.register('/bar', someOtherHandlerFunction);   // 2
server.register('/ws', webSocketHandler);            // 3

如果 #1 匹配,则不测试 #2,依此类推。所以,很贪心。

我见过只有一个处理程序的样本。如何注册多个处理程序?提前致谢!

4

3 回答 3

3

新答案:使用路由包: http: //pub.dartlang.org/packages/route

这是您使用路由serve()方法的示例:

HttpServer.bind('127.0.0.1', 8889).then((server) {
  var router = new Router(server)
    ..serve('/ws').transform(new WebSocketTransformer()).listen(handleWebSocket)
    ..serve('/foo').listen((req) {
      req.response..addString('foo')..close();
    });
});

路由器会自动捕获未处理的请求并发送 404,但很快您就可以使用defaultStream可以收听的内容覆盖它。

路由器还支持过滤器,可用于日志记录、身份验证、压缩等:

HttpServer.bind('127.0.0.1', 8889).then((server) {
  var router = new Router(server)
    ..filter(new RegExp(r'/.*'), (req) {
      //log all requests
      _logger.info("request: $req");
      return new Future.immediate(true); // keep processing request
    })
    ..filter(new Regexp(r'/secure/.*'), (req) {
      // check authentication asynchronously
      return getUserFromRequest(req).then((user) {
        if (user == null) {
          sendRedirect('/login'); // sendRedirect coming soon
          return false; // stop processing request
        } else {
          return true; // keep processing
        }
      });
    })
    ..serve(/* ... */ );
});
于 2013-03-09T22:08:13.287 回答
0

以下是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();
        });
    });
}

诚然,这可能是矫枉过正。

于 2013-02-27T07:18:08.577 回答
0

这是一种更手动但更短的方法:

  HttpServer.bind('127.0.0.1', 8889)
    .then((HttpServer server) {
      var sc = new StreamController();
      sc.stream.transform(new WebSocketTransformer()).listen(handleWebSocket);

      server.listen((HttpRequest request) {
        print("new connection from ${request.uri.scheme} ${request.uri}");

        // See https://code.google.com/p/dart/issues/detail?id=8825
        //if (request.uri.scheme == 'ws') {
        if (request.uri.path == '/ws') {
          sc.add(request);
        } else if (request.uri.path == '/foo') {
          request.response.addString('foo');
          request.response.close();
        } else {
          print("got 404 for ${request.uri}");
          request.response.statusCode = 404;
          request.response.close();
        }
      });
    });

请注意我必须如何创建一个 StreamController 以便我可以将事件泵送到WebSocketTransformer

于 2013-02-27T07:45:17.393 回答