所以我做了一个小api来启动屏幕上的minecraft服务器,这工作得很好。但是现在,每次我启动或停止服务器,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/bashnjava -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.
去掉下面一行:
res.end(); //end the response <-----------------
}).listen(8080); //the server object listens on port 8080
您正在调用res.end()"在函数
中调用它之后res.end("nVersion " + q.version); // In createServer
调用它,然后它放弃switch语句并再次执行上面的res.end()
你必须检查一下,如果你已经发送了一些响应,不要再发送了。所以最好使用:
return res.end();
停止功能。