Compare commits

...

5 Commits

Author SHA1 Message Date
20bb90e77a oh again update Get example 2025-07-31 20:51:30 +03:00
148ca53538 update Net.Http.Get example 2025-07-31 20:46:02 +03:00
2951fd2da9 add Net.Http.Get usage example 2025-07-31 20:39:44 +03:00
f411637520 add Net.Http to lua 2025-07-31 20:37:31 +03:00
75ee6e10aa change http server log level to LevelError 2025-07-31 19:48:06 +03:00
5 changed files with 204 additions and 4 deletions

26
com/Net/GetExpl.lua Normal file
View File

@@ -0,0 +1,26 @@
local reqAddr
local logReq = true
if In.Params and In.Params.url then
reqAddr = In.Params.url
else
Out.Error = {
code = -32602,
message = "no url provided"
}
return
end
local resp = Net.Http.Get(logReq, reqAddr)
if resp then
Out.Result.answer = {
status = resp.status,
body = resp.body
}
return
end
Out.Result.answer = {
status = resp.status
}

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

@@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"log" "log"
"log/slog"
"net" "net"
"net/http" "net/http"
"regexp" "regexp"
@@ -86,7 +87,7 @@ func RunHook(ctx context.Context, cs *corestate.CoreState, x *app.AppX) error {
Handler: r, Handler: r,
ErrorLog: log.New(&logs.SlogWriter{ ErrorLog: log.New(&logs.SlogWriter{
Logger: x.SLog, Logger: x.SLog,
Level: logs.GlobalLevel, Level: slog.LevelError,
}, "", 0), }, "", 0),
} }

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 {