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 00000000..4989810f Binary files /dev/null and b/hscontrol/assets/favicon.png differ 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().