Friendly and scalable websocket server for applications
As mentioned in introduction page to connect browser to websocket server you need to do following steps:
import {ChannelStreamConnection} from '@channelstream/channelstream';
let connection = new ChannelStreamConnection();
// this points to your application view
connection.connectUrl = '/connect';
connection.messageUrl = '/message';
// this points to channelstream
connection.websocketUrl = 'ws://127.0.0.1:8000/ws';
connection.longPollUrl = 'http://127.0.0.1:8000/listen';
connection.listenMessageCallback = (messages) => {
for (let message of messages) {
console.log('channelstream message', message);
// Do something on message received
}
};
// optional
connection.listenOpenedCallback = () => {
// Do something on websocket opened
};
// this will try to obtain connection UUID from `connectUrl` endpoint of your WEB application via XHR call
// and then use it to make websocket connection
connection.connect();
We need to tell the server that user "someuser" connects to "/tutorial" channel.
Channelstream requires all API calls to be signed with a shared secret, the default implementation used is
TimestampSigner
from itsdangerous
package.
# python example
import requests
from itsdangerous import TimestampSigner
# create auth header for backend request
signer = TimestampSigner("secret")
sig_for_server = signer.sign("channelstream")
secret_headers = {
"x-channelstream-secret": sig_for_server,
"Content-Type": "application/json",
}
# connect user
payload = {
"username": "someuser",
"channels": ["/tutorial-1"]
}
response = requests.post("http://127.0.0.1:8000/connect", data=json.dumps(payload), headers=secret_headers)
response.json() # contains connection UUID
Notice how "channels_info" get updated when you subscribe new users/create new channels. If no actual websocket/long-polling connections are made by the clients those objects will get garbage collected.
{ "username": "someuser", "channels": ["/tutorial-1"] }
# python example
import requests
from itsdangerous import TimestampSigner
# create auth header for backend request
signer = TimestampSigner("secret")
sig_for_server = signer.sign("channelstream")
secret_headers = {
"x-channelstream-secret": sig_for_server,
"Content-Type": "application/json",
}
# send messages
payload = [
{
"user": "system",
"channel": "/tutorial-1",
"message": {
"text": "This can serve as notification",
"level": "warning"
}
}
]
response = requests.post("http://127.0.0.1:8000/connect", data=json.dumps(payload), headers=secret_headers)
If you open up index page you will see that the connection there did not receive the message sent here - this is because they are subscribed to different channels and this is determined securely on your application side. However if you open this page in multiple windows/browsers you will see everyone subscribed to this channel will receive the message.
[ { "user": "system", "channel": "/tutorial-1", "message": { "text": "This can serve as notification", "level": "warning" } } ]
Now that you know all the basics of application flow, you can explore demo implementations in Flask and Pyramid for inspiration.