javascript - 代码抛出错误,写在结束后,但为什么
问题描述
所以我做了一个小api来在屏幕上启动我的世界服务器,效果很好。但是现在,每次我启动或停止服务器时,api都会以某种方式崩溃,因为http服务器在结束后写入,我找不到任何结束服务器的东西。
我似乎找不到它在哪里结束,这很奇怪。
我是 http 服务器、api 和这些东西的新手,所以这可能只是我的愚蠢错误。
//@author WizzerStudios on Github
//CC 2021
//Allowed:
//:: Editing
//Disallowed
//:: Redistributing
//:: Claiming as yours
//Importing stuff
var http = require('http');
const { exec } = require("child_process");
var url = require('url');
var https = require('https');
const fs = require('fs');
//Console log
console.log("Wizzer API booted.")
//Create API / HTTP Server
http.createServer(function (req, res) {
var q = url.parse(req.url, true).query;
//Check if password is correctly given.
if(q.password == "Password"){
//Switch to the action.
switch(q.action){
//If action is undefined:
case undefined:
res.end("Action not given.");
break;
//Get Logs is coming soon.
case "getlogs":
if(q.sname == undefined) res.end("No server name given.");
try {
const data = fs.readFileSync('serverfiles/' + q.sname + '/logs/latest.log', 'utf8');
res.end(data);
} catch (err) {
console.error(err)
res.end("Error occured! Server does not exist or isn't available.");
}
break;
//Start the server using the bash screen command.
case "stop":
//If no server name is given, end the connection.
if(q.sname == undefined) res.end("Server name not specified.");
//If server exists, run the screen command.
if (fs.existsSync('./servers/' + q.sname + '.json')) {
//Check if a screen session with the same name is already running.
exec('screen -S ' + q.sname + ' -Q select . ; echo $?',
(error, stdout, stderror) => {
if (error) {
console.error("Error: ", error);
return;
}
var out = stdout;
if(out.includes('0')){
exec('screen -p 0 -S minecraft-server -X eval `stuff "say TEST MESSAGE..."\\015`', (error, stdout, stderror) => {
res.end("Server stopped!"); //It says it stopped and crashes here !!!
});
} else {
res.end('Server already stopped!');
return;
}});
} else {
res.end("Server does not exist!");
return;
}
break;
case "start":
//If no server name is given, end the connection.
if(q.sname == undefined) res.end("Server name not specified.");
//If server exists, run the screen command.
if (fs.existsSync('./servers/' + q.sname + '.json')) {
//Check if a screen session with the same name is already running.
exec('screen -S ' + q.sname + ' -Q select . ; echo $?',
(error, stdout, stderror) => {
if (error) {
console.error("Error: ", error);
return;
}
var out = stdout;
if(out.includes('1')){
exec('screen -S ' + q.sname + ' -dm bash /home/mcserver/api/serverfiles/' + q.sname + '/start.sh', (error, stdout, stderror) => {
res.end("Server started!"); // Here it says it already stopped!
});
} else {
res.end('Server already started!');
return;
}});
} else {
res.end("Server does not exist!");
return;
}
break;
//Create server action.
case "createServer":
//If no game is given, end connection.
if(q.game == undefined) res.end("Game not given");
//Switch to the game chosen.
switch(q.game){
//Minecraft
case "minecraft":
if(q.sname == undefined) res.end("Server name not given."); // No server name given, end connection.
if(q.port == undefined) res.end("Port not given."); // No port given, end connection.
if(q.ram == undefined) res.end("Please give ram in gigabytes."); // No ram given, end connection.
if(q.software == undefined) res.end("Server software not given."); // Server software not given, end connection.
if(q.version == undefined) res.end("Server version not given."); // Version not given, end connection.
//Check if server already exists:
var path = './servers/' + q.sname + '.json';
if (fs.existsSync(path)) {
res.end("Server Exists.");
return;
}
ram = Number(q.ram);
ram *= 1024;
let server = {
name: q.sname,
port: q.port,
game: 'Minecraft',
ram: Number(ram),
software: q.software,
version: q.version
};
let data = JSON.stringify(server, null, 2);
fs.mkdir('./serverfiles/' + q.sname, (err) => {
if (err) {
throw err;
res.end(err)
}
});
fs.writeFile('./serverfiles/' + q.sname + '/eula.txt', 'eula=true', function (err) {
if (err) res.end(err);
if(err) console.log(err);
});
fs.writeFile('./serverfiles/' + q.sname + '/start.sh', '#!/bin/bash\njava -Xmx' + Number(ram) + 'M ' + '-Xms' + Number(ram) + 'M -jar /home/mcserver/api/serverfiles/' + q.sname + '/server.jar', function (err) {
if (err) res.end(err);
if(err) console.log(err);
});
exec('chmod +x ./serverfiles/' + q.sname + '/start.sh');
fs.writeFile('./serverfiles/' + q.sname + '/server.properties', 'port=' + q.port, function (err) {
if (err) res.end(err);
if(err) console.log(err);
});
try{
https.get("https://serverjars.com/api/fetchJar/" + q.software + "/" + q.version, function(response) { response.pipe(fs.createWriteStream("serverfiles/" + q.sname + '/server.jar'))});
} catch(err){
res.end("Failed!")
console.log(err)
}
fs.writeFile("servers/" + q.sname + ".json", data, (err) => {});
res.write("Server Software: " + q.software);
res.write("\nRam: " + Number(ram));
res.write("\nServer name: " + q.sname);
res.write("\nGame: Minecraft");
res.write("\nPort: " + q.port);
res.end("\nVersion " + q.version);
}
}
//if(req.url == "/?password=Password&?action=create"){
// res.write("game not given")
//} else if(req.url == "/?password=Password&?action=create&game"){
// res.write("Authenticated!")
//}
//} else {
//res.write("WRONG PASSWORD!")
}
res.end(); //end the response
}).listen(8080); //the server object listens on port 808
events.js:174
throw er; // Unhandled 'error' event
^
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at write_ (_http_outgoing.js:572:17)
at ServerResponse.write (_http_outgoing.js:567:10)
at exec (/home/mcserver/api/index.js:86:21)
at ChildProcess.exithandler (child_process.js:285:7)
at ChildProcess.emit (events.js:198:13)
at maybeClose (internal/child_process.js:982:16)
at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)
Emitted 'error' event at:
at writeAfterEndNT (_http_outgoing.js:634:7)
at process._tickCallback (internal/process/next_tick.js:63:19)
``` is the error.
I do know that i'm writing after the end, but where did it end?
Also, changing res.write to res.end doesn't crash my code, but it doesn't give anything in my browser.
解决方案
你必须检查以防你已经发送了一些响应以不再发送一些东西。所以每个最好使用:
return res.end();
停止功能。
推荐阅读
- c++ - 如何使用 C++ 将 XML 文件加载和读/写到 GTK+ 应用程序中?
- python - 美丽汤和 td 元素提取的问题
- machine-learning - PyTorch 由于广播而给出不正确的结果
- c# - Task.Delay 真的像 I/O 操作那样异步吗,即它是否依赖硬件和中断而不是线程?
- ruby-on-rails - Flash 消息仅显示一次(Rails 6)
- c++ - 连接一列中的所有行,其中另一列匹配/等于 sqlite 中的某些内容
- python - 如何将不同 csv 文件中的两列合并为一个 csv 文件
- html - 如何让 Safari 正确显示我的 Google 字体?
- oop - 关闭在失败的构造函数中创建的资源
- elasticsearch - ElasticSearch 中每个字段的不同时间范围