Needs to be used with a Client, example: https://gist.github.com/xprilion/aec07a8878882b7b06c596c174fd8b5b
-
-
Save xprilion/ceab48ec77a70be1d403e396170991e6 to your computer and use it in GitHub Desktop.
| #!/usr/bin/env python | |
| # WS server example that synchronizes state across clients | |
| import asyncio | |
| import json | |
| import logging | |
| import websockets | |
| import ssl | |
| logging.basicConfig() | |
| ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) | |
| # Generate with Lets Encrypt, copied to this location, chown to current user and 400 permissions | |
| ssl_cert = "/home/username/fullchain.pem" | |
| ssl_key = "/home/username/privkey.pem" | |
| ssl_context.load_cert_chain(ssl_cert, keyfile=ssl_key) | |
| STATE = {"value": 0} | |
| USERS = set() | |
| def state_event(): | |
| return json.dumps({"type": "state", **STATE}) | |
| def users_event(): | |
| return json.dumps({"type": "users", "count": len(USERS)}) | |
| async def notify_state(): | |
| if USERS: # asyncio.wait doesn't accept an empty list | |
| message = state_event() | |
| await asyncio.wait([user.send(message) for user in USERS]) | |
| async def notify_users(): | |
| if USERS: # asyncio.wait doesn't accept an empty list | |
| message = users_event() | |
| await asyncio.wait([user.send(message) for user in USERS]) | |
| async def register(websocket): | |
| USERS.add(websocket) | |
| await notify_users() | |
| async def unregister(websocket): | |
| USERS.remove(websocket) | |
| await notify_users() | |
| async def counter(websocket, path): | |
| # register(websocket) sends user_event() to websocket | |
| await register(websocket) | |
| try: | |
| await websocket.send(state_event()) | |
| async for message in websocket: | |
| data = json.loads(message) | |
| if data["action"] == "minus": | |
| STATE["value"] -= 1 | |
| await notify_state() | |
| elif data["action"] == "plus": | |
| STATE["value"] += 1 | |
| await notify_state() | |
| else: | |
| logging.error("unsupported event: {}", data) | |
| finally: | |
| await unregister(websocket) | |
| start_server = websockets.serve(counter, "0.0.0.0", 6789, ssl=ssl_context) | |
| asyncio.get_event_loop().run_until_complete(start_server) | |
| asyncio.get_event_loop().run_forever() |
Thanks! 😃
Published a blog that discusses this gist in more detail here - https://xprilion.com/python-websockets-ssl-with-lets-encrypt/
Published a blog that discusses this gist in more detail here - https://xprilion.com/python-websockets-ssl-with-lets-encrypt/
Dude. Great blog. Thanks a ton, super useful stuff especially with the chmod examples
Thanks for the feedback @vuolo, your comment earlier today encouraged me to work on the blog! 😃 I figured the way I had written it initially was slightly tough to follow for folks who were doing socket SSL setup for the first time.
hi @xprilion ,
i launched the example on my local machine on port 12088 (... start_server = websockets.serve(counter, "0.0.0.0", 12088, ssl=ssl_context) ...)
i tested it from chrome browser from Developer tools->console :
try {
let s = new WebSocket('wss://127.0.0.1:12088');
s.onerror = e =>{console.error('onerror!!!', e)}
s.onopen = r => {
console.debug('onopen', r)
}
} catch (e) {
console.error('EEERRR', e)
}
console result:
VM132:2 WebSocket connection to 'wss://127.0.0.1:12088/' failed:
(anonymous) @ VM132:2
VM132:3 onerror!!! Event {isTrusted: true, type: 'error', target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
as you can see it doesn't work. but if i launch the server script without ssl parameter (... start_server = websockets.serve(counter, "0.0.0.0", 12088...) it works:
try {
let s = new WebSocket('ws://127.0.0.1:12088');
s.onerror = e =>{console.error('onerror!!!', e)}
s.onopen = r => {
console.debug('onopen', r)
}
} catch (e) {
console.error('EEERRR', e)
}
result:
onopen Event {isTrusted: true, type: 'open', target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
also, no any external web server is launched on my machine.
any suggestions?
thanks in advance
Awesome example of a secure websocket!
Thank you so much @xprilion!
how about if python is the client?
I wonder if any special configuration is needed to use python as a client for a websocket, maybe you can generate one easily using any GPT tools? Do let me know if that doesn't work for you.
This was extremely helpful, thank you!