diff --git a/.gitignore b/.gitignore index 7d3d88f..97d592b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ bak/ bin/ +cert/ \ No newline at end of file diff --git a/Makefile b/Makefile index a581918..815a0c5 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ APP_NAME := node BIN_DIR := bin GOPATH := $(shell go env GOPATH) -.PHONY: all build run test fmt vet lint check clean +.PHONY: all build run runq test fmt vet lint check clean all: build @@ -25,6 +25,9 @@ build: run: build ./$(BIN_DIR)/$(APP_NAME) +runq: build + ./$(BIN_DIR)/$(APP_NAME) | jq + test: @go test ./... | grep -v '^?' || true diff --git a/cfg/config.yaml b/cfg/config.yaml index 31580b3..e40cdce 100644 --- a/cfg/config.yaml +++ b/cfg/config.yaml @@ -10,4 +10,9 @@ http_server: - b1 - s2 +tls: + enabled: "true" + cert_file: "./cert/server.crt" + key_file: "./cert/server.key" + com_dir: "com/" \ No newline at end of file diff --git a/cmd/node/node.go b/cmd/node/node.go index da5c668..99b9337 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -39,11 +39,21 @@ func main() { Config: cfg, }, serverv1) r := chi.NewRouter() - r.Route("/{ver}/com", func(r chi.Router) { + r.Route("/api/{ver}/com", func(r chi.Router) { r.Get("/", s.HandleList) r.Get("/{cmd}", s.Handle) }) r.NotFound(serverv1.ErrNotFound) + if cfg.TlsEnabled == "true" { + log.Info("Server started with TLS", slog.String("address", cfg.Address)) + err := http.ListenAndServeTLS(cfg.Address, cfg.CertFile, cfg.KeyFile, r) + if err != nil { + log.Error("Failed to start HTTPS server", slog.String("error", err.Error())) + } + } log.Info("Server started", slog.String("address", cfg.Address)) - http.ListenAndServe(cfg.Address, r) + err := http.ListenAndServe(cfg.Address, r) + if err != nil { + log.Error("Failed to start HTTP server", slog.String("error", err.Error())) + } } diff --git a/com/echo.lua b/com/echo.lua index 0b967e2..715beab 100644 --- a/com/echo.lua +++ b/com/echo.lua @@ -1,6 +1,6 @@ ---- #description = "Echoes back the message provided in the 'msg' parameter." - -local mod = require("_for_echo") +--- #description = "Echoes back the message." +--- #args +--- msg = the message if not Params.msg then Result.status = "error" @@ -9,5 +9,5 @@ if not Params.msg then end Result.status = "ok" -Result.answer = mod.translate(Params.msg) +Result.answer = Params.msg return \ No newline at end of file diff --git a/config/config.go b/config/config.go index 77abccd..020c888 100644 --- a/config/config.go +++ b/config/config.go @@ -12,6 +12,13 @@ type ConfigConf struct { Mode string `yaml:"mode" env-default:"dev"` ComDir string `yaml:"com_dir" env-default:"./com/"` HTTPServer `yaml:"http_server"` + TLS `yaml:"tls"` +} + +type TLS struct { + TlsEnabled string `yaml:"enabled" env-default:"false"` + CertFile string `yaml:"cert_file" env-default:"./cert/server.crt"` + KeyFile string `yaml:"key_file" env-default:"./cert/server.key"` } type HTTPServer struct { @@ -31,6 +38,7 @@ type ConfigEnv struct { } func MustLoadConfig() *ConfigConf { + log.SetOutput(os.Stderr) var configEnv ConfigEnv if err := cleanenv.ReadEnv(&configEnv); err != nil { log.Fatalf("Failed to read environment variables: %v", err) diff --git a/sv1/handle_com.go b/sv1/handle_com.go index f89912a..c972ad9 100644 --- a/sv1/handle_com.go +++ b/sv1/handle_com.go @@ -13,18 +13,23 @@ import ( func (h *HandlerV1) _handle() { uuid16 := h.newUUID() - h.log.Info("Received request", - slog.String("version", "v1"), - slog.String("connection-uuid", uuid16), - slog.String("remote", h.r.RemoteAddr), - slog.String("method", h.r.Method), - slog.String("url", h.r.URL.String())) + log := h.log.With( + slog.Group("request", + slog.String("version", "v1"), + slog.String("url", h.r.URL.String()), + slog.String("method", h.r.Method), + ), + slog.Group("connection", + slog.String("connection-uuid", uuid16), + slog.String("remote", h.r.RemoteAddr), + ), + ) + log.Info("Received request") cmd := chi.URLParam(h.r, "cmd") var scriptPath string if !h.allowedCmd.MatchString(string([]rune(cmd)[0])) { - h.log.Error("HTTP request error", - slog.String("connection-uuid", uuid16), + log.Error("HTTP request error", slog.String("error", "invalid command"), slog.String("cmd", cmd), slog.Int("status", http.StatusBadRequest)) @@ -32,8 +37,7 @@ func (h *HandlerV1) _handle() { return } if !h.listAllowedCmd.MatchString(cmd) { - h.log.Error("HTTP request error", - slog.String("connection-uuid", uuid16), + log.Error("HTTP request error", slog.String("error", "invalid command"), slog.String("cmd", cmd), slog.Int("status", http.StatusBadRequest)) @@ -41,8 +45,7 @@ func (h *HandlerV1) _handle() { return } if scriptPath = h.comMatch(chi.URLParam(h.r, "ver"), cmd); scriptPath == "" { - h.log.Error("HTTP request error", - slog.String("connection-uuid", uuid16), + log.Error("HTTP request error", slog.String("error", "command not found"), slog.String("cmd", cmd), slog.Int("status", http.StatusNotFound)) @@ -52,8 +55,7 @@ func (h *HandlerV1) _handle() { scriptPath = filepath.Join(h.cfg.ComDir, scriptPath) if _, err := os.Stat(scriptPath); err != nil { - h.log.Error("HTTP request error", - slog.String("connection-uuid", uuid16), + log.Error("HTTP request error", slog.String("error", "command not found"), slog.String("cmd", cmd), slog.Int("status", http.StatusNotFound)) @@ -79,19 +81,18 @@ func (h *HandlerV1) _handle() { prepareLuaEnv := filepath.Join(h.cfg.ComDir, "_prepare"+".lua") if _, err := os.Stat(prepareLuaEnv); err == nil { if err := L.DoFile(prepareLuaEnv); err != nil { - h.log.Error("Failed to prepare lua environment", - slog.String("connection-uuid", uuid16), + log.Error("Failed to prepare lua environment", slog.String("error", err.Error())) h.writeJSONError(http.StatusInternalServerError, "lua error: "+err.Error()) return } } else { - h.log.Error("No environment preparation script found, skipping preparation", slog.String("connection-uuid", uuid16), slog.String("error", err.Error())) + log.Error("No environment preparation script found, skipping preparation", + slog.String("error", err.Error())) } if err := L.DoFile(scriptPath); err != nil { - h.log.Error("Failed to execute lua script", - slog.String("connection-uuid", uuid16), + log.Error("Failed to execute lua script", slog.String("error", err.Error())) h.writeJSONError(http.StatusInternalServerError, "lua error: "+err.Error()) return @@ -117,23 +118,16 @@ func (h *HandlerV1) _handle() { json.NewEncoder(h.w).Encode(out) switch out["status"] { case "error": - h.log.Info("Command executed with error", - slog.String("connection-uuid", uuid16), + log.Info("Command executed with error", slog.String("cmd", cmd), slog.Any("result", out)) case "ok": - h.log.Info("Command executed successfully", - slog.String("connection-uuid", uuid16), + log.Info("Command executed successfully", slog.String("cmd", cmd), slog.Any("result", out)) default: - h.log.Info("Command executed and returned an unknown status", - slog.String("connection-uuid", uuid16), + log.Info("Command executed and returned an unknown status", slog.String("cmd", cmd), slog.Any("result", out)) } - h.log.Info("Session completed", - slog.String("connection-uuid", uuid16), - slog.String("remote", h.r.RemoteAddr), - slog.String("method", h.r.Method), - slog.String("url", h.r.URL.String())) + log.Info("Session completed") } diff --git a/sv1/handle_list.go b/sv1/handle_list.go index c52305f..85c6e00 100644 --- a/sv1/handle_list.go +++ b/sv1/handle_list.go @@ -13,17 +13,22 @@ import ( func (h *HandlerV1) _handleList() { uuid16 := h.newUUID() - h.log.Info("Received request", - slog.String("version", "v1"), - slog.String("connection-uuid", uuid16), - slog.String("remote", h.r.RemoteAddr), - slog.String("method", h.r.Method), - slog.String("url", h.r.URL.String())) - + log := h.log.With( + slog.Group("request", + slog.String("version", "v1"), + slog.String("url", h.r.URL.String()), + slog.String("method", h.r.Method), + ), + slog.Group("connection", + slog.String("connection-uuid", uuid16), + slog.String("remote", h.r.RemoteAddr), + ), + ) + log.Info("Received request") type ComMeta struct { - Description string + Description string `json:"Description"` + Arguments map[string]string `json:"Arguments,omitempty"` } - var ( files []os.DirEntry err error @@ -32,7 +37,7 @@ func (h *HandlerV1) _handleList() { ) if files, err = os.ReadDir(h.cfg.ComDir); err != nil { - h.log.Error("Failed to read commands directory", + log.Error("Failed to read commands directory", slog.String("error", err.Error())) h.writeJSONError(http.StatusInternalServerError, "failed to read commands directory: "+err.Error()) return @@ -94,14 +99,9 @@ func (h *HandlerV1) _handleList() { } } - h.log.Info("Command list prepared", - slog.String("connection-uuid", uuid16)) + log.Debug("Command list prepared") - h.log.Info("Session completed", - slog.String("connection-uuid", uuid16), - slog.String("remote", h.r.RemoteAddr), - slog.String("method", h.r.Method), - slog.String("url", h.r.URL.String())) + log.Info("Session completed") h.w.Header().Set("Content-Type", "application/json") json.NewEncoder(h.w).Encode(commands)