Combine Server and Client WebSocket. - Autobahn and Twisted

#1

Hello,

i am developing a code that will do the following :

Chat UI html & JS <–> Python (Server & Client) <–> Server Chat API

could you please give me a clue on how to pass thru the message from Chat UI to Server Chat API

and vice versa.

here’s the code that we try, i think it migth be wrong.

import logging

import pprint

import json

import random

from twisted.python import log

from twisted.internet import reactor, ssl

from stompest.protocol import commands, StompFrame, StompSpec

from autobahn.twisted.websocket import WebSocketClientFactory,

WebSocketClientProtocol,

connectWS, WebSocketServerProtocol, WebSocketServerFactory, listenWS

from basicauth import encode

RECEIVE_CHANNEL = “/user/chat.receive”

SEND_CHANNEL = “/chat/chat.send”

CHAT_API_WS_URL=“wss://xxxxxxxx/xxxx/websocket”

CHAT_API_USERNAME=“xxxx-test”

CHAT_API_PASSWORD=“password”

encoded_str = encode(CHAT_API_USERNAME, CHAT_API_PASSWORD)

headers = {

‘Authorization’: encoded_str

}

Connect Message

connect_message = {

“type” : “CONNECT”,

“from” : “csantoso”,

“serviceUuid”: “6b6e5fda-ed70-44df-baf3-109d3892c20f”,

“commandId”: 1,

“customData”: {

“userDefined12”: “companyCode”,

“userDefined13”: “em…@example.com”,

“userDefined15”: “ticketReference”


}

}

json_connect_message = json.dumps(connect_message)

class MyServerProtocol(WebSocketServerProtocol):


def onConnect(self, request):

print("=========  MyServerProtocol :: onConnect =========")

print("MyServerProtocol :: server Client connecting: {0}".format(request.peer))

factory = WebSocketClientFactory(CHAT_API_WS_URL, headers = headers)

factory.protocol = MyClientProtocol

if factory.isSecure:

print("setting up SSL")

contextFactory = ssl.ClientContextFactory()

else:

contextFactory = None

connectWS(factory, contextFactory)

self.client = MyClientProtocol()

def onOpen(self):

print("=========  MyServerProtocol :: onOpen =========")

print("server WebSocket connection open.")

payload = self.client.onOpen

def onMessage(self, payload, isBinary):

print("=========  MyServerProtocol :: onMessage =========")

if isBinary:

print("server Binary message received: {0} bytes".format(len(payload)))

else:

print("server Text message received: {0}".format(payload.decode('utf8')))

# messageFrame = commands.send(SEND_CHANNEL, body=bytes(json_connect_message, "utf-8"))

# self.client.sendMessage(bytes(messageFrame))

# self.sendMessage(self.client.onMessage, isBinary)

def onClose(self, wasClean, code, reason):

print("=========  MyServerProtocol :: onClose =========")

print("server WebSocket connection closed: {0}".format(reason))

class MyClientProtocol(WebSocketClientProtocol):


def onConnect(self, response):

print("=========  MyClientProtocol :: onConnect =========")

print("MyClientProtocol :: Server connected: {0}".format(response.peer))

def onOpen(self):

print("=========  MyClientProtocol :: onOpen =========")

print("MyClientProtocol :: WebSocket connection open.")

# Create a connect frame

connectStompFrame = commands.connect(login=None, passcode=None, headers=None, versions=None, host=None, heartBeats=None)

print("MyClientProtocol :: connectMsg 1:\n%s\n" % pprint.pformat(connectStompFrame))

self.sendMessage(bytes(connectStompFrame))

# Subscribe

def subscribe_call():

print("MyClientProtocol :: Subscribing...")

v = str(random.randint(0, 1000))

subscribeStompFrame, token = commands.subscribe(RECEIVE_CHANNEL, { "id": v})

self.sendMessage(bytes(subscribeStompFrame))

# Subscribe

# def connect_call():

#     print("Sending Connect message...")

#     print("connectMsg 2:\n%s\n" % str(bytes(json_connect_message, "utf-8")))

#     messageFrame = commands.send(SEND_CHANNEL, body=bytes(json_connect_message, "utf-8"))

#     self.sendMessage(bytes(messageFrame))

# def hello():

#     self.sendMessage(u"Hello, world!".encode('utf8'))

#     self.sendMessage(b"\x00\x01\x03\x04", isBinary=True)

#     self.factory.reactor.callLater(4, hello)

# start sending messages every second ..

reactor.callLater(1, subscribe_call)

# reactor.callLater(3, connect_call)

# hello()

def onSend(self, json_connect_message):

messageFrame = commands.send(SEND_CHANNEL, body=bytes(json_connect_message, "utf-8"))

self.sendMessage(bytes(messageFrame))

def onMessage(self, payload, isBinary):

print("=========  MyClientProtocol :: onMessage =========")

print("::::: payload :::: ",payload)

if isBinary:

print("MyClientProtocol :: Text message received : payload : ",payload)

print("MyClientProtocol :: Binary message received: {0} bytes".format(len(payload)))

else:

print("MyClientProtocol :: Text message received :: start process")

print("MyClientProtocol :: Text message received: {0}".format(payload.decode('utf8')))

if payload.decode('utf-8').startswith("CONNECTED"):

return payload

# self.sendMessage(payload, isBinary)

# print("MyClientProtocol :: Connected!")

def onClose(self, wasClean, code, reason):

print("=========  MyClientProtocol :: onClose =========")

print("MyClientProtocol :: WebSocket connection closed: {0}".format(reason))

if name == ‘main’:


import sys

from twisted.python import log

from twisted.internet import reactor

log.startLogging(sys.stdout)

serverFactory = WebSocketServerFactory(u"ws://127.0.0.1:9000")

serverFactory.protocol = MyServerProtocol

listenWS(serverFactory)

reactor.run()

0 Likes

#2

Hello,

i am developing a code that will do the following :

Chat UI html & JS <–> Python (Server & Client) <–> Server Chat API

could you please give me a clue on how to pass thru the message from Chat UI to Server Chat API

and vice versa.

here’s the code that we try, i think it migth be wrong.

import logging

import pprint

import json

import random

from twisted.python import log

from twisted.internet import reactor, ssl

from stompest.protocol import commands, StompFrame, StompSpec

from autobahn.twisted.websocket import WebSocketClientFactory,

WebSocketClientProtocol,

connectWS, WebSocketServerProtocol, WebSocketServerFactory, listenWS

from basicauth import encode

RECEIVE_CHANNEL = “/user/chat.receive”

SEND_CHANNEL = “/chat/chat.send”

CHAT_API_WS_URL=“wss://xxxxxxxx/xxxx/websocket”

CHAT_API_USERNAME=“xxxx-test”

CHAT_API_PASSWORD=“password”

encoded_str = encode(CHAT_API_USERNAME, CHAT_API_PASSWORD)

headers = {

‘Authorization’: encoded_str

}

Connect Message

connect_message = {

“type” : “CONNECT”,

“from” : “csantoso”,

“serviceUuid”: “6b6e5fda-ed70-44df-baf3-109d3892c20f”,

“commandId”: 1,

“customData”: {

“userDefined12”: “companyCode”,

“userDefined13”: “em…@example.com”,

“userDefined15”: “ticketReference”

}

}

json_connect_message = json.dumps(connect_message)

class MyServerProtocol(WebSocketServerProtocol):

def onConnect(self, request):

print("========= MyServerProtocol :: onConnect =========")

print(“MyServerProtocol :: server Client connecting: {0}”.format(request.peer))

factory = WebSocketClientFactory(CHAT_API_WS_URL, headers = headers)

factory.protocol = MyClientProtocol

if factory.isSecure:

print(“setting up SSL”)

contextFactory = ssl.ClientContextFactory()

else:

contextFactory = None

connectWS(factory, contextFactory)

self.client = MyClientProtocol()

def onOpen(self):

print("========= MyServerProtocol :: onOpen =========")

print(“server WebSocket connection open.”)

payload = self.client.onOpen

def onMessage(self, payload, isBinary):

print("========= MyServerProtocol :: onMessage =========")

if isBinary:

print(“server Binary message received: {0} bytes”.format(len(payload)))

else:

print(“server Text message received: {0}”.format(payload.decode(‘utf8’)))

messageFrame = commands.send(SEND_CHANNEL, body=bytes(json_connect_message, “utf-8”))

self.client.sendMessage(bytes(messageFrame))

self.sendMessage(self.client.onMessage, isBinary)

def onClose(self, wasClean, code, reason):

print("========= MyServerProtocol :: onClose =========")

print(“server WebSocket connection closed: {0}”.format(reason))

class MyClientProtocol(WebSocketClientProtocol):

def onConnect(self, response):

print("========= MyClientProtocol :: onConnect =========")

print(“MyClientProtocol :: Server connected: {0}”.format(response.peer))

def onOpen(self):

print("========= MyClientProtocol :: onOpen =========")

print(“MyClientProtocol :: WebSocket connection open.”)

Create a connect frame

connectStompFrame = commands.connect(login=None, passcode=None, headers=None, versions=None, host=None, heartBeats=None)

print(“MyClientProtocol :: connectMsg 1:\n%s\n” % pprint.pformat(connectStompFrame))

self.sendMessage(bytes(connectStompFrame))

Subscribe

def subscribe_call():

print(“MyClientProtocol :: Subscribing…”)

v = str(random.randint(0, 1000))

subscribeStompFrame, token = commands.subscribe(RECEIVE_CHANNEL, { “id”: v})

self.sendMessage(bytes(subscribeStompFrame))

Subscribe

def connect_call():

print(“Sending Connect message…”)

print(“connectMsg 2:\n%s\n” % str(bytes(json_connect_message, “utf-8”)))

messageFrame = commands.send(SEND_CHANNEL, body=bytes(json_connect_message, “utf-8”))

self.sendMessage(bytes(messageFrame))

def hello():

self.sendMessage(u"Hello, world!".encode(‘utf8’))

self.sendMessage(b"\x00\x01\x03\x04", isBinary=True)

self.factory.reactor.callLater(4, hello)

start sending messages every second …

reactor.callLater(1, subscribe_call)

reactor.callLater(3, connect_call)

hello()

def onSend(self, json_connect_message):

messageFrame = commands.send(SEND_CHANNEL, body=bytes(json_connect_message, “utf-8”))

self.sendMessage(bytes(messageFrame))

def onMessage(self, payload, isBinary):

print("========= MyClientProtocol :: onMessage =========")

print("::::: payload :::: ",payload)

if isBinary:

print("MyClientProtocol :: Text message received : payload : ",payload)

print(“MyClientProtocol :: Binary message received: {0} bytes”.format(len(payload)))

else:

print(“MyClientProtocol :: Text message received :: start process”)

print(“MyClientProtocol :: Text message received: {0}”.format(payload.decode(‘utf8’)))

if payload.decode(‘utf-8’).startswith(“CONNECTED”):

return payload

self.sendMessage(payload, isBinary)

print(“MyClientProtocol :: Connected!”)

def onClose(self, wasClean, code, reason):

print("========= MyClientProtocol :: onClose =========")

print(“MyClientProtocol :: WebSocket connection closed: {0}”.format(reason))

if name == ‘main’:

import sys

from twisted.python import log

from twisted.internet import reactor

log.startLogging(sys.stdout)

serverFactory = WebSocketServerFactory(u"ws://127.0.0.1:9000")

serverFactory.protocol = MyServerProtocol

listenWS(serverFactory)

reactor.run()

···

On Wednesday, February 13, 2019 at 5:52:31 PM UTC+7, Christian C.S wrote:

0 Likes

#3

Hi Christian,

Can you elaborate what are you trying to do?

If you want a client (publisher) to send message to multiple servers (subscribes on WAMP) - then just publish a message. If your " Python (Server & Client)" needs to works a proxy/middleware to “Server Chat API”, then they have to use separate topics - you receive message in Python, do whatever is required and then forward it to “Server Chat API”.

···

Zaar

0 Likes

#4

Hello Zaar Hai,

sorry for being unclear but you are correct that what we are trying to do is the “Python (server & Client)” need to works as proxy/middleware to the “Server Chat API”.

What do you mean separate topics?

because currently, i am pretty confuse how to create this proxy/middleware.

thanks,

Christian.

···

On Thursday, February 14, 2019 at 9:11:18 AM UTC+7, Zaar Hai wrote:

Hi Christian,

Can you elaborate what are you trying to do?

If you want a client (publisher) to send message to multiple servers (subscribes on WAMP) - then just publish a message. If your " Python (Server & Client)" needs to works a proxy/middleware to “Server Chat API”, then they have to use separate topics - you receive message in Python, do whatever is required and then forward it to “Server Chat API”.

On Thu, 14 Feb 2019 at 12:32, Christian C.S chris...@gmail.com wrote:

On Wednesday, February 13, 2019 at 5:52:31 PM UTC+7, Christian C.S wrote:

Hello,

i am developing a code that will do the following :

Chat UI html & JS <–> Python (Server & Client) <–> Server Chat API

could you please give me a clue on how to pass thru the message from Chat UI to Server Chat API

and vice versa.

here’s the code that we try, i think it migth be wrong.

import logging

import pprint

import json

import random

from twisted.python import log

from twisted.internet import reactor, ssl

from stompest.protocol import commands, StompFrame, StompSpec

from autobahn.twisted.websocket import WebSocketClientFactory,

WebSocketClientProtocol,

connectWS, WebSocketServerProtocol, WebSocketServerFactory, listenWS

from basicauth import encode

RECEIVE_CHANNEL = “/user/chat.receive”

SEND_CHANNEL = “/chat/chat.send”

CHAT_API_WS_URL=“wss://xxxxxxxx/xxxx/websocket”

CHAT_API_USERNAME=“xxxx-test”

CHAT_API_PASSWORD=“password”

encoded_str = encode(CHAT_API_USERNAME, CHAT_API_PASSWORD)

headers = {

‘Authorization’: encoded_str

}

Connect Message

connect_message = {

“type” : “CONNECT”,

“from” : “csantoso”,

“serviceUuid”: “6b6e5fda-ed70-44df-baf3-109d3892c20f”,

“commandId”: 1,

“customData”: {

“userDefined12”: “companyCode”,

“userDefined13”: “em…@example.com”,

“userDefined15”: “ticketReference”

}

}

json_connect_message = json.dumps(connect_message)

class MyServerProtocol(WebSocketServerProtocol):

def onConnect(self, request):

print("========= MyServerProtocol :: onConnect =========")

print(“MyServerProtocol :: server Client connecting: {0}”.format(request.peer))

factory = WebSocketClientFactory(CHAT_API_WS_URL, headers = headers)

factory.protocol = MyClientProtocol

if factory.isSecure:

print(“setting up SSL”)

contextFactory = ssl.ClientContextFactory()

else:

contextFactory = None

connectWS(factory, contextFactory)

self.client = MyClientProtocol()

def onOpen(self):

print("========= MyServerProtocol :: onOpen =========")

print(“server WebSocket connection open.”)

payload = self.client.onOpen

def onMessage(self, payload, isBinary):

print("========= MyServerProtocol :: onMessage =========")

if isBinary:

print(“server Binary message received: {0} bytes”.format(len(payload)))

else:

print(“server Text message received: {0}”.format(payload.decode(‘utf8’)))

messageFrame = commands.send(SEND_CHANNEL, body=bytes(json_connect_message, “utf-8”))

self.client.sendMessage(bytes(messageFrame))

self.sendMessage(self.client.onMessage, isBinary)

def onClose(self, wasClean, code, reason):

print("========= MyServerProtocol :: onClose =========")

print(“server WebSocket connection closed: {0}”.format(reason))

class MyClientProtocol(WebSocketClientProtocol):

def onConnect(self, response):

print("========= MyClientProtocol :: onConnect =========")

print(“MyClientProtocol :: Server connected: {0}”.format(response.peer))

def onOpen(self):

print("========= MyClientProtocol :: onOpen =========")

print(“MyClientProtocol :: WebSocket connection open.”)

Create a connect frame

connectStompFrame = commands.connect(login=None, passcode=None, headers=None, versions=None, host=None, heartBeats=None)

print(“MyClientProtocol :: connectMsg 1:\n%s\n” % pprint.pformat(connectStompFrame))

self.sendMessage(bytes(connectStompFrame))

Subscribe

def subscribe_call():

print(“MyClientProtocol :: Subscribing…”)

v = str(random.randint(0, 1000))

subscribeStompFrame, token = commands.subscribe(RECEIVE_CHANNEL, { “id”: v})

self.sendMessage(bytes(subscribeStompFrame))

Subscribe

def connect_call():

print(“Sending Connect message…”)

print(“connectMsg 2:\n%s\n” % str(bytes(json_connect_message, “utf-8”)))

messageFrame = commands.send(SEND_CHANNEL, body=bytes(json_connect_message, “utf-8”))

self.sendMessage(bytes(messageFrame))

def hello():

self.sendMessage(u"Hello, world!".encode(‘utf8’))

self.sendMessage(b"\x00\x01\x03\x04", isBinary=True)

self.factory.reactor.callLater(4, hello)

start sending messages every second …

reactor.callLater(1, subscribe_call)

reactor.callLater(3, connect_call)

hello()

def onSend(self, json_connect_message):

messageFrame = commands.send(SEND_CHANNEL, body=bytes(json_connect_message, “utf-8”))

self.sendMessage(bytes(messageFrame))

def onMessage(self, payload, isBinary):

print("========= MyClientProtocol :: onMessage =========")

print("::::: payload :::: ",payload)

if isBinary:

print("MyClientProtocol :: Text message received : payload : ",payload)

print(“MyClientProtocol :: Binary message received: {0} bytes”.format(len(payload)))

else:

print(“MyClientProtocol :: Text message received :: start process”)

print(“MyClientProtocol :: Text message received: {0}”.format(payload.decode(‘utf8’)))

if payload.decode(‘utf-8’).startswith(“CONNECTED”):

return payload

self.sendMessage(payload, isBinary)

print(“MyClientProtocol :: Connected!”)

def onClose(self, wasClean, code, reason):

print("========= MyClientProtocol :: onClose =========")

print(“MyClientProtocol :: WebSocket connection closed: {0}”.format(reason))

if name == ‘main’:

import sys

from twisted.python import log

from twisted.internet import reactor

log.startLogging(sys.stdout)

serverFactory = WebSocketServerFactory(u"ws://127.0.0.1:9000")

serverFactory.protocol = MyServerProtocol

listenWS(serverFactory)

reactor.run()

You received this message because you are subscribed to the Google Groups “Autobahn” group.

To unsubscribe from this group and stop receiving emails from it, send an email to autobahnws+...@googlegroups.com.

To post to this group, send email to auto...@googlegroups.com.

To view this discussion on the web visit https://groups.google.com/d/msgid/autobahnws/ee41aef7-6526-4c5a-bf07-5d0fa1e23457%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


Zaar

0 Likes

#5

Suppose you are using pub/sub for communication. You need to have two uris - uri:a and uri:b. Browser only publishes/subscribes to uri:a. Server only publishes/subscribes to uri:b. Python server works with both and forwards messages - e.g. while handling on_event() from subscription on uri:a it publishes the messages to uri:b.

Hope this helps,

Zaar

P.S. Have you had a chance to watch this presentation? https://crossbario.com/static/presentations/microservices/#/

May be it can help to figure out how do want to use WAMP.

···

Zaar

0 Likes

#6

Thanks again Zaar...
actually that’s the idea.

would you be able to suggest?
how to make the python subs/pubs to both uri?

because currently, we initialize
websocketclientfactory
and make connectWS 2 times.
one to uri a and 2nd one to uri b.

but it seems that we can’t pass the publish to each others

thanks again for the help

0 Likes