远程调用任意JS函数 HTTP server 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 import timefrom flask import Flask, requestimport loggingimport jsonfrom websocket_server import WebsocketServerimport threadingimport uuiddef recv_message (client, server, message ): print (message) try : d = json.loads(message) _id = d.get('id' ) data = d.get('data' ) CACHE[_id ] = data except Exception as e: print (e) pass CACHE = {} app = Flask(__name__) server = WebsocketServer(host='127.0.0.1' , port=10086 , loglevel=logging.INFO) server.set_fn_message_received(recv_message)class MyThread (threading.Thread ): def __init__ (self ): threading.Thread.__init__(self) def run (self ): server.run_forever()@app.route("/" ) def index (): data = request.args.get('data' ) func_name = request.args.get('func_name' ) if not data: return "Hello, World!" _id = uuid.uuid4().hex d = {'data' : data, "func_name" : func_name, "id" : _id } msg = json.dumps(d) print (msg) try : client = server.clients[-1 ] except Exception as e: client = None if not client: return 'Not connected!' server.send_message(client, msg) ts = time.time() while True : time.sleep(0.1 ) data = CACHE.get(_id ) if data: del (CACHE[_id ]) return data if time.time() - ts > 5 : break return 'OK' if __name__ == '__main__' : t = MyThread() t.start() app.run('0.0.0.0' , 9999 , debug=False )
Another html page: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <script src ="crypto-js.min.js" > </script > <script > var key = CryptoJS.enc.Utf8.parse('1111111111111111' ); var iv = CryptoJS.enc.Utf8.parse('0000000000000000' ); function test_encrypt (s ) { var input = CryptoJS.enc.Utf8.parse(s); encrypted = CryptoJS.AES.encrypt(input, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) return encrypted.ciphertext.toString(CryptoJS.enc.Base64) } function test_decrypt (s ) { decrypted = CryptoJS.AES.decrypt(s, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) return decrypted.toString(CryptoJS.enc.Utf8) }</script >
Run js in console:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 const ws = new WebSocket("ws://localhost:10086/" ); ws.onopen = function ( ) { console .log("WebSocket Client Connected" ); }; ws.onmessage = function (e ) { console .log(e) var obj = JSON .parse(e.data) var func_name = obj.func_name var data = obj.data var id = obj.id if (func_name === "test_encrypt" ) { var result = test_encrypt(data) var msg = JSON .stringify({ 'id' : id, 'data' : result }) ws.send(msg) } if (func_name === "test_decrypt" ) { var result = test_decrypt(data) var msg = JSON .stringify({ 'id' : id, 'data' : result }) ws.send(msg) } };
远程调用: http ://localhost:9999 /?data=2222 &func_name=test_encrypthttp ://localhost:9999 /?data=vctKhKpbboUox82 pkoqx%2 Bg%3 D%3 D&func_name=test_decrypt
2023-7-1 更新 Python的websocket在实际使用中存在比较慢的情况。于是尝试进行优化。
使用nodejs的ws库创建一个websocket server,将所有收到的消息广播出来,python端则不再需要http server,直接发送、接收websocket消息即可。
https://gi thub.com/websockets/ ws
配置环境:
npm install ws npm install babel-cli -g npm install babel-preset-env -D
ws_server.js:
import WebSocket, { WebSocketServer } from 'ws' ;const wss = new WebSocketServer({ port : 3000 }); wss.on('connection' , function connection (ws ) { ws.on('error' , console .error); ws.on('message' , function message (data, isBinary ) { wss.clients.forEach(function each (client ) { if (client !== ws && client.readyState === WebSocket.OPEN) { client.send(data, { binary : isBinary }); } }); }); });
启动websocket服务:
babel-node --presets env ws_server.js
Python端:
def test (data ): signstr = '' d = {"data" : data, "func_name" : "test_encrypt" , "id" : _id } ws_url = "ws://localhost:3000/" ws = websocket.WebSocket() ws.connect(ws_url) ws.send(json.dumps(data)) for _ in range (100 ): signstr = ws.recv() if _id in signstr: dd = json.loads(signstr) signstr = dd.get('data' ) break time.sleep(0.1 ) ws.close() return signstr