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}) }