Files
GoSally/internal/server/sv1/handle.go

347 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package sv1
import (
"net/http"
"github.com/akyaiy/GoSally-mvp/internal/server/rpc"
)
func (h *HandlerV1) Handle(w http.ResponseWriter, r *http.Request, req rpc.RPCRequest) {
rpc.WriteResponse(w, &rpc.RPCResponse{
JSONRPC: rpc.JSONRPCVersion,
ID: req.ID,
Result: "Hi",
}) // test answer to make sure everything works
}
// func (h *HandlerV1) Handle(w http.ResponseWriter, r *http.Request) {
// var req PettiRequest
// // server, ok := s.servers[serversApiVer(payload.PettiVer)]
// // if !ok {
// // WriteRouterError(w, &RouterError{
// // Status: "error",
// // StatusCode: http.StatusBadRequest,
// // Payload: map[string]any{
// // "Message": InvalidProtovolVersion,
// // },
// // })
// // s.log.Info("invalid request received", slog.String("issue", InvalidProtovolVersion), slog.String("requested-version", payload.PettiVer))
// // return
// // }
// if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
// utils.WriteJSONError(w, http.StatusBadRequest, "невалидный JSON: "+err.Error())
// return
// }
// if req.PettiVer == "" {
// utils.WriteJSONError(w, http.StatusBadRequest, "отсутствует PettiVer")
// return
// }
// if req.PettiVer != h.GetVersion() {
// utils.WriteJSONError(w, http.StatusBadRequest, "неподдерживаемая версия PettiVer")
// return
// }
// if req.PackageType.Request == "" {
// utils.WriteJSONError(w, http.StatusBadRequest, "отсутствует PackageType.Request")
// return
// }
// if req.Payload == nil {
// utils.WriteJSONError(w, http.StatusBadRequest, "отсутствует Payload")
// return
// }
// cmdRaw, ok := req.Payload["Exec"].(string)
// if !ok || cmdRaw == "" {
// utils.WriteJSONError(w, http.StatusBadRequest, "Payload.Exec отсутствует или некорректен")
// return
// }
// cmd := cmdRaw
// if !h.allowedCmd.MatchString(string([]rune(cmd)[0])) || !h.listAllowedCmd.MatchString(cmd) {
// utils.WriteJSONError(w, http.StatusBadRequest, "команда запрещена")
// return
// }
// // ===== Проверка скрипта
// scriptPath := h.comMatch(h.GetVersion(), cmd)
// if scriptPath == "" {
// utils.WriteJSONError(w, http.StatusNotFound, "команда не найдена")
// return
// }
// fullPath := filepath.Join(h.cfg.ComDir, scriptPath)
// if _, err := os.Stat(fullPath); err != nil {
// utils.WriteJSONError(w, http.StatusNotFound, "файл команды не найден")
// return
// }
// // ===== Запуск Lua
// L := lua.NewState()
// defer L.Close()
// inTable := L.NewTable()
// paramsTable := L.NewTable()
// if params, ok := req.Payload["PassedParameters"].(map[string]interface{}); ok {
// for k, v := range params {
// L.SetField(paramsTable, k, utils.ConvertGolangTypesToLua(L, v))
// }
// }
// L.SetField(inTable, "Params", paramsTable)
// L.SetGlobal("In", inTable)
// resultTable := L.NewTable()
// outTable := L.NewTable()
// L.SetField(outTable, "Result", resultTable)
// L.SetGlobal("Out", outTable)
// prepareLua := filepath.Join(h.cfg.ComDir, "_prepare.lua")
// if _, err := os.Stat(prepareLua); err == nil {
// if err := L.DoFile(prepareLua); err != nil {
// utils.WriteJSONError(w, http.StatusInternalServerError, "lua _prepare ошибка: "+err.Error())
// return
// }
// }
// if err := L.DoFile(fullPath); err != nil {
// utils.WriteJSONError(w, http.StatusInternalServerError, "lua exec ошибка: "+err.Error())
// return
// }
// lv := L.GetGlobal("Out")
// tbl, ok := lv.(*lua.LTable)
// if !ok {
// utils.WriteJSONError(w, http.StatusInternalServerError, "'Out' не таблица")
// return
// }
// resultVal := tbl.RawGetString("Result")
// resultTbl, ok := resultVal.(*lua.LTable)
// if !ok {
// utils.WriteJSONError(w, http.StatusInternalServerError, "'Result' не таблица")
// return
// }
// out := make(map[string]any)
// resultTbl.ForEach(func(key lua.LValue, value lua.LValue) {
// out[key.String()] = utils.ConvertLuaTypesToGolang(value)
// })
// uuid32, _ := corestate.GetNodeUUID(filepath.Join(config.MetaDir, "uuid"))
// resp := PettiResponse{
// PettiVer: req.PettiVer,
// ResponsibleAgentUUID: uuid32,
// PackageType: struct {
// AnswerOf string `json:"AnswerOf"`
// }{AnswerOf: req.PackageType.Request},
// Payload: map[string]any{
// "RequestedCommand": cmd,
// "Response": out,
// },
// }
// // ===== Финальная проверка на сериализацию (валидность сборки)
// respData, err := json.Marshal(resp)
// if err != nil {
// utils.WriteJSONError(w, http.StatusInternalServerError, "внутренняя ошибка: пакет невалиден")
// return
// }
// w.Header().Set("Content-Type", "application/json")
// w.WriteHeader(http.StatusOK)
// if _, err := w.Write(respData); err != nil {
// h.log.Error("Ошибка при отправке JSON", slog.String("err", err.Error()))
// }
// // ===== Логгирование статуса
// status, _ := out["status"].(string)
// switch status {
// case "ok":
// h.log.Info("Успешно", slog.String("cmd", cmd), slog.Any("out", out))
// case "error":
// h.log.Warn("Ошибка в команде", slog.String("cmd", cmd), slog.Any("out", out))
// default:
// h.log.Info("Неизвестный статус", slog.String("cmd", cmd), slog.Any("out", out))
// }
// }
/*
import (
"encoding/json"
"log/slog"
"net/http"
"os"
"path/filepath"
"github.com/akyaiy/GoSally-mvp/core/config"
"github.com/akyaiy/GoSally-mvp/core/corestate"
"github.com/akyaiy/GoSally-mvp/core/utils"
"github.com/go-chi/chi/v5"
lua "github.com/yuin/gopher-lua"
)
// HandlerV1 is the main handler for version 1 of the API.
// The function processes the HTTP request and runs Lua scripts,
// preparing the environment and subsequently transmitting the execution result
func (h *HandlerV1) Handle(w http.ResponseWriter, r *http.Request) {
uuid16, err := utils.NewUUID(int(config.UUIDLength))
if err != nil {
h.log.Error("Failed to generate UUID",
slog.String("error", err.Error()))
if err := utils.WriteJSONError(w, http.StatusInternalServerError, "failed to generate UUID: "+err.Error()); err != nil {
h.log.Error("Failed to write JSON", slog.String("err", err.Error()))
}
return
}
log := h.log.With(
slog.Group("request",
slog.String("version", h.GetVersion()),
slog.String("url", r.URL.String()),
slog.String("method", r.Method),
),
slog.Group("connection",
slog.String("connection-uuid", uuid16),
slog.String("remote", r.RemoteAddr),
),
)
log.Info("Received request")
cmd := chi.URLParam(r, "cmd")
if !h.allowedCmd.MatchString(string([]rune(cmd)[0])) || !h.listAllowedCmd.MatchString(cmd) {
log.Error("HTTP request error",
slog.String("error", "invalid command"),
slog.String("cmd", cmd),
slog.Int("status", http.StatusBadRequest))
if err := utils.WriteJSONError(w, http.StatusBadRequest, "invalid command"); err != nil {
h.log.Error("Failed to write JSON", slog.String("err", err.Error()))
}
return
}
scriptPath := h.comMatch(chi.URLParam(r, "ver"), cmd)
if scriptPath == "" {
log.Error("HTTP request error",
slog.String("error", "command not found"),
slog.String("cmd", cmd),
slog.Int("status", http.StatusNotFound))
if err := utils.WriteJSONError(w, http.StatusNotFound, "command not found"); err != nil {
h.log.Error("Failed to write JSON", slog.String("err", err.Error()))
}
return
}
scriptPath = filepath.Join(h.cfg.ComDir, scriptPath)
if _, err := os.Stat(scriptPath); err != nil {
log.Error("HTTP request error",
slog.String("error", "command not found"),
slog.String("cmd", cmd),
slog.Int("status", http.StatusNotFound))
if err := utils.WriteJSONError(w, http.StatusNotFound, "command not found"); err != nil {
h.log.Error("Failed to write JSON", slog.String("err", err.Error()))
}
return
}
L := lua.NewState()
defer L.Close()
paramsTable := L.NewTable()
qt := r.URL.Query()
for k, v := range qt {
if len(v) > 0 {
L.SetField(paramsTable, k, lua.LString(v[0]))
}
}
inTable := L.NewTable()
L.SetField(inTable, "Params", paramsTable)
L.SetGlobal("In", inTable)
// Создаем таблицу Out с Result
resultTable := L.NewTable()
outTable := L.NewTable()
L.SetField(outTable, "Result", resultTable)
L.SetGlobal("Out", outTable)
prepareLuaEnv := filepath.Join(h.cfg.ComDir, "_prepare.lua")
if _, err := os.Stat(prepareLuaEnv); err == nil {
if err := L.DoFile(prepareLuaEnv); err != nil {
log.Error("Failed to prepare lua environment",
slog.String("error", err.Error()))
if err := utils.WriteJSONError(w, http.StatusInternalServerError, "lua error: "+err.Error()); err != nil {
h.log.Error("Failed to write JSON", slog.String("err", err.Error()))
}
return
}
} else {
log.Warn("No environment preparation script found, skipping preparation")
}
if err := L.DoFile(scriptPath); err != nil {
log.Error("Failed to execute lua script",
slog.String("error", err.Error()))
if err := utils.WriteJSONError(w, http.StatusInternalServerError, "lua error: "+err.Error()); err != nil {
h.log.Error("Failed to write JSON", slog.String("err", err.Error()))
}
return
}
lv := L.GetGlobal("Out")
tbl, ok := lv.(*lua.LTable)
if !ok {
log.Error("Lua global 'Out' is not a table")
if err := utils.WriteJSONError(w, http.StatusInternalServerError, "'Out' is not a table"); err != nil {
h.log.Error("Failed to write JSON", slog.String("err", err.Error()))
}
return
}
resultVal := tbl.RawGetString("Result")
resultTbl, ok := resultVal.(*lua.LTable)
if !ok {
log.Error("Lua global 'Result' is not a table")
if err := utils.WriteJSONError(w, http.StatusInternalServerError, "'Result' is not a table"); err != nil {
h.log.Error("Failed to write JSON", slog.String("err", err.Error()))
}
return
}
out := make(map[string]any)
resultTbl.ForEach(func(key lua.LValue, value lua.LValue) {
out[key.String()] = utils.ConvertLuaTypesToGolang(value)
})
uuid32, _ := corestate.GetNodeUUID(filepath.Join(config.MetaDir, "uuid"))
response := ResponseFormat{
ResponsibleAgentUUID: uuid32,
RequestedCommand: cmd,
Response: out,
}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(response); err != nil {
log.Error("Failed to encode JSON response",
slog.String("error", err.Error()))
}
status, _ := out["status"].(string)
switch status {
case "error":
log.Info("Command executed with error",
slog.String("cmd", cmd),
slog.Any("result", out))
case "ok":
log.Info("Command executed successfully",
slog.String("cmd", cmd),
slog.Any("result", out))
default:
log.Info("Command executed and returned an unknown status",
slog.String("cmd", cmd),
slog.Any("result", out))
}
log.Info("Session completed")
}
*/