77 lines
3.4 KiB
Go
77 lines
3.4 KiB
Go
// Package api — HTTP-сервер монолита: маршруты, CORS, health.
|
||
package api
|
||
|
||
import (
|
||
"log/slog"
|
||
"net/http"
|
||
|
||
"github.com/gorilla/mux"
|
||
|
||
"gitea.services.ngcloud.ru/Nail/IoT/internal/service/api/handler"
|
||
"gitea.services.ngcloud.ru/Nail/IoT/internal/service/api/middleware"
|
||
)
|
||
|
||
// corsMiddleware добавляет CORS-заголовки (консоль и API на одном домене платформы).
|
||
func corsMiddleware(next http.Handler) http.Handler {
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
|
||
w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
|
||
if r.Method == http.MethodOptions {
|
||
w.WriteHeader(http.StatusNoContent)
|
||
return
|
||
}
|
||
next.ServeHTTP(w, r)
|
||
})
|
||
}
|
||
|
||
// NewRouter собирает все маршруты сервиса.
|
||
func NewRouter(h *handler.Handler, log *slog.Logger, authTestMode bool, jwtHMACSecret string, version string) http.Handler {
|
||
r := mux.NewRouter()
|
||
|
||
// Health — для платформенных проверок контейнера.
|
||
r.HandleFunc("/health", healthHandler(version)).Methods(http.MethodGet)
|
||
r.HandleFunc("/healthz", healthHandler(version)).Methods(http.MethodGet)
|
||
|
||
// Лендинг "/" — инструкция (дизайн Nubes, как у shared-sqs) + статика.
|
||
r.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
|
||
ServeLanding(w, req, version)
|
||
}).Methods(http.MethodGet)
|
||
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", StaticHandler()))
|
||
|
||
// UI — публичные страницы (без данных).
|
||
r.HandleFunc("/console", ServeIoTConsole).Methods(http.MethodGet)
|
||
r.HandleFunc("/iot-admin", ServeIoTAdmin).Methods(http.MethodGet)
|
||
|
||
// Админ-статистика — свой Bearer-токен.
|
||
r.HandleFunc("/iot-admin/stats", h.AdminStats).Methods(http.MethodGet)
|
||
|
||
// MQTT auth/acl — для EMQX, без JWT.
|
||
r.HandleFunc("/internal/mqtt/auth", h.MQTTAuth).Methods(http.MethodPost)
|
||
r.HandleFunc("/internal/mqtt/acl", h.MQTTAcl).Methods(http.MethodPost)
|
||
|
||
// /v1 — под JWT.
|
||
v1 := r.PathPrefix("/v1").Subrouter()
|
||
v1.HandleFunc("/namespaces/{namespace}/iot/devices", h.ListIoTDevices).Methods(http.MethodGet)
|
||
v1.HandleFunc("/namespaces/{namespace}/iot/devices", h.CreateIoTDevice).Methods(http.MethodPost)
|
||
v1.HandleFunc("/namespaces/{namespace}/iot/devices/{name}", h.GetIoTDevice).Methods(http.MethodGet)
|
||
v1.HandleFunc("/namespaces/{namespace}/iot/devices/{name}", h.DeleteIoTDevice).Methods(http.MethodDelete)
|
||
v1.HandleFunc("/namespaces/{namespace}/iot/devices/{name}", h.UpdateIoTDevice).Methods(http.MethodPatch)
|
||
v1.HandleFunc("/namespaces/{namespace}/iot/telemetry", h.ListIoTTelemetry).Methods(http.MethodGet)
|
||
|
||
v1.Use(func(next http.Handler) http.Handler {
|
||
return middleware.Auth(authTestMode, jwtHMACSecret, log, next)
|
||
})
|
||
|
||
return corsMiddleware(middleware.Logging(log, r))
|
||
}
|
||
|
||
// healthHandler отдаёт статус сервиса и версию (для платформы).
|
||
func healthHandler(version string) http.HandlerFunc {
|
||
return func(w http.ResponseWriter, r *http.Request) {
|
||
w.Header().Set("Content-Type", "application/json")
|
||
w.WriteHeader(http.StatusOK)
|
||
_, _ = w.Write([]byte(`{"status":"ok","version":"` + version + `"}`))
|
||
}
|
||
}
|