// Package httpapi serves the Kamado REST API. WebSocket push and static // UI serving land in a follow-up commit. package httpapi import ( "encoding/json" "log/slog" "net/http" "github.com/kamadopool/kamado-api/internal/state" ) type Server struct { Agg *state.Aggregator Hub *Hub Log *slog.Logger } func New(agg *state.Aggregator, log *slog.Logger) *Server { return &Server{Agg: agg, Hub: NewHub(), Log: log} } // Handler returns an http.Handler with all kamado routes mounted under /api. func (s *Server) Handler() http.Handler { mux := http.NewServeMux() mux.HandleFunc("GET /api/health", s.health) mux.HandleFunc("GET /api/pool", s.pool) mux.HandleFunc("GET /api/users", s.users) mux.HandleFunc("GET /api/workers", s.workers) mux.HandleFunc("GET /api/clients", s.clients) mux.HandleFunc("GET /api/blocks", s.blocks) mux.HandleFunc("GET /api/snapshot", s.snapshot) mux.HandleFunc("GET /api/ws", s.handleWS) return mux } func writeJSON(w http.ResponseWriter, status int, v any) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Cache-Control", "no-store") w.WriteHeader(status) _ = json.NewEncoder(w).Encode(v) } // ---- handlers --------------------------------------------------------- func (s *Server) health(w http.ResponseWriter, r *http.Request) { snap := s.Agg.Snapshot() status := http.StatusOK if !snap.CKPoolOK || !snap.BitcoinOK { status = http.StatusServiceUnavailable } writeJSON(w, status, map[string]any{ "ok": snap.CKPoolOK && snap.BitcoinOK, "ckpool": snap.CKPoolOK, "bitcoin": snap.BitcoinOK, "last_error": snap.LastError, }) } func (s *Server) snapshot(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, s.Agg.Snapshot()) } func (s *Server) pool(w http.ResponseWriter, r *http.Request) { snap := s.Agg.Snapshot() writeJSON(w, http.StatusOK, map[string]any{ "pool": snap.Pool, "uptime_seconds": snap.Uptime, "hashrate_hs_1m": snap.HashrateHs, "hashrate_hs_5m": snap.HashrateHs5m, "hashrate_hs_1h": snap.HashrateHs1h, "hashrate_hs_24h": snap.HashrateHs24h, "chain": snap.Chain, "network_hashrate_hs": snap.NetworkHashrateHs, }) } func (s *Server) users(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, s.Agg.Snapshot().Users) } func (s *Server) workers(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, s.Agg.Snapshot().Workers) } func (s *Server) clients(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, s.Agg.Snapshot().Clients) } func (s *Server) blocks(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, s.Agg.Blocks()) }