add Net.Http to lua

This commit is contained in:
2025-07-31 20:37:31 +03:00
parent 75ee6e10aa
commit f411637520
3 changed files with 176 additions and 3 deletions

View File

@@ -22,3 +22,38 @@ Out = {
---@type Log ---@type Log
Log = {} Log = {}
---@class HttpResponse
---@field status integer HTTP status code
---@field status_text string HTTP status text
---@field body string Response body
---@field content_length integer Content length
---@field headers table<string, string|string[]> Response headers
---@class Http
---@field Get fun(log: boolean, url: string): HttpResponse, string? Makes HTTP GET request
---@field Post fun(log: boolean, url: string, content_type: string, payload: string): HttpResponse, string? Makes HTTP POST request
---@class Net
---@field Http Http HTTP client methods
---@type Net
Net = {
Http = {
---Makes HTTP GET request
---@param log boolean Whether to log the request
---@param url string URL to request
---@return HttpResponse response
---@return string? error
Get = function(log, url) end,
---Makes HTTP POST request
---@param log boolean Whether to log the request
---@param url string URL to request
---@param content_type string Content-Type header
---@param payload string Request body
---@return HttpResponse response
---@return string? error
Post = function(log, url, content_type, payload) end
}
}

View File

@@ -24,5 +24,5 @@ func (h *HandlerV1) Handle(r *http.Request, req *rpc.RPCRequest) *rpc.RPCRespons
} }
} }
return h.handleLUA(method, req) return h.handleLUA(r, req, method)
} }

View File

@@ -2,17 +2,32 @@ package sv1
import ( import (
"fmt" "fmt"
"io"
"log/slog" "log/slog"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings"
"github.com/akyaiy/GoSally-mvp/internal/engine/logs" "github.com/akyaiy/GoSally-mvp/internal/engine/logs"
"github.com/akyaiy/GoSally-mvp/internal/server/rpc" "github.com/akyaiy/GoSally-mvp/internal/server/rpc"
lua "github.com/yuin/gopher-lua" lua "github.com/yuin/gopher-lua"
) )
func (h *HandlerV1) handleLUA(path string, req *rpc.RPCRequest) *rpc.RPCResponse { func addInitiatorHeaders(req *http.Request, headers http.Header) {
clientIP := req.RemoteAddr
if forwardedFor := req.Header.Get("X-Forwarded-For"); forwardedFor != "" {
clientIP = forwardedFor
}
headers.Set("X-Initiator-IP", clientIP)
headers.Set("X-Initiator-Host", req.Host)
headers.Set("X-Initiator-User-Agent", req.UserAgent())
headers.Set("X-Initiator-Referer", req.Referer())
}
func (h *HandlerV1) handleLUA(r *http.Request, req *rpc.RPCRequest, path string) *rpc.RPCResponse {
L := lua.NewState() L := lua.NewState()
defer L.Close() defer L.Close()
@@ -68,6 +83,129 @@ func (h *HandlerV1) handleLUA(path string, req *rpc.RPCRequest) *rpc.RPCResponse
L.SetGlobal("Log", logTable) L.SetGlobal("Log", logTable)
net := L.NewTable()
netHttp := L.NewTable()
L.SetField(netHttp, "Get", L.NewFunction(func(L *lua.LState) int {
logRequest := L.ToBool(1)
url := L.ToString(2)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
addInitiatorHeaders(r, req.Header)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
if logRequest {
h.x.SLog.Info("HTTP GET request",
slog.String("script", path),
slog.String("url", url),
slog.Int("status", resp.StatusCode),
slog.String("status_text", resp.Status),
slog.String("initiator_ip", req.Header.Get("X-Initiator-IP")),
)
}
result := L.NewTable()
L.SetField(result, "status", lua.LNumber(resp.StatusCode))
L.SetField(result, "status_text", lua.LString(resp.Status))
L.SetField(result, "body", lua.LString(body))
L.SetField(result, "content_length", lua.LNumber(resp.ContentLength))
headers := L.NewTable()
for k, v := range resp.Header {
L.SetField(headers, k, ConvertGolangTypesToLua(L, v))
}
L.SetField(result, "headers", headers)
L.Push(result)
return 1
}))
L.SetField(netHttp, "Post", L.NewFunction(func(L *lua.LState) int {
logRequest := L.ToBool(1)
url := L.ToString(2)
contentType := L.ToString(3)
payload := L.ToString(4)
body := strings.NewReader(payload)
req, err := http.NewRequest("POST", url, body)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
req.Header.Set("Content-Type", contentType)
addInitiatorHeaders(r, req.Header)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
if logRequest {
h.x.SLog.Info("HTTP POST request",
slog.String("script", path),
slog.String("url", url),
slog.String("content_type", contentType),
slog.Int("status", resp.StatusCode),
slog.String("status_text", resp.Status),
slog.String("initiator_ip", req.Header.Get("X-Initiator-IP")),
)
}
result := L.NewTable()
L.SetField(result, "status", lua.LNumber(resp.StatusCode))
L.SetField(result, "status_text", lua.LString(resp.Status))
L.SetField(result, "body", lua.LString(respBody))
L.SetField(result, "content_length", lua.LNumber(resp.ContentLength))
headers := L.NewTable()
for k, v := range resp.Header {
L.SetField(headers, k, ConvertGolangTypesToLua(L, v))
}
L.SetField(result, "headers", headers)
L.Push(result)
return 1
}))
L.SetField(net, "Http", netHttp)
L.SetGlobal("Net", net)
prep := filepath.Join(*h.x.Config.Conf.ComDir, "_prepare.lua") prep := filepath.Join(*h.x.Config.Conf.ComDir, "_prepare.lua")
if _, err := os.Stat(prep); err == nil { if _, err := os.Stat(prep); err == nil {
if err := L.DoFile(prep); err != nil { if err := L.DoFile(prep); err != nil {