From 97a480249e7c8f605efd7a4252449791eabc90a8 Mon Sep 17 00:00:00 2001 From: unwox Date: Thu, 6 Jun 2024 16:08:13 +0600 Subject: refactor main.go into several files --- worker.go | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 worker.go (limited to 'worker.go') diff --git a/worker.go b/worker.go new file mode 100644 index 0000000..d125f17 --- /dev/null +++ b/worker.go @@ -0,0 +1,144 @@ +package main + +import ( + "errors" + "io" + "net/http" +) + +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? +} -- cgit v1.2.3