diff options
| author | unwox <me@unwox.com> | 2024-06-06 16:08:13 +0600 |
|---|---|---|
| committer | unwox <me@unwox.com> | 2024-06-06 16:08:26 +0600 |
| commit | 97a480249e7c8f605efd7a4252449791eabc90a8 (patch) | |
| tree | cdf6cdad3d05cb22681af039cf6a3a6faf10adcb /main.go | |
| parent | 6ef4939963e85fa044753598cd8456d48a155d4a (diff) | |
refactor main.go into several files
Diffstat (limited to 'main.go')
| -rw-r--r-- | main.go | 259 |
1 files changed, 0 insertions, 259 deletions
@@ -1,269 +1,10 @@ package main import ( - "errors" "fmt" - "io" "log" "net/http" ) -/* -#cgo LDFLAGS: -llua -#include <stdlib.h> -#include <lua.h> -#include <lualib.h> -#include <lauxlib.h> -*/ -import "C" - -import "unsafe" - -type LuaRef C.longlong -type Lua struct { - l *C.lua_State -} - -func (l *Lua) Start () { - l.l = C.luaL_newstate() - C.luaL_openlibs(l.l) -} - -func (l *Lua) Close () { - C.lua_close(l.l) - C.free(unsafe.Pointer(l.l)) -} - -func (l *Lua) Require (file string) (LuaRef, error) { - if !l.LoadFile(file) { - return 0, errors.New("could not open the file") - } - if !l.PCall(0, C.LUA_MULTRET) { - return 0, errors.New("could not execute the file") - } - if !l.IsTable(-1) { - return 0, errors.New("module did not return a table") - } - return l.PopToRef(), nil -} - - -func (l *Lua) PCall (nargs int, nresults int) bool { - res := C.lua_pcallk(l.l, C.int(nargs), C.int(nresults), 0, 0, nil) - return res == C.LUA_OK -} - -func (l *Lua) LoadFile (file string) bool { - cfile := C.CString(file) - defer C.free(unsafe.Pointer(cfile)) - res := C.luaL_loadfilex(l.l, cfile, nil) - return res == C.LUA_OK -} - -func (l *Lua) StackLen () int { - return int(C.lua_gettop(l.l)) -} - -func (l *Lua) ToString (index int) string { - return C.GoString(C.lua_tolstring(l.l, C.int(index), nil)) -} - -func (l *Lua) ToInt (index int) int { - return int(C.lua_tonumberx(l.l, C.int(index), nil)) -} - -func (l *Lua) PopToRef () LuaRef { - return LuaRef(C.luaL_ref(l.l, C.LUA_REGISTRYINDEX)) -} - -func (l *Lua) Pop (n int) { - C.lua_settop(l.l, C.int(-n - 1)) -} - -func (l *Lua) PushNil () { - C.lua_pushnil(l.l) -} - -func (l *Lua) PushString (str string) { - cstr := C.CString(str) - defer C.free(unsafe.Pointer(cstr)) - C.lua_pushstring(l.l, cstr) -} - -func (l *Lua) PushTable (table map[string]string) { - C.lua_createtable(l.l, 0, C.int(len(table))) - for k, v := range table { - l.PushString(v) - C.lua_setfield(l.l, -2, C.CString(k)) - } -} - -func (l *Lua) PushFromRef (ref LuaRef) { - C.lua_rawgeti(l.l, C.LUA_REGISTRYINDEX, C.longlong(ref)); -} - -func (l *Lua) IsString (index int) bool { - return C.lua_isstring(l.l, C.int(index)) == 1 -} - -func (l *Lua) IsNumber (index int) bool { - return C.lua_isnumber(l.l, C.int(index)) == 1 -} - -func (l *Lua) IsFunction (index int) bool { - return C.lua_type(l.l, C.int(index)) == C.LUA_TFUNCTION -} - -func (l *Lua) IsTable (index int) bool { - return C.lua_type(l.l, C.int(index)) == C.LUA_TTABLE -} - -func (l *Lua) Next () bool { - return C.lua_next(l.l, -2) != 0 -} - -func (l *Lua) PushTableItem (key string) { - ckey := C.CString(key) - defer C.free(unsafe.Pointer(ckey)) - C.lua_pushstring(l.l, ckey); - C.lua_gettable(l.l, -2); -} - -type WorkerRequest struct { - Request *http.Request - Route string - result chan *WorkerResponse -} - -type WorkerResponse struct { - Code int - Headers map[string]string - Body string -} - -type Worker struct { - read chan *WorkerRequest - lua *Lua - api LuaRef - routes map[string]LuaRef - started bool -} - -func NewWorker(read chan *WorkerRequest) *Worker { - return &Worker { - read: read, - routes: make(map[string]LuaRef), - lua: &Lua{}, - } -} - -func (w *Worker) Start (filename string) error { - if w.started { - return errors.New("already started") - } - - w.lua.Start() - api, err := w.lua.Require(filename) - if err != nil { - return err - } - w.api = api - w.initRoutes() - - return nil -} - -func (w *Worker) Listen () { - for { - r := <- w.read - handlerRef := w.routes[r.Route] - w.lua.PushFromRef(handlerRef) - w.lua.PushString(r.Request.Method) - w.lua.PushString(r.Request.URL.Path) - - fh := make(map[string]string) - for k := range r.Request.Header { - fh[k] = r.Request.Header.Get(k) - } - w.lua.PushTable(fh) - - body, err := io.ReadAll(r.Request.Body) - if err != nil { - w.lua.Pop(4); - // TODO: 500 - return - } - w.lua.PushString(string(body)) - - w.lua.PCall(4, 3) - code := w.lua.ToInt(-3) - rbody := w.lua.ToString(-1) - - // parse headers - headers := make(map[string]string) - w.lua.Pop(1) - w.lua.PushNil() - for w.lua.Next() { - if !w.lua.IsString(-2) || !w.lua.IsString(-2) { - w.lua.Pop(1) - continue - } - v := w.lua.ToString(-1) - w.lua.Pop(1) - // we must not pop the item key from the stack because - // otherwise C.lua_next won't work properly - k := w.lua.ToString(-1) - headers[k] = v - } - w.lua.Pop(2) - - r.result <- &WorkerResponse { - Code: int(code), - Headers: headers, - Body: rbody, - } - } -} - -func (w *Worker) Request (route string, r *http.Request,) chan *WorkerResponse { - res := make(chan *WorkerResponse) - w.read <- &WorkerRequest{ - Request: r, - Route: route, - result: res, - } - return res -} - -func (w *Worker) ListRoutes() []string { - res := []string{} - for route, _ := range w.routes { - res = append(res, route) - } - return res -} - -func (w *Worker) Stop () { - w.lua.Close() -} - -func (w *Worker) initRoutes() { - w.lua.PushFromRef(w.api) - w.lua.PushTableItem("routes") - // FIXME: istable? - w.lua.PushNil() - for w.lua.Next() { - if !w.lua.IsString(-2) || !w.lua.IsFunction(-1) { - w.lua.Pop(1) - continue - } - handlerRef := w.lua.PopToRef() - // we must not pop the item key from the stack because - // otherwise C.lua_next won't work properly - route := w.lua.ToString(-1) - w.routes[route] = handlerRef - } - // FIXME: pop? -} func main() { rch := make(chan *WorkerRequest, 4096) |
