feat(iot-console): IoT управляющий UI v0.1.53
- Добавлен HTML SPA: internal/api/ui/iot-console.html Ванильный JS + mqtt.js (CDN), без фреймворков. Страницы: вход, список устройств, credentials, эмулятор MQTT, заглушка телеметрии. - Добавлен go:embed: internal/api/console_embed.go, GET /console - Добавлен CORS middleware в router.go для http://iot.kube5s.ru - Ingress emqx-ws-ingress.yaml: /console → sless-operator:9090 - Версия образа v0.1.53, задеплоен Доступно: http://iot.kube5s.ru/console
This commit is contained in:
+30
-8
@@ -1,7 +1,8 @@
|
||||
// Изменено: 2026-03-20 (function-service-split: добавлены /services маршруты)
|
||||
// Изменено: 2026-04-04 (iot-console: добавлен CORS middleware + /console маршрут)
|
||||
// router.go — регистрация всех REST-маршрутов через gorilla/mux.
|
||||
// Все маршруты защищены Bearer-токеном (middleware.Auth).
|
||||
// Маршруты сгруппированы по /v1/namespaces/{namespace}/...
|
||||
// Все маршруты /v1/ защищены Bearer-токеном (middleware.Auth).
|
||||
// /console — публичный маршрут (статический HTML без auth).
|
||||
// CORS включён для http://iot.kube5s.ru — там хостится IoT Консоль (UI).
|
||||
|
||||
package api
|
||||
|
||||
@@ -15,12 +16,34 @@ import (
|
||||
"gitea-naeel.giteak8s.services.ngcloud.ru/naeel/sless/internal/api/middleware"
|
||||
)
|
||||
|
||||
// corsMiddleware добавляет CORS-заголовки для IoT Консоли на http://iot.kube5s.ru.
|
||||
// Нужен потому что: консоль на http://iot.kube5s.ru, API на https://sless.kube5s.ru — разные origin.
|
||||
// Обрабатывает preflight OPTIONS запросы от браузера.
|
||||
func corsMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "http://iot.kube5s.ru")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
|
||||
w.Header().Set("Access-Control-Max-Age", "600")
|
||||
// Preflight OPTIONS возвращаем немедленно без передачи дальше
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// NewRouter собирает gorilla/mux роутер со всеми маршрутами.
|
||||
// /fn/{namespace}/{name} — публичный прокси для вызова функций, без auth.
|
||||
// /v1/ — защищён JWT-аутентификацией (middleware.Auth).
|
||||
// /console — IoT Консоль (HTML SPA), без auth, с CORS.
|
||||
// /v1/ — защищён JWT-аутентификацией (middleware.Auth), с CORS.
|
||||
func NewRouter(h *handler.Handler, log *slog.Logger) http.Handler {
|
||||
r := mux.NewRouter()
|
||||
|
||||
// IoT Консоль — статический HTML, публично доступен
|
||||
r.HandleFunc("/console", ServeIoTConsole).Methods(http.MethodGet)
|
||||
|
||||
// Публичный прокси для вызова HTTP-триггеров — без auth токена
|
||||
// Все HTTP методы разрешены (GET/POST/PUT/... — решает сама функция)
|
||||
r.PathPrefix("/fn/{namespace}/{name}").HandlerFunc(h.InvokeFunction)
|
||||
@@ -84,12 +107,11 @@ func NewRouter(h *handler.Handler, log *slog.Logger) http.Handler {
|
||||
// Изолирует клиента в пределах его топиков: {namespace}/{deviceId}/#
|
||||
r.HandleFunc("/internal/mqtt/acl", h.MQTTAcl).Methods(http.MethodPost)
|
||||
|
||||
// Цепочка middleware: logging → (auth только для /v1/) → router
|
||||
// /fn/ — без auth, /v1/ — с auth.
|
||||
// Используем gorilla/mux Use() чтобы auth применялся только к v1 суброутеру.
|
||||
// Цепочка middleware: CORS → logging → (auth только для /v1/) → router
|
||||
// /fn/ — без auth, /console — без auth, /v1/ — с auth.
|
||||
v1.Use(func(next http.Handler) http.Handler {
|
||||
return middleware.Auth(log, next)
|
||||
})
|
||||
|
||||
return middleware.Logging(log, r)
|
||||
return corsMiddleware(middleware.Logging(log, r))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user