2013-02-27 3 views
6

(Sto usando la nuova versione di v2 di dart: io.)Come posso registrare più gestori per un HttpServer, in Dart?

Vorrei registrare più gestori per un HttpServer, in particolare un WebSocketTransformer e altri gestori arbitrari. Qualcosa del genere:

// pseudo-code 

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

Se # 1 corrisponde, quindi # 2 non viene testato e così via. Quindi, è avido.

Ho visto campioni con un solo gestore. Come posso registrare molti gestori? Grazie in anticipo!

risposta

3

Nuova risposta: utilizzare il pacchetto di percorso : http://pub.dartlang.org/packages/route

Ecco il vostro esempio utilizzando serve() il metodo di percorso:

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

Il router intercetta automaticamente le richieste non gestite e invia un 404, anche se presto sarà possibile sostituirlo con un defaultStream che è possibile ascoltare.

router supporta anche i filtri, utile per la registrazione, autenticazione, compressione, ecc .:

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

Questo è quello che stavo cercando, grazie! –

0

Ecco come il API docs consiglia di registrare un gestore WebSocket:

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

Tuttavia, il server è un flusso unico abbonamento. Una volta collegato a listen, non è possibile allegare altri listener.

Quello che voglio veramente è che qualcosa guardi un evento, decidi se è in grado di gestirlo, e in tal caso lo instrado su un altro stream. Altrimenti, passalo. In questo modo, l'evento (in questo caso un oggetto HttpRequest) viene passato lungo una catena finché non viene gestito.

Ho creato una classe TakeAndRoute che si estende StreamEventTransformer. Il TakeAndRoute utilizza una funzione per determinare se deve afferrare l'evento e instradarlo su un altro stream, o semplicemente inoltrarlo.

Ecco cosa mi è venuta:

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

Certo, questo potrebbe essere eccessivo.

0

Ecco un modo più manuale, ma più breve per farlo:

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

Notate come ho dovuto creare uno StreamController così ho potuto pompare eventi per WebSocketTransformer