Как я могу использовать shelf_web_socket для прослушивания запросов http и ws на одном и том же порту
https://pub.dartlang.org/packages/shelf_web_socket показывает этот пример
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_web_socket/shelf_web_socket.dart';
void main() {
var handler = webSocketHandler((webSocket) {
webSocket.listen((message) {
webSocket.add("echo $message");
});
});
shelf_io.serve(handler, 'localhost', 8080).then((server) {
print('Serving at ws://${server.address.host}:${server.port}');
});
}
Я хотел бы знать, как совместить это с инициализацией моего HTTP-сервера
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as sIo;
import 'package:shelf_auth/shelf_auth.dart' as sAuth;
import 'package:shelf_auth/src/authentication.dart' as sAuth2;
import 'package:option/option.dart';
import 'package:shelf_web_socket/shelf_web_socket.dart' as sWs;
...
var authMiddleware = sAuth.authenticate(
[new MyAuthenticator()],
sessionHandler: new sAuth.JwtSessionHandler('bla', 'blub', new UserLookup()),
allowHttp: true,
allowAnonymousAccess: false);
var handler = const shelf.Pipeline()
.addMiddleware(shelf.logRequests())
.addMiddleware(authMiddleware)
.addHandler(_handleHttpRequest);
// var wsHandler = sWs.webSocketHandler(_handleWebSocketConnect);
sIo.serve(handler, '0.0.0.0', servePort).then((server) {
_log.finest('Serving at http://${server.address.host}:${server.port}');
});
Что нужно сделать, чтобы wsHandler
вызывается для подключений WebSocket и handler
продолжает обрабатывать HTTP-запросы (если возможно, на одном и том же порту) и, если возможно, использует настроенную аутентификацию и управление сеансами.
Я пробовал это на другом порту, но с промежуточным программным обеспечением аутентификации / сеанса (не знаю, предполагается ли это использовать вместе)
var authMiddleware = sAuth.authenticate(
[new MyAuthenticator()],
sessionHandler: new sAuth.JwtSessionHandler('bla', 'blub', new UserLookup()),
allowHttp: true,
allowAnonymousAccess: false);
var handler = const shelf.Pipeline()
.addMiddleware(shelf.logRequests())
.addMiddleware(authMiddleware)
.addHandler(_handleHttpRequest);
sIo.serve(handler, '0.0.0.0', servePort).then((server) {
_log.finest('Serving at http://${server.address.host}:${server.port}');
});
var wsHandler = const shelf.Pipeline()
.addMiddleware(shelf.logRequests())
.addMiddleware(authMiddleware)
.addHandler(sWs.webSocketHandler(_handleWebSocketConnect));
sIo.serve(wsHandler, '0.0.0.0', servePort + 1).then((server) {
_log.finest('Serving at ws://${server.address.host}:${server.port}');
});
и получил
Illegal argument(s): webSocketHandler may only be used with a server that supports request hijacking.
1 ответ
На данный момент вашим корневым обработчиком является http-обработчик. Вам нужно настроить обработчик, который условно отправляет запросы обработчику ws или другому обработчику для ваших запросов http. Например
/ws -> ваш обработчик ws
/rest -> ваш другой обработчик
Самый простой способ сделать это - использовать роутер, например shel_route.
Однако кто-то недавно попробовал это и обнаружил ошибку на полке, которая остановила эту работу. Который, как вы заметили ниже, исправлен, но не объединен.
Как только проблема будет решена, вы сможете сделать
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_route/shelf_route.dart' as route;
import 'package:shelf_web_socket/shelf_web_socket.dart' as sWs;
import 'package:shelf_auth/shelf_auth.dart' as sAuth;
import 'dart:async';
import 'package:option/option.dart';
import 'package:shelf_exception_response/exception_response.dart';
void main(List<String> arguments) {
var authMiddleware = sAuth.authenticate(
[new MyAuthenticator()],
sessionHandler: new sAuth.JwtSessionHandler('bla', 'blub', new UserLookup()),
allowHttp: true,
allowAnonymousAccess: false);
var router = (route.router()
..get('/rest', _handleHttpRequest)
..get('/ws', sWs.webSocketHandler(_handleWebSocketConnect)));
var handler = const shelf.Pipeline()
.addMiddleware(exceptionResponse())
.addMiddleware(shelf.logRequests())
.addMiddleware(authMiddleware)
.addHandler(router.handler);
route.printRoutes(router);
io.serve(handler, '127.0.0.1', 8080).then((server) {
print('Serving at http://${server.address.host}:${server.port}');
});
}
Пока проблема не будет устранена, вы можете заменить router.handler на
var hackyRouterHandler = (shelf.Request request) {
var path = request.url.path;
if (path.startsWith('/rest')) {
return _handleHttpRequest(request);
}
else if (path.startsWith('/ws')) {
return sWs.webSocketHandler(_handleWebSocketConnect)(request);
}
else {
throw new NotFoundException();
}
};