https://pub.dartlang.org/packages/shelf_web_socket shows this example
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}');
});
}
I would like to know how to combine this with my HTTP server initialization
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}');
});
What needs to be done so that wsHandler
gets called for WebSocket connects and handler
keeps handling HTTP requests (if possible on the same port) and if possible uses the configured authentication and session management.
I tried it on a different port but with the authentication/session middleware (no idea if this is supposed to be used together)
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}');
});
and got
Illegal argument(s): webSocketHandler may only be used with a server that supports request hijacking.
By default, a single server can handle 65,536 socket connections just because it's the max number of TCP ports available.
WebSockets - Overview In computer science, handshaking is a process that ensures the server is in sync with its clients. Handshaking is the basic concept of Web Socket protocol. The following diagram shows the server handshake with various clients −
By default the WebSocket protocol uses port 80 for regular WebSocket connections and port 443 for WebSocket connections tunneled over TLS [RFC2818].
No. The server can't initiate a connection.
At the moment your root handler is the http handler. You'll need to set up a handler that conditionally sends requests to the ws handler or another handler for your http requests. Eg
/ws -> your ws handler
/rest -> your other handler
The easiest way to do that is to use a router like shelf_route.
However someone recently tried this and hit a bug in shelf that stopped this working. Which as you noted below is fixed but not merged.
Once the issue is fixed you should be able to do
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}');
});
}
Until the issue is fixed you can replace the router.handler with
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();
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With