add favicon to webpages (#2858)

Co-authored-by: TeejMcSteez <tjhall047@gmail.com>
Co-authored-by: Kristoffer Dalby <kristoffer@dalby.cc>
This commit is contained in:
Teej
2025-11-11 22:46:57 -05:00
committed by GitHub
parent 1dcb04ce9b
commit 218a8db1b9
6 changed files with 42 additions and 7 deletions

View File

@@ -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**

View File

@@ -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
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -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, `
<!doctype html><html><head>
<link rel="icon" href="/favicon.ico">
</head><body></body></html>
`)
}

View File

@@ -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,

View File

@@ -20,7 +20,7 @@ func SwaggerUI(
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3/swagger-ui.css">
<link rel="icon" href="/favicon.ico">
<script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-standalone-preset.js"></script>
<script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js" charset="UTF-8"></script>
</head>
@@ -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().