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

heathcliff26 / go-wol / 14551968200

19 Apr 2025 06:53PM UTC coverage: 85.714% (+0.5%) from 85.169%
14551968200

push

github

heathcliff26
api: Implement hosts endpoint

Implement functions for adding/removing hosts.
Fix an error where storage would allow any string to be added as a new MAC.

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

34 of 41 new or added lines in 3 files covered. (82.93%)

1 existing line in 1 file now uncovered.

618 of 721 relevant lines covered (85.71%)

31.64 hits per line

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

77.92
/pkg/server/api/v1/api.go
1
package v1
2

3
import (
4
        "encoding/json"
5
        "log/slog"
6
        "net/http"
7
        "strings"
8

9
        "github.com/heathcliff26/go-wol/pkg/server/storage"
10
        "github.com/heathcliff26/go-wol/pkg/wol"
11
)
12

13
type Response struct {
14
        Status string `json:"status"`
15
        Reason string `json:"reason"`
16
}
17

18
type apiHandler struct {
19
        storage *storage.Storage
20
}
21

22
func NewRouter(storage *storage.Storage) *http.ServeMux {
2✔
23
        handler := &apiHandler{
2✔
24
                storage: storage,
2✔
25
        }
2✔
26

2✔
27
        router := http.NewServeMux()
2✔
28
        router.HandleFunc("GET /wake/{macAddr}", WakeHandler)
2✔
29
        router.HandleFunc("PUT /hosts/{macAddr}/{name}", handler.AddHostHandler)
2✔
30
        router.HandleFunc("DELETE /hosts/{macAddr}", handler.RemoveHostHandler)
2✔
31
        return router
2✔
32
}
2✔
33

34
// GET /wake/{macAddr}
35
// Send a magic packet to the specified MAC address
36
func WakeHandler(res http.ResponseWriter, req *http.Request) {
3✔
37
        macAddr := req.PathValue("macAddr")
3✔
38

3✔
39
        packet, err := wol.CreatePacket(macAddr)
3✔
40
        if err != nil {
5✔
41
                slog.Info("Client send invalid MAC address", slog.String("mac", macAddr), slog.Any("error", err))
2✔
42
                res.WriteHeader(http.StatusBadRequest)
2✔
43
                sendResponse(res, "Invalid MAC address")
2✔
44
                return
2✔
45
        }
2✔
46

47
        err = packet.Send("")
1✔
48
        if err != nil {
1✔
49
                slog.Info("Failed to send magic packet", slog.String("mac", macAddr), slog.Any("error", err))
×
50
                res.WriteHeader(http.StatusBadRequest)
×
51
                sendResponse(res, "Failed to send magic packet")
×
52
                return
×
53
        }
×
54

55
        slog.Info("Send magic packet", slog.String("mac", macAddr))
1✔
56
        sendResponse(res, "")
1✔
57
}
58

59
// PUT /hosts/{macAddr}/{name}
60
// Add a host to the storage
61
func (h *apiHandler) AddHostHandler(res http.ResponseWriter, req *http.Request) {
2✔
62
        macAddr := req.PathValue("macAddr")
2✔
63
        name := req.PathValue("name")
2✔
64

2✔
65
        err := h.storage.AddHost(macAddr, name)
2✔
66
        if err != nil {
3✔
67
                slog.Error("Failed to add host", "mac", macAddr, "name", name, "error", err)
1✔
68
                if strings.HasSuffix(err.Error(), "invalid MAC address") {
2✔
69
                        res.WriteHeader(http.StatusBadRequest)
1✔
70
                } else {
1✔
NEW
71
                        res.WriteHeader(http.StatusInternalServerError)
×
NEW
72
                }
×
73
                sendResponse(res, "Failed to add host")
1✔
74
                return
1✔
75
        }
76

77
        slog.Info("Added host", slog.String("mac", macAddr), slog.String("name", name))
1✔
78
        sendResponse(res, "")
1✔
79
}
80

81
// DELETE /hosts/{macAddr}
82
// Remove a host from the storage
83
func (h *apiHandler) RemoveHostHandler(res http.ResponseWriter, req *http.Request) {
1✔
84
        macAddr := req.PathValue("macAddr")
1✔
85

1✔
86
        err := h.storage.RemoveHost(macAddr)
1✔
87
        if err != nil {
1✔
NEW
88
                slog.Error("Failed to remove host", "mac", macAddr, "error", err)
×
NEW
89
                res.WriteHeader(http.StatusInternalServerError)
×
NEW
90
                sendResponse(res, "Failed to remove host")
×
NEW
91
                return
×
NEW
92
        }
×
93

94
        slog.Info("Removed host", slog.String("mac", macAddr))
1✔
95
        sendResponse(res, "")
1✔
96
}
97

98
func sendResponse(rw http.ResponseWriter, reason string) {
6✔
99
        response := Response{
6✔
100
                Status: "error",
6✔
101
                Reason: reason,
6✔
102
        }
6✔
103
        if reason == "" {
9✔
104
                response.Status = "ok"
3✔
105
        }
3✔
106

107
        b, err := json.MarshalIndent(response, "", "  ")
6✔
108
        if err != nil {
6✔
109
                slog.Error("Failed to create Response", "err", err)
×
110
                return
×
111
        }
×
112

113
        rw.Header().Set("Content-Type", "application/json")
6✔
114

6✔
115
        _, err = rw.Write(b)
6✔
116
        if err != nil {
6✔
117
                slog.Error("Failed to send response to client", "err", err)
×
118
        }
×
119
}
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