-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi_peer.go
More file actions
39 lines (35 loc) · 1.38 KB
/
api_peer.go
File metadata and controls
39 lines (35 loc) · 1.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package control
import (
"encoding/json"
"net/http"
"time"
"github.com/zsiec/switchframe/server/peer"
)
// registerPeerRoutes registers the peer health endpoint on the given mux.
// The /api/peer/health endpoint is unauthenticated so peer engines can
// call it without API tokens. /api/peer/force-leader is authenticated
// via a separate control-plane shared secret.
func (a *API) registerPeerRoutes(mux *http.ServeMux) {
mux.HandleFunc("GET /api/peer/health", a.handlePeerHealth)
mux.HandleFunc("POST /api/peer/force-leader", a.handleForceLeader)
}
// handlePeerHealth returns lightweight health information for peer engine
// polling. This is an unauthenticated endpoint — peer engines call it every
// 5 seconds to detect failures before the control plane notices.
func (a *API) handlePeerHealth(w http.ResponseWriter, r *http.Request) {
state := a.switcher.State()
resp := peer.HealthResponse{
Status: "ok",
UptimeMs: time.Since(a.startTime).Milliseconds(),
ProgramSource: state.ProgramSource,
LastCommandSeq: state.LastCommandSeq,
}
// Defensive nil guard: handler is unauthenticated, so a latent
// nil-deref on an accessor refactor would be a remote DoS.
if a.peerPoller != nil {
resp.EngineLabel = a.peerPoller.LocalLabel()
resp.Epoch = a.peerPoller.LocalEpoch()
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(resp)
}