Created
June 16, 2023 04:23
-
-
Save char101/edb6b46da01c1c26b4c72a76b49d3b3c to your computer and use it in GitHub Desktop.
Simple javascript - python rpc via websocket
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class RemoteService { | |
#id = 0; | |
#socket = null; | |
#queue = new Map(); | |
constructor(wsUrl) { | |
this.#socket = new WebSocket(wsUrl); | |
this.#socket.addEventListener('error', error => console.log('socket error: ', error)); | |
this.#socket.addEventListener('message', this._onMessage.bind(this)); | |
return new Promise((resolve, reject) => { | |
this.#socket.addEventListener('open', () => { | |
this._onOpen(resolve); | |
}); | |
}); | |
} | |
_send(msg) { | |
msg.id = ++this.#id; | |
if (this.#id === 2147483647) { | |
this.#id = 0; | |
} | |
this.#socket.send(JSON.stringify(msg)); | |
return new Promise((resolve, reject) => { | |
this.#queue.set(msg.id, [msg.cmd, resolve, reject]); | |
}); | |
} | |
async _onOpen(callback) { | |
const names = await this._send({cmd: 'list'}); | |
const send = this._send.bind(this); | |
for (const name of names) { | |
this[name] = new Proxy({}, { | |
get(target, prop, receiver) { | |
return (...args) => send({cmd: 'call', name, prop, args}); | |
} | |
}); | |
} | |
callback(this); | |
} | |
_onMessage(event) { | |
const data = JSON.parse(event.data); | |
const [cmd, resolve, reject] = this.#queue.get(data.id); | |
this.#queue.delete(data.id); | |
if (!data.err) { | |
resolve(data.data); | |
} else { | |
reject('remote exception: ' + data.err); | |
} | |
} | |
} | |
(async function() { | |
const remote = await new RemoteService('ws://127.0.0.1:3021'); | |
console.log(await remote.test.hello('world')); | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
import traceback | |
from websockets.server import serve | |
from yapic import json | |
class Test: | |
def hello(self, text): | |
return f'hello {text}' | |
services = { | |
'test': Test(), | |
} | |
async def handler(socket): | |
async for message in socket: | |
msg = json.loads(message) | |
err = None | |
match msg['cmd']: | |
case 'list': | |
data = list(services.keys()) | |
case 'call': | |
try: | |
data = getattr(services[msg['name']], msg['prop'])(*msg['args']) | |
except Exception as _err: | |
print(traceback.format_exc()) | |
err = str(_err) | |
await socket.send(json.dumps({ | |
'id': msg['id'], | |
'err': err, | |
'data': data, | |
})) | |
async def main(): | |
async with serve(handler, '127.0.0.1', 3021): | |
await asyncio.Future() | |
asyncio.run(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment