godot_repl_server/server/main.go

100 lines
2.6 KiB
Go
Raw Normal View History

2022-05-19 12:18:00 +03:00
package main
import (
"bytes"
"context"
"log"
"net/http"
"os"
"os/exec"
"strings"
"text/template"
"time"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
type CodeStruct struct {
Code []string
Id string
}
func main() {
r := gin.Default()
var godot_path string
godot_path, exists := os.LookupEnv("GODOT")
if !exists {
godot_path = "godot"
}
scripts_path, exists := os.LookupEnv("SCRIPTS")
if !exists {
scripts_path = "./"
}
r.POST("/run", func(c *gin.Context) {
code := c.DefaultPostForm("code", "")
if code == "" {
c.JSON(http.StatusBadRequest, gin.H{"status": "Empty body"})
return
}
lines := strings.Split(code, "\n")
log.Printf("%v", lines)
file_uuid := uuid.New()
file_uuid_clean := strings.Replace(file_uuid.String(), "-", "", -1)
filename := scripts_path + file_uuid_clean + ".gd"
// err := os.WriteFile(filename, code_bytes, 0644)
tmpl, err := template.ParseFiles("template")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"status": "could not parse template", "error": err.Error()})
return
}
file, err := os.Create(filename)
defer file.Close()
defer os.Remove(filename)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"status": "could not create file", "error": err.Error()})
return
}
err = tmpl.Execute(file, CodeStruct{Code: lines, Id: file_uuid_clean})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"status": "could not write file", "error": err.Error()})
return
}
var stdout bytes.Buffer
var stderr bytes.Buffer
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, godot_path, "-s", filename, "--no-window")
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err = cmd.Run()
out_str := stdout.String()
err_str := stderr.String()
separator := "=== " + file_uuid_clean + " ==="
out_sep := strings.Split(out_str, separator)
err_sep := strings.Split(err_str, separator)
if len(out_sep) == 1 {
out_sep = append(out_sep, "")
}
if len(err_sep) == 1 {
err_sep = append(err_sep, "")
}
if ctx.Err() == context.DeadlineExceeded {
2022-05-19 15:09:57 +03:00
c.JSON(http.StatusRequestTimeout, gin.H{"status": "timeout", "stdout": out_sep[1], "stderr": err_sep[1]})
2022-05-19 12:18:00 +03:00
return
}
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"status": err.Error()})
return
}
out_separated := strings.Split(out_str, separator)
if len(out_separated) < 2 {
c.JSON(http.StatusBadRequest, gin.H{"status": "runtime error", "stdout": out_str, "stderr": err_str})
return
}
c.JSON(http.StatusOK, gin.H{"result": out_separated[1]})
})
log.Fatal(r.Run(":8080").Error())
}