From 98790dbe3b70926880d5435a00137d3b5639a8bd Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 22 Oct 2026 18:58:14 +0000 Subject: [PATCH] rewrite using net/http --- app/app.go | 53 ++++++++-------- app/common/utils.go | 65 ++++++++++++-------- app/routes/account.go | 24 +++++--- app/routes/backups.go | 55 +++++++++++------ app/routes/config.go | 136 +++++++++++++++++++++++++---------------- app/routes/index.go | 47 +++++++++----- app/routes/login.go | 18 ++++-- app/routes/settings.go | 27 ++++++-- go.mod | 34 +---------- 9 files changed, 270 insertions(+), 189 deletions(-) diff --git a/app/app.go b/app/app.go index c4fc411..ecf9d45 100644 --- a/app/app.go +++ b/app/app.go @@ -4,12 +4,11 @@ import ( "flag" "fmt" "log" + "net/http" "proxmoxaas-dashboard/app/common" "proxmoxaas-dashboard/app/routes" - "strings" "web" // go will complain here until the first build - "github.com/gin-gonic/gin" "github.com/tdewolff/minify/v2" ) @@ -19,44 +18,42 @@ func Run() { common.Global = common.GetConfig(*configPath) - // setup gin - gin.SetMode(gin.ReleaseMode) - router := gin.Default() + // setup http router + router := http.NewServeMux() // setup static resources m := common.InitMinify() ServeStatic(router, m) html := common.MinifyStatic(m, web.Templates) - common.TMPL = common.LoadHTMLToGin(router, html) + common.TMPL = common.LoadHTML(html) // dynamic routes for pages and page fragments - router.GET("/", routes.HandleGETIndex) - router.GET("/index", routes.HandleGETIndex) - router.GET("/index/instances", routes.HandleGETInstancesFragment) - router.GET("/account", routes.HandleGETAccount) - router.GET("/config", routes.HandleGETConfig) - router.GET("/config/volumes", routes.HandleGETConfigVolumesFragment) - router.GET("/config/nets", routes.HandleGETConfigNetsFragment) - router.GET("/config/devices", routes.HandleGETConfigDevicesFragment) - router.GET("/config/boot", routes.HandleGETConfigBootFragment) - router.GET("/backups", routes.HandleGETBackups) - router.GET("/backups/backups", routes.HandleGETBackupsFragment) - router.GET("/login", routes.HandleGETLogin) - router.GET("/settings", routes.HandleGETSettings) + router.HandleFunc("GET /", routes.HandleGETIndex) + router.HandleFunc("GET /index", routes.HandleGETIndex) + router.HandleFunc("GET /index/instances", routes.HandleGETInstancesFragment) + router.HandleFunc("GET /account", routes.HandleGETAccount) + router.HandleFunc("GET /config", routes.HandleGETConfig) + router.HandleFunc("GET /config/volumes", routes.HandleGETConfigVolumesFragment) + router.HandleFunc("GET /config/nets", routes.HandleGETConfigNetsFragment) + router.HandleFunc("GET /config/devices", routes.HandleGETConfigDevicesFragment) + router.HandleFunc("GET /config/boot", routes.HandleGETConfigBootFragment) + router.HandleFunc("GET /backups", routes.HandleGETBackups) + router.HandleFunc("GET /backups/backups", routes.HandleGETBackupsFragment) + router.HandleFunc("GET /login", routes.HandleGETLogin) + router.HandleFunc("GET /settings", routes.HandleGETSettings) // run on all interfaces with port - log.Fatal("[ERR ] starting gin router: ", router.Run(fmt.Sprintf("0.0.0.0:%d", common.Global.Port))) + log.Fatal("[ERR ] starting gin router: ", http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", common.Global.Port), router)) } // setup static resources under web (css, images, modules, scripts) -func ServeStatic(router *gin.Engine, m *minify.M) { +func ServeStatic(router *http.ServeMux, m *minify.M) { static := common.MinifyStatic(m, web.Static) - router.GET("/websrc/*path", func(c *gin.Context) { - path, _ := c.Params.Get("path") - trimed_path := strings.Replace(path, "/", "", 1) // replace leading "/" captured by *path - data := static[trimed_path] - fmt.Println(path) - c.Header("Content-Encoding", data.MimeType.Encoding) - c.Data(200, data.MimeType.Type, []byte(data.Data)) + router.HandleFunc("GET /websrc/{path...}", func(w http.ResponseWriter, r *http.Request) { + path := r.PathValue("path") + data := static[path] + w.Header().Set("Content-Encoding", data.MimeType.Encoding) + w.Header().Set("Content-Type", data.MimeType.Type) + w.Write([]byte(data.Data)) }) } diff --git a/app/common/utils.go b/app/common/utils.go index e291747..28e9081 100644 --- a/app/common/utils.go +++ b/app/common/utils.go @@ -16,7 +16,6 @@ import ( "strconv" "strings" - "github.com/gin-gonic/gin" "github.com/tdewolff/minify/v2" paas "proxmoxaas-common-lib" @@ -103,9 +102,8 @@ func MinifyStatic(m *minify.M, files embed.FS) map[string]StaticFile { } } -func LoadHTMLToGin(engine *gin.Engine, html map[string]StaticFile) *template.Template { - root := template.New("") - engine.FuncMap = template.FuncMap{ +func LoadHTML(html map[string]StaticFile) *template.Template { + funcMap := template.FuncMap{ "MapKeys": func(x any, sep string) string { v := reflect.ValueOf(x) keys := v.MapKeys() @@ -133,9 +131,11 @@ func LoadHTMLToGin(engine *gin.Engine, html map[string]StaticFile) *template.Tem return dict, nil }, } - tmpl := template.Must(root, LoadAndAddToRoot(engine.FuncMap, root, html)) - engine.SetHTMLTemplate(root) - return tmpl + root := template.New("").Funcs(funcMap) + if err := LoadAndAddToRoot(funcMap, root, html); err != nil { + log.Fatal(err) + } + return root } func LoadAndAddToRoot(FuncMap template.FuncMap, root *template.Template, html map[string]StaticFile) error { @@ -170,9 +170,9 @@ func TemplateMinifier(m *minify.M, w io.Writer, r io.Reader, _ map[string]string return nil } -func HandleNonFatalError(c *gin.Context, err error) { +func HandleNonFatalError(w http.ResponseWriter, err error) { log.Printf("[WARN] encountered a non-fatal error: %s", err.Error()) - c.Status(http.StatusInternalServerError) + w.WriteHeader(http.StatusInternalServerError) } func RequestGetAPI(path string, auth *paas.Auth, body any) (*http.Response, int, error) { @@ -221,25 +221,41 @@ func RequestGetAPI(path string, auth *paas.Auth, body any) (*http.Response, int, return response, response.StatusCode, nil } -func GetAuthFromRequest(c *gin.Context) (paas.Auth, error) { - _, errAuth := c.Cookie("auth") - username, errUsername := c.Cookie("username") - token, errToken := c.Cookie("PVEAuthCookie") - csrf, errCSRF := c.Cookie("CSRFPreventionToken") - access, errAccess := c.Cookie("PAASAccessManagerTicket") - if errUsername != nil || errAuth != nil || errToken != nil || errCSRF != nil || errAccess != nil { - return paas.Auth{}, fmt.Errorf("error occured getting user cookies: (auth: %s, token: %s, csrf: %s)", errAuth, errToken, errCSRF) - } else { - return paas.Auth{Username: username, Token: token, CSRF: csrf, AccessManagerTicket: access}, nil +func GetAuthFromRequest(r *http.Request) (paas.Auth, error) { + _, errAuth := r.Cookie("auth") + username, errUsername := r.Cookie("username") + token, errToken := r.Cookie("PVEAuthCookie") + csrf, errCSRF := r.Cookie("CSRFPreventionToken") + access, errAccess := r.Cookie("PAASAccessManagerTicket") + + if errUsername != nil || errAuth != nil || errToken != nil || + errCSRF != nil || errAccess != nil { + return paas.Auth{}, fmt.Errorf( + "error occurred getting user cookies: (auth: %v, token: %v, csrf: %v)", + errAuth, errToken, errCSRF, + ) } + + return paas.Auth{ + Username: username.Value, + Token: token.Value, + CSRF: csrf.Value, + AccessManagerTicket: access.Value, + }, nil } -func GetInstancePathFromRequest(c *gin.Context) (paas.InstancePath, error) { - req_node := c.Query("node") - req_type := c.Query("type") - req_vmid := c.Query("vmid") +func GetInstancePathFromRequest(r *http.Request) (paas.InstancePath, error) { + query := r.URL.Query() + + req_node := query.Get("node") + req_type := query.Get("type") + req_vmid := query.Get("vmid") + if req_node == "" || req_type == "" || req_vmid == "" { - return paas.InstancePath{}, fmt.Errorf("request missing required values: (node: %s, type: %s, vmid: %s)", req_node, req_type, req_vmid) + return paas.InstancePath{}, fmt.Errorf( + "request missing required values: (node: %s, type: %s, vmid: %s)", + req_node, req_type, req_vmid, + ) } vmid_int, err := strconv.ParseUint(req_vmid, 10, 64) @@ -252,6 +268,7 @@ func GetInstancePathFromRequest(c *gin.Context) (paas.InstancePath, error) { InstanceType: paas.InstanceType(req_type), InstanceID: paas.InstanceID(vmid_int), } + return vm_path, nil } diff --git a/app/routes/account.go b/app/routes/account.go index 159f560..c075040 100644 --- a/app/routes/account.go +++ b/app/routes/account.go @@ -1,13 +1,13 @@ package routes import ( + "bytes" "fmt" "net/http" paas "proxmoxaas-common-lib" "proxmoxaas-dashboard/app/common" "github.com/gerow/go-color" - "github.com/gin-gonic/gin" "github.com/go-viper/mapstructure/v2" ) @@ -40,29 +40,39 @@ var Green = color.RGB{ B: 0, } -func HandleGETAccount(c *gin.Context) { - auth, err := common.GetAuthFromRequest(c) +func HandleGETAccount(w http.ResponseWriter, r *http.Request) { + auth, err := common.GetAuthFromRequest(r) if err == nil { user, err := GetUserBasic(auth) if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) return } pools, err := GetUserPools(auth) if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) return } - c.HTML(http.StatusOK, "html/account.html", gin.H{ + w.Header().Set("Content-Type", "text/html") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/account.html", map[string]any{ "global": common.Global, "page": "account", "user": user, "pools": pools, }) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } else { + w.Write(body.Bytes()) + return + } } else { - c.Redirect(http.StatusFound, "/login") // if user is not authed, redirect user to login page + http.Redirect(w, r, "/login", http.StatusFound) // if user is not authed, redirect user to login page + return } } diff --git a/app/routes/backups.go b/app/routes/backups.go index 910326a..1165877 100644 --- a/app/routes/backups.go +++ b/app/routes/backups.go @@ -1,13 +1,13 @@ package routes import ( + "bytes" "fmt" "net/http" paas "proxmoxaas-common-lib" "proxmoxaas-dashboard/app/common" "time" - "github.com/gin-gonic/gin" "github.com/go-viper/mapstructure/v2" ) @@ -20,61 +20,78 @@ type InstanceBackup struct { TimeFormatted string } -func HandleGETBackups(c *gin.Context) { - auth, err := common.GetAuthFromRequest(c) +func HandleGETBackups(w http.ResponseWriter, r *http.Request) { + auth, err := common.GetAuthFromRequest(r) if err == nil { - vm_path, err := common.GetInstancePathFromRequest(c) + vm_path, err := common.GetInstancePathFromRequest(r) if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) return } backups, err := GetInstanceBackups(vm_path, auth) if err != nil { - common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance backups: %s", err.Error())) + common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance backups: %s", err.Error())) + return } config, err := GetInstanceConfig(vm_path, auth) // only used for the VM's name if err != nil { - common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + return } - c.HTML(http.StatusOK, "html/backups.html", gin.H{ + w.Header().Set("Content-Type", "text/html") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/index.html", map[string]any{ "global": common.Global, "page": "backups", "backups": backups, "config": config, }) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } else { + w.Write(body.Bytes()) + return + } } else { - c.Redirect(http.StatusFound, "/login") + http.Redirect(w, r, "/login", http.StatusFound) + return } } -func HandleGETBackupsFragment(c *gin.Context) { - auth, err := common.GetAuthFromRequest(c) +func HandleGETBackupsFragment(w http.ResponseWriter, r *http.Request) { + auth, err := common.GetAuthFromRequest(r) if err == nil { // user should be authed, try to return index with population - vm_path, err := common.GetInstancePathFromRequest(c) + vm_path, err := common.GetInstancePathFromRequest(r) if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) return } backups, err := GetInstanceBackups(vm_path, auth) if err != nil { - common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance backups: %s", err.Error())) + common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance backups: %s", err.Error())) + return } - c.Header("Content-Type", "text/plain") - err = common.TMPL.ExecuteTemplate(c.Writer, "html/backups-backups.go.tmpl", gin.H{ + w.Header().Set("Content-Type", "text/plain") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/backups-backups.go.tmpl", map[string]any{ "backups": backups, }) if err != nil { - c.Status(http.StatusInternalServerError) + w.WriteHeader(http.StatusInternalServerError) + return } else { - c.Status(http.StatusOK) + w.Write(body.Bytes()) + return } } else { // return 401 - c.Status(http.StatusUnauthorized) + w.WriteHeader(http.StatusUnauthorized) + return } } diff --git a/app/routes/config.go b/app/routes/config.go index 4645e28..994c6cf 100644 --- a/app/routes/config.go +++ b/app/routes/config.go @@ -1,6 +1,7 @@ package routes import ( + "bytes" "fmt" "net/http" paas "proxmoxaas-common-lib" @@ -8,7 +9,6 @@ import ( "slices" "sort" - "github.com/gin-gonic/gin" "github.com/go-viper/mapstructure/v2" ) @@ -31,24 +31,26 @@ type PoolConfig struct { } } -func HandleGETConfig(c *gin.Context) { - auth, err := common.GetAuthFromRequest(c) +func HandleGETConfig(w http.ResponseWriter, r *http.Request) { + auth, err := common.GetAuthFromRequest(r) if err == nil { - vm_path, err := common.GetInstancePathFromRequest(c) + vm_path, err := common.GetInstancePathFromRequest(r) if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) return } config, err := GetInstanceConfig(vm_path, auth) if err != nil { - common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + return } if config.Type == "VM" { // if VM, fetch CPU types from node config.ProctypeSelect, err = GetCPUTypes(vm_path, config.Pool, auth) if err != nil { - common.HandleNonFatalError(c, fmt.Errorf("error encountered getting proctypes: %s", err.Error())) + common.HandleNonFatalError(w, fmt.Errorf("error encountered getting proctypes: %s", err.Error())) + return } } for i, cpu := range config.ProctypeSelect.Options { @@ -57,125 +59,155 @@ func HandleGETConfig(c *gin.Context) { } } - c.HTML(http.StatusOK, "html/config.html", gin.H{ + w.Header().Set("Content-Type", "text/html") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/config.html", map[string]any{ "global": common.Global, "page": "config", "config": config, }) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } else { + w.Write(body.Bytes()) + return + } } else { - c.Redirect(http.StatusFound, "/login") + http.Redirect(w, r, "/login", http.StatusFound) + return } } -func HandleGETConfigVolumesFragment(c *gin.Context) { - auth, err := common.GetAuthFromRequest(c) +func HandleGETConfigVolumesFragment(w http.ResponseWriter, r *http.Request) { + auth, err := common.GetAuthFromRequest(r) if err == nil { - vm_path, err := common.GetInstancePathFromRequest(c) + vm_path, err := common.GetInstancePathFromRequest(r) if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) return } config, err := GetInstanceConfig(vm_path, auth) if err != nil { - common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + return } - c.Header("Content-Type", "text/plain") - err = common.TMPL.ExecuteTemplate(c.Writer, "html/config-volumes.go.tmpl", gin.H{ + w.Header().Set("Content-Type", "text/plain") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/config-volumes.go.tmpl", map[string]any{ "config": config, }) if err != nil { - c.Status(http.StatusInternalServerError) + w.WriteHeader(http.StatusInternalServerError) + return } else { - c.Status(http.StatusOK) + w.Write(body.Bytes()) + return } } else { - c.Status(http.StatusUnauthorized) + w.WriteHeader(http.StatusUnauthorized) + return } } -func HandleGETConfigNetsFragment(c *gin.Context) { - auth, err := common.GetAuthFromRequest(c) +func HandleGETConfigNetsFragment(w http.ResponseWriter, r *http.Request) { + auth, err := common.GetAuthFromRequest(r) if err == nil { - vm_path, err := common.GetInstancePathFromRequest(c) + vm_path, err := common.GetInstancePathFromRequest(r) if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) return } config, err := GetInstanceConfig(vm_path, auth) if err != nil { - common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + return } - c.Header("Content-Type", "text/plain") - err = common.TMPL.ExecuteTemplate(c.Writer, "html/config-nets.go.tmpl", gin.H{ + w.Header().Set("Content-Type", "text/plain") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/config-nets.go.tmpl", map[string]any{ "config": config, }) if err != nil { - c.Status(http.StatusInternalServerError) + w.WriteHeader(http.StatusInternalServerError) + return } else { - c.Status(http.StatusOK) + w.Write(body.Bytes()) + return } - } else { - c.Status(http.StatusUnauthorized) + } else { // return 401 + w.WriteHeader(http.StatusUnauthorized) + return } } -func HandleGETConfigDevicesFragment(c *gin.Context) { - auth, err := common.GetAuthFromRequest(c) +func HandleGETConfigDevicesFragment(w http.ResponseWriter, r *http.Request) { + auth, err := common.GetAuthFromRequest(r) if err == nil { - vm_path, err := common.GetInstancePathFromRequest(c) + vm_path, err := common.GetInstancePathFromRequest(r) if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) return } config, err := GetInstanceConfig(vm_path, auth) if err != nil { - common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + return } - c.Header("Content-Type", "text/plain") - err = common.TMPL.ExecuteTemplate(c.Writer, "html/config-devices.go.tmpl", gin.H{ + w.Header().Set("Content-Type", "text/plain") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/config-devices.go.tmpl", map[string]any{ "config": config, }) if err != nil { - c.Status(http.StatusInternalServerError) + w.WriteHeader(http.StatusInternalServerError) + return } else { - c.Status(http.StatusOK) + w.Write(body.Bytes()) + return } - } else { - c.Status(http.StatusUnauthorized) + } else { // return 401 + w.WriteHeader(http.StatusUnauthorized) + return } } -func HandleGETConfigBootFragment(c *gin.Context) { - auth, err := common.GetAuthFromRequest(c) +func HandleGETConfigBootFragment(w http.ResponseWriter, r *http.Request) { + auth, err := common.GetAuthFromRequest(r) if err == nil { - vm_path, err := common.GetInstancePathFromRequest(c) + vm_path, err := common.GetInstancePathFromRequest(r) if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) return } config, err := GetInstanceConfig(vm_path, auth) if err != nil { - common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error())) + return } - c.Header("Content-Type", "text/plain") - err = common.TMPL.ExecuteTemplate(c.Writer, "html/config-boot.go.tmpl", gin.H{ + w.Header().Set("Content-Type", "text/plain") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/config-boot.go.tmpl", map[string]any{ "config": config, }) if err != nil { - c.Status(http.StatusInternalServerError) + w.WriteHeader(http.StatusInternalServerError) + return } else { - c.Status(http.StatusOK) + w.Write(body.Bytes()) + return } - } else { - c.Status(http.StatusUnauthorized) + } else { // return 401 + w.WriteHeader(http.StatusUnauthorized) + return } } diff --git a/app/routes/index.go b/app/routes/index.go index 4dca59f..9b7cac2 100644 --- a/app/routes/index.go +++ b/app/routes/index.go @@ -1,13 +1,13 @@ package routes import ( + "bytes" "fmt" "net/http" paas "proxmoxaas-common-lib" "proxmoxaas-dashboard/app/common" "strconv" - "github.com/gin-gonic/gin" "github.com/go-viper/mapstructure/v2" ) @@ -45,46 +45,61 @@ type InstanceStatus struct { Status string } -func HandleGETIndex(c *gin.Context) { - auth, err := common.GetAuthFromRequest(c) +func HandleGETIndex(w http.ResponseWriter, r *http.Request) { + auth, err := common.GetAuthFromRequest(r) if err == nil { // user should be authed, try to return index with population instances, _, err := GetClusterResources(auth) if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) return } - page := gin.H{ + page := map[string]any{ "global": common.Global, "page": "index", "instances": instances, } - c.HTML(http.StatusOK, "html/index.html", page) + + w.Header().Set("Content-Type", "text/html") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/index.html", page) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } else { + w.Write(body.Bytes()) + return + } } else { // return index without populating - c.Redirect(http.StatusFound, "/login") // if user is not authed, redirect user to login page + http.Redirect(w, r, "/login", http.StatusFound) + return } } -func HandleGETInstancesFragment(c *gin.Context) { - auth, err := common.GetAuthFromRequest(c) +func HandleGETInstancesFragment(w http.ResponseWriter, r *http.Request) { + auth, err := common.GetAuthFromRequest(r) if err == nil { // user should be authed, try to return index with population instances, _, err := GetClusterResources(auth) if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) return } - c.Header("Content-Type", "text/plain") - err = common.TMPL.ExecuteTemplate(c.Writer, "html/index-instances.go.tmpl", gin.H{ + + w.Header().Set("Content-Type", "text/plain") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/index-instances.go.tmpl", map[string]any{ "instances": instances, }) if err != nil { - c.Status(http.StatusInternalServerError) + w.WriteHeader(http.StatusInternalServerError) + return } else { - c.Status(http.StatusOK) + w.Write(body.Bytes()) + return } } else { // return 401 - c.Status(http.StatusUnauthorized) + w.WriteHeader(http.StatusUnauthorized) + return } - } func GetClusterResources(auth paas.Auth) (map[uint]InstanceCard, map[string]Node, error) { diff --git a/app/routes/login.go b/app/routes/login.go index 8157f21..3c4594c 100644 --- a/app/routes/login.go +++ b/app/routes/login.go @@ -1,11 +1,11 @@ package routes import ( + "bytes" "fmt" "net/http" "proxmoxaas-dashboard/app/common" - "github.com/gin-gonic/gin" "github.com/go-viper/mapstructure/v2" ) @@ -41,10 +41,11 @@ func GetLoginRealms() ([]Realm, error) { return realms, nil } -func HandleGETLogin(c *gin.Context) { +func HandleGETLogin(w http.ResponseWriter, r *http.Request) { realms, err := GetLoginRealms() if err != nil { - common.HandleNonFatalError(c, err) + common.HandleNonFatalError(w, err) + return } sel := common.Select{ @@ -60,9 +61,18 @@ func HandleGETLogin(c *gin.Context) { }) } - c.HTML(http.StatusOK, "html/login.html", gin.H{ + w.Header().Set("Content-Type", "text/html") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/login.html", map[string]any{ "global": common.Global, "page": "login", "realms": sel, }) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } else { + w.Write(body.Bytes()) + return + } } diff --git a/app/routes/settings.go b/app/routes/settings.go index 2b021e5..18bed57 100644 --- a/app/routes/settings.go +++ b/app/routes/settings.go @@ -1,20 +1,35 @@ package routes import ( + "bytes" "net/http" "proxmoxaas-dashboard/app/common" - - "github.com/gin-gonic/gin" ) -func HandleGETSettings(c *gin.Context) { - _, err := common.GetAuthFromRequest(c) +func HandleGETSettings(w http.ResponseWriter, r *http.Request) { + auth, err := common.GetAuthFromRequest(r) if err == nil { - c.HTML(http.StatusOK, "html/settings.html", gin.H{ + _, err := GetUserBasic(auth) + if err != nil { + common.HandleNonFatalError(w, err) + return + } + + w.Header().Set("Content-Type", "text/html") + body := bytes.Buffer{} + err = common.TMPL.ExecuteTemplate(&body, "html/settings.html", map[string]any{ "global": common.Global, "page": "settings", }) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } else { + w.Write(body.Bytes()) + return + } } else { - c.Redirect(http.StatusFound, "/login") + http.Redirect(w, r, "/login", http.StatusFound) + return } } diff --git a/go.mod b/go.mod index 49701e4..f4a77e5 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.27.0 require ( github.com/gerow/go-color v0.0.0-20140219113758-125d37f527f1 - github.com/gin-gonic/gin v1.12.0 github.com/go-viper/mapstructure/v2 v2.5.0 github.com/tdewolff/minify/v2 v2.24.17 proxmoxaas-common-lib v0.0.0 @@ -15,35 +14,4 @@ replace proxmoxaas-common-lib => ./proxmoxaas-common-lib replace web => ./dist/web -require ( - github.com/bytedance/gopkg v0.1.4 // indirect - github.com/bytedance/sonic v1.15.2 // indirect - github.com/bytedance/sonic/loader v0.5.2 // indirect - github.com/cloudwego/base64x v0.1.7 // indirect - github.com/gabriel-vasile/mimetype v1.4.15 // indirect - github.com/gin-contrib/sse v1.1.1 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.30.3 // indirect - github.com/goccy/go-json v0.10.6 // indirect - github.com/goccy/go-yaml v1.19.2 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.4.0 // indirect - github.com/leodido/go-urn v1.5.0 // indirect - github.com/mattn/go-isatty v0.0.24 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.4.3 // indirect - github.com/quic-go/qpack v0.6.0 // indirect - github.com/quic-go/quic-go v0.61.0 // indirect - github.com/tdewolff/parse/v2 v2.8.16 // indirect - github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.3.2 // indirect - go.mongodb.org/mongo-driver/v2 v2.8.1 // indirect - golang.org/x/arch v0.30.0 // indirect - golang.org/x/crypto v0.55.0 // indirect - golang.org/x/net v0.58.0 // indirect - golang.org/x/sys v0.47.0 // indirect - golang.org/x/text v0.41.0 // indirect - google.golang.org/protobuf v1.36.12 // indirect -) +require github.com/tdewolff/parse/v2 v2.8.16 // indirect