• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

heathcliff26 / go-wol / 13090488100

01 Feb 2025 04:39PM UTC coverage: 65.819% (+2.5%) from 63.343%
13090488100

push

github

heathcliff26
server: Add caching headers for static files

Set ETag header for static files to facilitate client-side caching.
Change the version logic to enable runtime access to just the version
string.

Fixes: #7

Signed-off-by: Heathcliff <heathcliff@heathcliff.eu>

17 of 20 new or added lines in 3 files covered. (85.0%)

233 of 354 relevant lines covered (65.82%)

3.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/pkg/server/server.go
1
package server
2

3
import (
4
        "bytes"
5
        "crypto/sha256"
6
        "encoding/hex"
7
        "errors"
8
        "html/template"
9
        "log/slog"
10
        "net/http"
11
        "strconv"
12
        "strings"
13

14
        "github.com/heathcliff26/go-wol/pkg/server/api"
15
        "github.com/heathcliff26/go-wol/pkg/server/config"
16
        "github.com/heathcliff26/go-wol/static"
17
        "github.com/heathcliff26/simple-fileserver/pkg/middleware"
18
)
19

20
type Server struct {
21
        addr          string
22
        ssl           config.SSLConfig
23
        indexHTML     string
24
        indexChecksum string
25
}
26

27
func NewServer(c config.Config) (*Server, error) {
×
28
        tmpl, err := template.New("index.html").Parse(string(static.IndexTemplate))
×
29
        if err != nil {
×
30
                return nil, err
×
31
        }
×
32

33
        var buf bytes.Buffer
×
34
        err = tmpl.Execute(&buf, c.Hosts)
×
35
        if err != nil {
×
36
                return nil, err
×
37
        }
×
38
        indexHTML := buf.String()
×
39

×
40
        checksum := sha256.Sum256([]byte(indexHTML))
×
41

×
42
        return &Server{
×
43
                addr:          ":" + strconv.Itoa(c.Port),
×
44
                ssl:           c.SSL,
×
45
                indexHTML:     indexHTML,
×
46
                indexChecksum: hex.EncodeToString(checksum[:]),
×
47
        }, nil
×
48
}
49

50
func (s *Server) indexHandler(res http.ResponseWriter, req *http.Request) {
×
51
        res.Header().Set("ETag", s.indexChecksum)
×
52
        res.Header().Set("Cache-Control", "public, max-age=300")
×
53

×
54
        if match := req.Header.Get("If-None-Match"); match != "" {
×
55
                if strings.Contains(match, s.indexChecksum) {
×
56
                        res.WriteHeader(http.StatusNotModified)
×
57
                        return
×
58
                }
×
59
        }
60

61
        count, err := res.Write([]byte(s.indexHTML))
×
62
        if err != nil {
×
63
                slog.Error("Failed to write index.html to client", "err", err, slog.Int("written", count))
×
64
        }
×
65
}
66

67
// Starts the server and exits with error if that fails
68
func (s *Server) Run() error {
×
69
        router := http.NewServeMux()
×
70
        router.HandleFunc("GET /{$}", s.indexHandler)
×
71
        router.HandleFunc("GET /index.html", s.indexHandler)
×
72
        router.HandleFunc("GET /api/{macAddr}", api.Api)
×
NEW
73
        router.Handle("GET /css/", StaticFileServer(static.CSS))
×
NEW
74
        router.Handle("GET /js/", StaticFileServer(static.JS))
×
75

×
76
        server := http.Server{
×
77
                Addr:    s.addr,
×
78
                Handler: middleware.Logging(router),
×
79
        }
×
80

×
81
        var err error
×
82
        if s.ssl.Enabled {
×
83
                slog.Info("Starting server", slog.String("addr", s.addr), slog.String("sslKey", s.ssl.Key), slog.String("sslCert", s.ssl.Cert))
×
84
                err = server.ListenAndServeTLS(s.ssl.Cert, s.ssl.Key)
×
85
        } else {
×
86
                slog.Info("Starting server", slog.String("addr", s.addr))
×
87
                err = server.ListenAndServe()
×
88
        }
×
89

90
        // This just means the server was closed after running
91
        if errors.Is(err, http.ErrServerClosed) {
×
92
                slog.Info("Server closed, exiting")
×
93
                return nil
×
94
        }
×
95
        return err
×
96
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc