package main import ( // External "git.ahall.se/go/html_template" // Standard "encoding/json" "fmt" "io" "io/fs" "net/http" "strconv" ) var ( engine HTMLTemplate.Engine ) func initWebserver() (err error) { address := fmt.Sprintf("%s:%d", config.Network.Address, config.Network.Port) logger.Info("webserver", "listen", address) subViewFS, _ := fs.Sub(viewFS, "views") subStaticFS, _ := fs.Sub(staticFS, "static") engine, err = HTMLTemplate.NewEngine(subViewFS, subStaticFS, flagDev) if err != nil { return } http.HandleFunc("/", pageIndex) http.HandleFunc("/app", pageApp) http.HandleFunc("/nodes/tree/{startNode}", actionNodesTree) http.HandleFunc("/nodes/{nodeID}", actionNode) http.HandleFunc("/nodes/update/{nodeID}", actionNodeUpdate) http.HandleFunc("/types/{typeID}", actionType) http.HandleFunc("/types/", actionTypesAll) err = http.ListenAndServe(address, nil) return } func httpError(w http.ResponseWriter, err error) { // {{{ out := struct { OK bool Error string }{ false, err.Error(), } j, _ := json.Marshal(out) w.Write(j) } // }}} func pageIndex(w http.ResponseWriter, r *http.Request) { // {{{ if r.URL.Path == "/" { http.Redirect(w, r, "/app", http.StatusSeeOther) } else { engine.StaticResource(w, r) } } // }}} func pageApp(w http.ResponseWriter, r *http.Request) { // {{{ page := NewPage("app") err := engine.Render(page, w, r) if err != nil { w.Write([]byte(err.Error())) } } // }}} func actionNodesTree(w http.ResponseWriter, r *http.Request) { // {{{ var err error startNode := 0 startNodeStr := r.PathValue("startNode") startNode, _ = strconv.Atoi(startNodeStr) var maxDepth int if maxDepth, err = strconv.Atoi(r.URL.Query().Get("depth")); err != nil { maxDepth = 3 } topNode, err := GetNodeTree(startNode, maxDepth) if err != nil { httpError(w, err) return } out := struct { OK bool Nodes *Node }{ true, topNode, } j, _ := json.Marshal(out) w.Write(j) } // }}} func actionNode(w http.ResponseWriter, r *http.Request) { // {{{ nodeID := 0 nodeIDStr := r.PathValue("nodeID") nodeID, _ = strconv.Atoi(nodeIDStr) node, err := GetNode(nodeID) if err != nil { httpError(w, err) return } out := struct { OK bool Node Node }{ true, node, } j, _ := json.Marshal(out) w.Write(j) } // }}} func actionNodeUpdate(w http.ResponseWriter, r *http.Request) { // {{{ nodeID := 0 nodeIDStr := r.PathValue("nodeID") nodeID, _ = strconv.Atoi(nodeIDStr) data, _ := io.ReadAll(r.Body) err := UpdateNode(nodeID, data) if err != nil { httpError(w, err) return } out := struct { OK bool }{ true, } j, _ := json.Marshal(out) w.Write(j) } // }}} func actionType(w http.ResponseWriter, r *http.Request) { // {{{ typeID := 0 typeIDStr := r.PathValue("typeID") typeID, _ = strconv.Atoi(typeIDStr) typ, err := GetType(typeID) if err != nil { httpError(w, err) return } j, _ := json.Marshal(typ) w.Write(j) } // }}} func actionTypesAll(w http.ResponseWriter, r *http.Request) { // {{{ types, err := GetTypes() if err != nil { httpError(w, err) return } out := struct { OK bool Types []NodeType }{ true, types, } j, _ := json.Marshal(out) w.Write(j) } // }}} // vim: foldmethod=marker