From 218a8db1b901cc6c7b777c5855c01b15154d932e Mon Sep 17 00:00:00 2001 From: Teej <107083710+TeejMcSteez@users.noreply.github.com> Date: Tue, 11 Nov 2025 22:46:57 -0500 Subject: [PATCH] add favicon to webpages (#2858) Co-authored-by: TeejMcSteez Co-authored-by: Kristoffer Dalby --- CHANGELOG.md | 3 ++- hscontrol/app.go | 4 ++-- hscontrol/assets/favicon.png | Bin 0 -> 22340 bytes hscontrol/handlers.go | 33 ++++++++++++++++++++++++++++++--- hscontrol/templates/general.go | 4 ++++ swagger.go | 5 ++++- 6 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 hscontrol/assets/favicon.png diff --git a/CHANGELOG.md b/CHANGELOG.md index b25c80ee..9129c526 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Changes +- Add favicon to webpages + [#2858](https://github.com/juanfont/headscale/pull/2858) - Reclaim IPs from the IP allocator when nodes are deleted [#2831](https://github.com/juanfont/headscale/pull/2831) @@ -138,7 +140,6 @@ the code base over time and make it more correct and efficient. starting/ending with hyphen are rejected ### Changes - - **Database schema migration improvements for SQLite** [#2617](https://github.com/juanfont/headscale/pull/2617) - **IMPORTANT: Backup your SQLite database before upgrading** diff --git a/hscontrol/app.go b/hscontrol/app.go index eb5528ba..4ce98719 100644 --- a/hscontrol/app.go +++ b/hscontrol/app.go @@ -476,8 +476,8 @@ func (h *Headscale) createRouter(grpcMux *grpcRuntime.ServeMux) *mux.Router { apiRouter := router.PathPrefix("/api").Subrouter() apiRouter.Use(h.httpAuthenticationMiddleware) apiRouter.PathPrefix("/v1/").HandlerFunc(grpcMux.ServeHTTP) - - router.PathPrefix("/").HandlerFunc(notFoundHandler) + router.HandleFunc("/favicon.ico", FaviconHandler) + router.PathPrefix("/").HandlerFunc(BlankHandler) return router } diff --git a/hscontrol/assets/favicon.png b/hscontrol/assets/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..4989810faa546554d0e8a494ce8b980816c46b54 GIT binary patch literal 22340 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 H^o;*2r@Ea? literal 0 HcmV?d00001 diff --git a/hscontrol/handlers.go b/hscontrol/handlers.go index 0cc5bd36..d52b4d50 100644 --- a/hscontrol/handlers.go +++ b/hscontrol/handlers.go @@ -1,6 +1,8 @@ package hscontrol import ( + "bytes" + _ "embed" "encoding/json" "errors" "fmt" @@ -8,6 +10,7 @@ import ( "net/http" "strconv" "strings" + "time" "github.com/chasefleming/elem-go/styles" "github.com/gorilla/mux" @@ -98,6 +101,7 @@ func (h *Headscale) handleVerifyRequest( // Check if any node has the requested NodeKey var nodeKeyFound bool + for _, node := range nodes.All() { if node.NodeKey() == derpAdmitClientRequest.NodePublic { nodeKeyFound = true @@ -128,6 +132,7 @@ func (h *Headscale) VerifyHandler( httpError(writer, err) return } + writer.Header().Set("Content-Type", "application/json") } @@ -149,6 +154,7 @@ func (h *Headscale) KeyHandler( resp := tailcfg.OverTLSPublicKeyResponse{ PublicKey: h.noisePrivateKey.Public(), } + writer.Header().Set("Content-Type", "application/json") json.NewEncoder(writer).Encode(resp) @@ -171,13 +177,14 @@ func (h *Headscale) HealthHandler( if err != nil { writer.WriteHeader(http.StatusInternalServerError) + res.Status = "fail" } json.NewEncoder(writer).Encode(res) } - - if err := h.state.PingDB(req.Context()); err != nil { + err := h.state.PingDB(req.Context()) + if err != nil { respond(err) return @@ -192,6 +199,7 @@ func (h *Headscale) RobotsHandler( ) { writer.Header().Set("Content-Type", "text/plain") writer.WriteHeader(http.StatusOK) + _, err := writer.Write([]byte("User-agent: *\nDisallow: /")) if err != nil { log.Error(). @@ -211,7 +219,8 @@ func (h *Headscale) VersionHandler( writer.WriteHeader(http.StatusOK) versionInfo := types.GetVersionInfo() - if err := json.NewEncoder(writer).Encode(versionInfo); err != nil { + err := json.NewEncoder(writer).Encode(versionInfo) + if err != nil { log.Error(). Caller(). Err(err). @@ -268,3 +277,21 @@ func (a *AuthProviderWeb) RegisterHandler( writer.WriteHeader(http.StatusOK) writer.Write([]byte(templates.RegisterWeb(registrationId).Render())) } + +//go:embed assets/favicon.png +var favicon []byte + +func FaviconHandler(writer http.ResponseWriter, req *http.Request) { + writer.Header().Set("Content-Type", "image/png") + http.ServeContent(writer, req, "favicon.ico", time.Unix(0, 0), bytes.NewReader(favicon)) +} + +// Returns a blank page with favicon linked. +func BlankHandler(writer http.ResponseWriter, res *http.Request) { + writer.Header().Set("Content-Type", "text/html; charset=utf-8") + io.WriteString(writer, ` + + + + `) +} diff --git a/hscontrol/templates/general.go b/hscontrol/templates/general.go index 3728b736..6e2af390 100644 --- a/hscontrol/templates/general.go +++ b/hscontrol/templates/general.go @@ -49,6 +49,10 @@ func HtmlStructure(head, body *elem.Element) *elem.Element { attrs.Name: "viewport", attrs.Content: "width=device-width, initial-scale=1.0", }), + elem.Link(attrs.Props{ + attrs.Rel: "icon", + attrs.Href: "/favicon.ico", + }), head, ), body, diff --git a/swagger.go b/swagger.go index 306fc1f6..fa764568 100644 --- a/swagger.go +++ b/swagger.go @@ -20,7 +20,7 @@ func SwaggerUI( - + @@ -57,6 +57,7 @@ func SwaggerUI( writer.Header().Set("Content-Type", "text/plain; charset=utf-8") writer.WriteHeader(http.StatusInternalServerError) + _, err := writer.Write([]byte("Could not render Swagger")) if err != nil { log.Error(). @@ -70,6 +71,7 @@ func SwaggerUI( writer.Header().Set("Content-Type", "text/html; charset=utf-8") writer.WriteHeader(http.StatusOK) + _, err := writer.Write(payload.Bytes()) if err != nil { log.Error(). @@ -85,6 +87,7 @@ func SwaggerAPIv1( ) { writer.Header().Set("Content-Type", "application/json; charset=utf-8") writer.WriteHeader(http.StatusOK) + if _, err := writer.Write(apiV1JSON); err != nil { log.Error(). Caller().