0
votes

Does inbuilt WebSocket API in WSO2 APIM manager supports socket.io/nodejs based endpoint?

I have socket.io based websocket server (in NodeJS) And socket.io javascript client, in between we are using WSO2 API manager for authenticating websocket connections. But WSO2 fails to connect backend server and gives nothing in response. I used access_token query parameter for passing Bearer token (from JavaScript client) and it seems working as no error. But WSO2 does not forward requests to endpoint.

Same works fine with native WebSocket server-client.

3
could be due to the header mismatch. Is there any errors in the console?ruks

3 Answers

1
votes

You can add the following logs to <AM_HOME>/repository/conf/log4j.properties to debug the issue further. For APIM 3.x.x you can change it according to the log4j2 and add to log4j2.properties

log4j.logger.org.wso2.carbon.inbound.endpoint.protocol.websocket.InboundWebsocketSourceHandler=DEBUG log4j.logger.org.wso2.carbon.inbound.endpoint.protocol.websocket.InboundWebsocketResponseSender=DEBUG 
log4j.logger.org.wso2.carbon.websocket.transport.WebSocketClientHandler=DEBUG 
log4j.logger.org.wso2.carbon.websocket.transport.WebsocketTransportSender=DEBUG
0
votes

Previous answer was for socket.io JS client, here is the same hack for socket.io python client.

Modify client.py file from /home/user/.local/lib/python3.6/site-packages/engineio

line no. 515

change this,

return ('{scheme}://{netloc}/{path}/?{query}'
                    '{sep}transport={transport}&EIO=3').format(...

to this,

return ('{scheme}://{netloc}/{path}?{query}'
                        '{sep}transport={transport}&EIO=3').format(...

Now, instead of directly modifying actual flow we can use conditional parameter.

if self.noslash == 'true':
            return ('{scheme}://{netloc}/{path}?{query}'
                    '{sep}transport={transport}&EIO=3').format(...

else return original statement.

noslash parameter can be fetched from connect() function in both engineio and socketio library of python.

def connect(self, url, headers={}, transports=None,
                engineio_path='engine.io', noslash=None):
       self.noslash = noslash

Here is the sample connection string for python-socketio

sio.connect('http://localhost:9099', headers={'Authorization':'Bearer 90e8sf10-3s1w-495f-b20d-5a009f63193v'}, transports=['websocket'], socketio_path='/livefeed/v1', noslash='true')
0
votes

finally I get rid of this issue. Yes, WSO2 APIM websocket supports socket.io js library that will be the first answer to my own query. More on that, here are some findings.

The actual reason for issue was request URL pattern used by socket.io library and WSO2 APIM. Socket.io JS library make the final URL with / at the end of resource (reference), which is not accepted by query separation logic used by WSO2.

So in simple, this is acceptable

ws://localhost:9099/livefeed/v1?EIO=4&transport=websocket

but not this,

ws://localhost:9099/livefeed/v1/?EIO=4&transport=websocket

Solution:

After few discussions with WSO2 team, it was clear that it is impossible to implement changes at their end. So little hack in socket.io.js file worked for me.

line number - 2535

changed this,

_this.opts.path = _this.opts.path.replace(/\/$/, "") + "/";

to this,

if(typeof opts.noslash!== 'undefined' && opts.noslash== "true"){
    _this.opts.path = _this.opts.path.replace(/\/$/, "");
}else{
   _this.opts.path = _this.opts.path.replace(/\/$/, "") + "/";
}

and created socket using extra argument.

 var socket = io.connect("http://localhost:9099?access_token=90e8sf10-3s1w-495f-b20d-5a009f63193v", { transports: ['websocket', 'polling'], path: '/livefeed/v1', noslash: 'true' });

I know this is not a actual solution, but it worked for me.