Dart/Flutter WebSocket server/client is not working properly in the same side

3,778

i solved the issue. It seems in AuthorizationController(first code part) where i send the data to websocket i need to apply json encoding to the data.

channel.sink.add(json.encode(map));
Share:
3,778
Kadir Akin
Author by

Kadir Akin

Updated on December 22, 2022

Comments

  • Kadir Akin
    Kadir Akin over 1 year

    im trying to develop an oauth2 demo for my interests. In the demo when user hit authorization server, authorization server return to me with the redirect url. In my server i reserved an endpoint for this redirect url. In this endpoint i take request's queryparameters and i connect to a websocket via web_socket_channel . After connection i send the query paramater data to web socket. Below i'll add the implementation.

    import 'package:aqueduct/aqueduct.dart';
    import 'package:web_socket_channel/web_socket_channel.dart' as ws;
    class AuthorizationController extends ResourceController{
      static final uri = Uri(scheme: 'ws',host: 'localhost',pathSegments: ['connect'],port: 8888);
    
      @Operation.get()
      Future<Response> manageRedirection()async{
        Map<String,dynamic> map = request.raw.uri.queryParameters;
        sendToWs(map);
        return Response.ok(map.toString());
      }
    
      void sendToWs(Map<String,dynamic> map){
        final channel =ws.WebSocketChannel.connect(uri);
        print("AuthorizationController: data -> $map");
        channel.sink.add(map);
      }
    }
    

    Now in the server side(http server's /connect endpoint reserved for this) i upgrade incoming requests and i create a WebSocketClient instance and add that instance to a list. Below i'll show the upgrading part and WebSocketClient class

    List<WebsocketClient> clients =  [];
    
    class Oauth2demoserverChannel extends ApplicationChannel {
      @override
      Future prepare() async {
        logger.onRecord.listen((rec) => print("$rec ${rec.error ?? ""} ${rec.stackTrace ?? ""}"));
    
      }
      @override
      Controller get entryPoint {
        final router = Router();
    
        router
          .route("/redirection")
          .link(() => AuthorizationController());
    
        router
          .route("/connect")
          .linkFunction((request) async {
            void handleWebSocket(WebSocket webSocket){
              var newC = WebsocketClient(webSocket);
              clients.add(newC);
              print("clients map:${clients.asMap()}");
            }
            // ignore: close_sinks
            // ignore: unused_local_variable
            final socket = await WebSocketTransformer.upgrade(request.raw)
              .then(handleWebSocket);
          return null;
          });
        return router;
      }
    }
    

    Above part is about Dart Aqueduct framework and its routing. I reserved /redirection end point for authorize server's redirection job. I get the data on that endpoint and as we can see at the first code part i connect myself to ws://localhost:8888/connect and add data.

    Now i'll show you about these WebSocketClientClass. This class takes an websocket instance at constructor and starts listening. When the message arrives; messageHandlertakes all web socket clients in the list and broadcasts the message.

    import 'package:oauth2demoserver/oauth2demoserver.dart';
    import 'package:oauth2demoserver/channel.dart' as ch;
    
    class WebsocketClient{
      WebsocketClient(WebSocket ws){
        _webSocket = ws;
        
    
        _webSocket.listen(messageHandler,onError: errorHandler,onDone: finishHandler);
      }
      WebSocket _webSocket;
    
      void messageHandler(dynamic data){
        for(WebsocketClient wsc in ch.clients){
          if( wsc != this){
            wsc._webSocket.add(data);
          }
    
        }
      }
    
      void errorHandler(error){
        print("err");
        _webSocket.close();
      }
    
      void finishHandler(){
        print("finished");
        _webSocket.close();
      }
    }
    

    Now in the other hand i have an seperate Flutter application. In that application i connect to the ws://localhost:8888/connect and i can listen or add something and in the server WebSocketClient can handle message and broadcast it. But when i try to hit http://localhost:8888/redirection with some query parameter, freshly created WebSocketClient instance for that redirection doesn't enter the messageHandler function and it goes onDone .Because of these message never goes any channel. I wonder why this is happening, any idea? I'll add a picture that show reaction against get call to /redirection end point. /redirection end point takes the query parameters end sends to web socket server for broadcating but it is not as we can see in this picture

    note: i also tried another package for connection in /redirect endpoint, with that client it was giving error code 1005, it may be helpful.

    edit: i also tried with javascript and python web socket server. So there is no problem with the server configurations as it seems. I guess there is a little trick about http server. Still waiting for an help, thanks.