2013-02-27 7 views
6

(Tôi đang sử dụng phiên bản lib v2 mới của phi tiêu: io.)Làm cách nào để đăng ký nhiều trình xử lý cho máy chủ HttpServer, trong Dart?

Tôi muốn đăng ký nhiều trình xử lý cho một HttpServer, cụ thể là trình xử lý WebSocketTransformer và các trình xử lý tùy ý khác. Một cái gì đó như thế này:

// pseudo-code 

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

Nếu # 1 khớp, thì # 2 không được kiểm tra, v.v. Vì vậy, nó tham lam.

Tôi đã xem các mẫu chỉ bằng một trình xử lý. Làm cách nào để đăng ký nhiều trình xử lý? Cảm ơn trước!

Trả lời

3

câu trả lời mới: Sử dụng gói đường : http://pub.dartlang.org/packages/route

Dưới đây là ví dụ của bạn sử dụng phương pháp đường của 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(); 
    }); 
}); 

Bộ định tuyến tự động bắt các yêu cầu chưa được xử lý và gửi 404, mặc dù bạn sẽ sớm có thể ghi đè lên bằng một số defaultStream mà bạn có thể nghe.

Router cũng hỗ trợ bộ lọc, hữu ích cho khai thác gỗ, auth, nén, v.v .:

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(/* ... */); 
}); 
+0

Đó là những gì tôi đang tìm kiếm, cảm ơn! –

0

Đây là cách API docs khuyên bạn nên đăng ký một handler WebSocket:

server 
    .where((request) => request.uri.path == "/ws") 
    .transform(new WebSocketTransformer()).listen((webSocket) => ...); 

Tuy nhiên, máy chủ là một dòng đơn thuê bao. Sau khi đính kèm listen, bạn không thể đính kèm các trình nghe khác.

Điều tôi thực sự muốn dành cho một cái gì đó để xem một sự kiện, quyết định xem nó có thể xử lý sự kiện hay không và sau đó định tuyến cho luồng khác. Nếu không, hãy vượt qua nó. Bằng cách này, sự kiện (trong trường hợp này là một đối tượng HttpRequest) được truyền theo một chuỗi cho đến khi nó được xử lý.

Tôi đã tạo một lớp học TakeAndRoute kéo dài StreamEventTransformer. TakeAndRoute sử dụng một chức năng để xác định xem nó có nên lấy sự kiện và định tuyến đến một luồng khác hay đơn giản là chuyển tiếp nó.

Đây là những gì tôi đã đưa ra:

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

Phải thừa nhận rằng, đây có thể là quá mức cần thiết.

0

Dưới đây là một cách thủ công hơn, nhưng ngắn hơn để làm điều đó:

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

Chú ý làm thế nào tôi đã phải tạo ra một StreamController vì vậy tôi có thể bơm các sự kiện để WebSocketTransformer