Files
lingniu-vehicle-ingest/go/vehicle-gateway/internal/realtime/http.go
2026-07-01 21:51:13 +08:00

70 lines
1.9 KiB
Go

package realtime
import (
"encoding/json"
"errors"
"net/http"
"strings"
"github.com/redis/go-redis/v9"
"lingniu-vehicle-ingest/go/vehicle-gateway/internal/envelope"
)
type Handler struct {
repository *Repository
}
func NewHandler(repository *Repository) *Handler {
if repository == nil {
panic("realtime repository must not be nil")
}
return &Handler{repository: repository}
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
return
}
path := strings.Trim(strings.TrimPrefix(r.URL.Path, "/api/realtime/vehicles/"), "/")
parts := strings.Split(path, "/")
if len(parts) == 0 || strings.TrimSpace(parts[0]) == "" {
writeError(w, http.StatusNotFound, "vehicle not found")
return
}
vin := parts[0]
switch {
case len(parts) == 1:
snapshot, err := h.repository.GetMerged(r.Context(), vin)
writeResult(w, snapshot, err)
case len(parts) == 2 && parts[1] == "online":
status, err := h.repository.IsOnline(r.Context(), vin)
writeResult(w, status, err)
case len(parts) == 3 && parts[1] == "protocols":
snapshot, err := h.repository.GetProtocol(r.Context(), vin, envelope.Protocol(strings.ToUpper(parts[2])))
writeResult(w, snapshot, err)
default:
writeError(w, http.StatusNotFound, "route not found")
}
}
func writeResult(w http.ResponseWriter, value any, err error) {
if err != nil {
if errors.Is(err, redis.Nil) {
writeError(w, http.StatusNotFound, "not found")
return
}
writeError(w, http.StatusInternalServerError, err.Error())
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(value)
}
func writeError(w http.ResponseWriter, status int, message string) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
_ = json.NewEncoder(w).Encode(map[string]any{"error": message})
}