首页 > 解决方案 > 代码抛出错误,写在结束后,但为什么

问题描述

所以我做了一个小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.

标签: javascriptnode.jsapihttpserver

解决方案


你必须检查以防你已经发送了一些响应以不再发送一些东西。所以每个最好使用:

return res.end();

停止功能。


推荐阅读