diff options
Diffstat (limited to 'http_server.go')
| -rw-r--r-- | http_server.go | 70 |
1 files changed, 49 insertions, 21 deletions
diff --git a/http_server.go b/http_server.go index 04ac90a..a574cfa 100644 --- a/http_server.go +++ b/http_server.go @@ -4,7 +4,6 @@ package awwan import ( - "bytes" "encoding/json" "errors" "fmt" @@ -39,6 +38,9 @@ const DefListenAddress = `127.0.0.1:17600` type httpServer struct { *libhttp.Server + // idExecRes contains the execution ID and its response. + idExecRes map[string]*ExecResponse + aww *Awwan memfsBase *memfs.MemFS // The files caches. @@ -53,6 +55,8 @@ func newHttpServer(aww *Awwan, address string) (httpd *httpServer, err error) { ) httpd = &httpServer{ + idExecRes: make(map[string]*ExecResponse), + aww: aww, baseDir: aww.BaseDir, } @@ -168,7 +172,7 @@ func (httpd *httpServer) registerEndpoints() (err error) { Path: pathAwwanApiExecute, RequestType: libhttp.RequestTypeJSON, ResponseType: libhttp.ResponseTypeJSON, - Call: httpd.awwanApiExecute, + Call: httpd.Execute, }) if err != nil { return fmt.Errorf("%s: %w", logp, err) @@ -608,9 +612,33 @@ func (httpd *httpServer) awwanApiFsPut(epr *libhttp.EndpointRequest) (rawBody [] return json.Marshal(res) } -func (httpd *httpServer) awwanApiExecute(epr *libhttp.EndpointRequest) (resb []byte, err error) { +// Execute request to execute the script. +// +// Request format, +// +// POST /awwan/api/execute +// Content-Type: application/json +// +// { +// "mode": <string>, +// "script": <string>, +// "line_range": <string +// } +// +// On success it will return the state of execution, +// +// Content-Type: application/json +// +// { +// "code": 200, +// "data": <ExecResponse> +// } +// +// The ExecResponse contains ID that can be used to fetch the latest state +// of execution or to stream output. +func (httpd *httpServer) Execute(epr *libhttp.EndpointRequest) (resb []byte, err error) { var ( - logp = "awwanApiExecute" + logp = `Execute` req = &ExecRequest{} res = &libhttp.EndpointResponse{} ) @@ -629,29 +657,29 @@ func (httpd *httpServer) awwanApiExecute(epr *libhttp.EndpointRequest) (resb []b return nil, res } - var ( - data = &ExecResponse{ - ExecRequest: req, - } + var execRes = newExecResponse(req) - logw bytes.Buffer - ) + // Encode to JSON first to minimize data race. - req.registerLogWriter(`output`, &logw) + res.Code = http.StatusOK + res.Data = execRes - if req.Mode == CommandModeLocal { - err = httpd.aww.Local(req) - } else { - err = httpd.aww.Play(req) - } + resb, err = json.Marshal(res) if err != nil { - data.Error = err.Error() + res.Message = fmt.Sprintf(`%s: %s`, logp, err) + return nil, res } - data.Output = logw.Bytes() + httpd.idExecRes[execRes.ID] = execRes - res.Code = http.StatusOK - res.Data = data + go func() { + if req.Mode == CommandModeLocal { + err = httpd.aww.Local(req) + } else { + err = httpd.aww.Play(req) + } + execRes.end(err) + }() - return json.Marshal(res) + return resb, nil } |
