NodeJS无法修改类obj



这是我在这个论坛上的第一篇文章。所以请原谅我的失误。

我想写一个NodeJS服务器,它运行WebSocket服务器(npm-ws模块(。NodeJS服务器还包含一个Class Obj,我想稍后通过Websocket服务器修改它的函数。我的问题是修改后的函数不能访问全局变量。

如果有这个问题的解决方案,或者为什么会出现这种情况,有人能帮忙吗?因为如果你在没有Websocket的情况下这样做,它会起作用。

这是代码:

服务器代码:

const WebSocket = require('ws');

// WebSocket Server
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
try {
message = JSON.parse(message);
if (message.type == "handler") {
handler.modify(message.data);
console.log("modifyed");
}
if (message.type == "func") {
handler.modify_func(message.data);
console.log("modifyed");
}
if (message.type == "run") {
eval(message.data);
}
}
catch (error) {
}
});
});
// Modifying class
class Handler {
constructor() {
this.functions = [];
}
modify(data) {
let temp_class = new Function('return ' + data)();
temp_class.functions.forEach(element => {
if (this.functions.indexOf(element) == -1) {
this.functions.push(element)
}
this[element] = temp_class[element];
});
}
modify_func(data) {
let temp_func = new Function('return ' + data)();
this[temp_func.name] = temp_func;
}
test_func_from_orginal() {
console.log("test_func_from_orginal says:");
console.log(test_val);
}
}

var test_val = "this is the global variable";
var handler = new Handler();

客户代码:

const WebSocket = require('ws');

//WebSocket Client
var ws = new WebSocket('ws://localhost:8080');
ws.on('open', function open(event) {
// ws.send(JSON.stringify({ type: "handler", data: Handler.toString() }))
ws.send(JSON.stringify({ type: "func", data: test_func_from_func.toString() }))
console.log("open")
});
//Class Module
class Handler {
static get functions() {
return ["test"];
}
static test_func_from_class() {
console.log("test_func_from_class sayes:")
console.log(test_val);
}
}

function test_func_from_func() {
console.log("test_func_from_func sayes:")
console.log(test_val);
}


setTimeout(function () { ws.send(JSON.stringify({ type: "run", data: 'handler.test_func_from_orginal()' })) }, 1000);
// setTimeout(function () { ws.send(JSON.stringify({ type: "run", data: 'handler.test_func_from_class()' })) }, 1000);
setTimeout(function () { ws.send(JSON.stringify({ type: "run", data: 'handler.test_func_from_func()' })) }, 1000);

好吧,这就是它的全部内容——一个简单的错误。如果你去掉所有的websocket内容(这在这里并不是真正相关的,因为字符串,而不是上下文,无论如何都是来回传递的(,你会得到:

class ServerHandler {
constructor() {
this.functions = [];
}
modify(data) {
let temp_class = new Function('return ' + data)();
// not sure why not just `eval(data)` btw
temp_class.functions.forEach(funcName => {
if (this.functions.indexOf(funcName) == -1) {
this.functions.push(funcName)
}
this[funcName] = temp_class[funcName];
});
}
}
class ClientHandler {
static get functions() {
return ["test_func_from_class"]; 
// not "test" as in your example
// you actually don't even need this registry: 
// all the static methods can be collected in runtime
}
static test_func_from_class() {
console.log("test_func_from_class sayes:")
console.log(test_val);
}
}
var test_val = 42;
var handler = new ServerHandler();
handler.modify(ClientHandler.toString());
eval(`handler.test_func_from_class()`); // 42

这一切都很好,因为存储在静态get函数中的方法名称("test"(和该方法的实际名称("test_func_from_class"(之间不再不匹配。诀窍在于,与该临时类一起创建的所有静态函数的作用域与ServerHandler中创建的任何其他实体的作用域相同;这就是他们"看到"test_val的方式。

但这里的"工作"仅仅是从技术角度来看这种方法的可能性,而不是可行性。任意输入的new Functioneval都是非常危险的安全漏洞,它们在这里是敞开的。

我现在找到了解决问题的方法。

服务器代码

const WebSocket = require('ws');


// WebSocket Server
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
message = JSON.parse(message);
try {
if (message.type == "run") {
eval(message.data);
}
if (message.type == "obj_handler") {
handler.modify(JSON.parse(message.data));
}
}
catch (error) {
console.log(error);
}
// console.log('received: %s', message);
});
ws.send('something');
});


class ServerHandler {
constructor() {
this.data = "hi";
}
modify(data) {
for (const func in data) {
this[func] = eval(data[func]);
}
}
}
var test_val = 42;
var handler = new ServerHandler();

客户代码:

const WebSocket = require('ws');

//WebSocket Client
try {
var ws = new WebSocket('ws://localhost:8080');
ws.on('open', function open(event) {
ws.send(JSON.stringify({ type: "obj_handler", data: update.convert() }))
});
}
catch (error) {
}


// Needed Update with 2 new Functions
update = {
func_test_global: () => {
console.log(test_val);
},

func_test_this: _ => {
console.log(this.data);
},
convert: function () {
let new_update = {};
for (const func in this) {
if (func != "convert")
new_update[func] = "" + this[func];
}
return JSON.stringify(new_update)
}
}

// setTimeout(function () { ws.send(JSON.stringify({ type: "run", data: 'handler.func_test_global()' })) }, 1000);
// setTimeout(function () { ws.send(JSON.stringify({ type: "run", data: 'handler.func_test_this()' })) }, 1000);

最新更新