github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/api/api.go (about) 1 // This file is part of the Smart Home 2 // Program complex distribution https://github.com/e154/smart-home 3 // Copyright (C) 2016-2023, Filippov Alex 4 // 5 // This library is free software: you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 3 of the License, or (at your option) any later version. 9 // 10 // This libraryc is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Library General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library. If not, see 17 // <https://www.gnu.org/licenses/>. 18 19 package api 20 21 import ( 22 "context" 23 "crypto/tls" 24 "fmt" 25 "net/http" 26 "strings" 27 "time" 28 29 "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 30 echopprof "github.com/hiko1129/echo-pprof" 31 echoCacheMiddleware "github.com/kenshin579/echo-http-cache" 32 "github.com/labstack/echo/v4" 33 "github.com/labstack/echo/v4/middleware" 34 "go.uber.org/atomic" 35 36 "github.com/e154/smart-home/adaptors" 37 "github.com/e154/smart-home/api/controllers" 38 "github.com/e154/smart-home/api/stub" 39 publicAssets "github.com/e154/smart-home/build" 40 "github.com/e154/smart-home/common/events" 41 "github.com/e154/smart-home/common/logger" 42 "github.com/e154/smart-home/system/bus" 43 "github.com/e154/smart-home/system/rbac" 44 ) 45 46 var ( 47 log = logger.MustGetLogger("api") 48 ) 49 50 // Api ... 51 type Api struct { 52 controllers *controllers.Controllers 53 echoFilter *rbac.EchoAccessFilter 54 echo *echo.Echo 55 cfg Config 56 certPublic string 57 certKey string 58 adaptors *adaptors.Adaptors 59 eventBus bus.Bus 60 httpServer http.Server 61 tlsServer http.Server 62 tlsStarted *atomic.Bool 63 } 64 65 // NewApi ... 66 func NewApi(controllers *controllers.Controllers, 67 echoFilter *rbac.EchoAccessFilter, 68 cfg Config, 69 eventBus bus.Bus, 70 adaptors *adaptors.Adaptors) (api *Api) { 71 api = &Api{ 72 controllers: controllers, 73 echoFilter: echoFilter, 74 cfg: cfg, 75 adaptors: adaptors, 76 eventBus: eventBus, 77 tlsStarted: atomic.NewBool(false), 78 } 79 return 80 } 81 82 // Start ... 83 func (a *Api) Start() (err error) { 84 85 // HTTP 86 a.echo = echo.New() 87 a.echo.Use(middleware.BodyLimitWithConfig(middleware.BodyLimitConfig{ 88 Skipper: middleware.DefaultSkipper, 89 Limit: "128M", 90 })) 91 a.echo.Use(controllers.NewMiddlewareContextValue) 92 a.echo.Use(middleware.Recover()) 93 94 if a.cfg.Debug { 95 var format = `INFO api/v1 [${method}] ${uri} ${status} ${latency_human} ${error}` + "\n" 96 97 log.Info("debug enabled") 98 DefaultLoggerConfig := middleware.LoggerConfig{ 99 Skipper: middleware.DefaultSkipper, 100 Format: format, 101 CustomTimeFormat: "2006-01-02 15:04:05.00000", 102 } 103 a.echo.Use(middleware.LoggerWithConfig(DefaultLoggerConfig)) 104 a.echo.Debug = true 105 } 106 107 if a.cfg.Pprof { 108 // automatically add routers for net/http/pprof 109 // e.g. /debug/pprof, /debug/pprof/heap, etc. 110 log.Info("pprof enabled") 111 echopprof.Wrap(a.echo) 112 113 prefix := "/debug/pprof" 114 group := a.echo.Group(prefix) 115 echopprof.WrapGroup(prefix, group) 116 } 117 118 a.echo.HideBanner = true 119 a.echo.HidePort = true 120 121 if a.cfg.Gzip { 122 a.echo.Use(middleware.GzipWithConfig(middleware.DefaultGzipConfig)) 123 a.echo.Use(middleware.Decompress()) 124 a.echo.Use(echoCacheMiddleware.CacheWithConfig(echoCacheMiddleware.CacheConfig{ 125 Store: echoCacheMiddleware.NewCacheMemoryStoreWithConfig(echoCacheMiddleware.CacheMemoryStoreConfig{ 126 Capacity: 5, 127 Algorithm: echoCacheMiddleware.LFU, 128 }), 129 Expiration: 10 * time.Second, 130 })) 131 132 } 133 134 a.registerHandlers() 135 136 go a.startTlsServer() 137 go a.startServer() 138 139 a.eventBus.Subscribe("system/models/variables/+", a.eventHandler, false) 140 a.eventBus.Publish("system/services/api", events.EventServiceStarted{Service: "Api"}) 141 142 return nil 143 } 144 145 // Shutdown ... 146 func (a *Api) Shutdown(ctx context.Context) (err error) { 147 a.httpServer.Shutdown(ctx) 148 a.tlsServer.Shutdown(ctx) 149 if a.echo != nil { 150 err = a.echo.Shutdown(ctx) 151 } 152 a.eventBus.Unsubscribe("system/models/variables/+", a.eventHandler) 153 a.eventBus.Publish("system/services/api", events.EventServiceStopped{Service: "Api"}) 154 155 return 156 } 157 158 func (a *Api) startServer() { 159 log.Infof("HTTP Server started at :%d", a.cfg.HttpPort) 160 a.httpServer = http.Server{ 161 Addr: fmt.Sprintf(":%d", a.cfg.HttpPort), 162 Handler: a.echo, 163 } 164 if err := a.httpServer.ListenAndServe(); err != http.ErrServerClosed { 165 log.Errorf("error when starting HTTP server: %w", err) 166 } else { 167 log.Info("HTTP server stopped serving requests") 168 } 169 } 170 171 func (a *Api) startTlsServer() { 172 if !a.tlsStarted.CompareAndSwap(false, true) { 173 return 174 } 175 defer a.tlsStarted.Store(false) 176 177 a.getCerts() 178 if a.certPublic == "" || a.certKey == "" { 179 return 180 } 181 182 // Generate a key pair from your pem-encoded cert and key ([]byte). 183 cert, err := tls.X509KeyPair([]byte(a.certPublic), []byte(a.certKey)) 184 if err != nil { 185 log.Error(err.Error()) 186 return 187 } 188 log.Infof("HTTPS Server started at :%d", a.cfg.HttpsPort) 189 190 a.tlsServer = http.Server{ 191 Addr: fmt.Sprintf(":%d", a.cfg.HttpsPort), 192 Handler: a.echo, 193 TLSConfig: &tls.Config{ 194 Certificates: []tls.Certificate{cert}, 195 }, 196 } 197 if err = a.tlsServer.ListenAndServeTLS("", ""); err != http.ErrServerClosed { 198 log.Errorf("error when starting HTTPS server: %w", err) 199 } else { 200 log.Info("HTTPS server stopped serving requests") 201 } 202 } 203 204 // CustomMatcher ... 205 func (a *Api) CustomMatcher(key string) (string, bool) { 206 switch key { 207 case "X-Api-Key": 208 return key, true 209 default: 210 return runtime.DefaultHeaderMatcher(key) 211 } 212 } 213 214 func (a *Api) registerHandlers() { 215 216 // Swagger 217 if a.cfg.Swagger { 218 var contentHandler = echo.WrapHandler(http.FileServer(http.FS(SwaggerAssets))) 219 a.echo.GET("/swagger-ui", contentHandler) 220 a.echo.GET("/swagger-ui/*", contentHandler) 221 a.echo.GET("/api.swagger3.yaml", contentHandler) 222 } 223 224 var typedocHandler = echo.WrapHandler(http.FileServer(http.FS(TypedocAssets))) 225 a.echo.GET("/typedoc", typedocHandler) 226 a.echo.GET("/typedoc/*", typedocHandler) 227 228 wrapper := stub.ServerInterfaceWrapper{ 229 Handler: a.controllers, 230 } 231 232 v1 := a.echo.Group("/v1") 233 v1.GET("/access_list", a.echoFilter.Auth(wrapper.AuthServiceAccessList)) 234 v1.POST("/action", a.echoFilter.Auth(wrapper.ActionServiceAddAction)) 235 v1.DELETE("/action/:id", a.echoFilter.Auth(wrapper.ActionServiceDeleteAction)) 236 v1.GET("/action/:id", a.echoFilter.Auth(wrapper.ActionServiceGetActionById)) 237 v1.PUT("/action/:id", a.echoFilter.Auth(wrapper.ActionServiceUpdateAction)) 238 v1.GET("/actions", a.echoFilter.Auth(wrapper.ActionServiceGetActionList)) 239 v1.GET("/actions/search", a.echoFilter.Auth(wrapper.ActionServiceSearchAction)) 240 v1.POST("/area", a.echoFilter.Auth(wrapper.AreaServiceAddArea)) 241 v1.DELETE("/area/:id", a.echoFilter.Auth(wrapper.AreaServiceDeleteArea)) 242 v1.GET("/area/:id", a.echoFilter.Auth(wrapper.AreaServiceGetAreaById)) 243 v1.PUT("/area/:id", a.echoFilter.Auth(wrapper.AreaServiceUpdateArea)) 244 v1.GET("/areas", a.echoFilter.Auth(wrapper.AreaServiceGetAreaList)) 245 v1.GET("/areas/search", a.echoFilter.Auth(wrapper.AreaServiceSearchArea)) 246 v1.GET("/backups", a.echoFilter.Auth(wrapper.BackupServiceGetBackupList)) 247 v1.POST("/backups", a.echoFilter.Auth(wrapper.BackupServiceNewBackup)) 248 v1.POST("/backup/upload", a.echoFilter.Auth(wrapper.BackupServiceUploadBackup)) 249 v1.POST("/backup/apply", a.echoFilter.Auth(wrapper.BackupServiceApplyState)) 250 v1.POST("/backup/rollback", a.echoFilter.Auth(wrapper.BackupServiceRevertState)) 251 v1.PUT("/backup/:name", a.echoFilter.Auth(wrapper.BackupServiceRestoreBackup)) 252 v1.DELETE("/backup/:name", a.echoFilter.Auth(wrapper.BackupServiceDeleteBackup)) 253 v1.POST("/condition", a.echoFilter.Auth(wrapper.ConditionServiceAddCondition)) 254 v1.DELETE("/condition/:id", a.echoFilter.Auth(wrapper.ConditionServiceDeleteCondition)) 255 v1.GET("/condition/:id", a.echoFilter.Auth(wrapper.ConditionServiceGetConditionById)) 256 v1.PUT("/condition/:id", a.echoFilter.Auth(wrapper.ConditionServiceUpdateCondition)) 257 v1.GET("/conditions", a.echoFilter.Auth(wrapper.ConditionServiceGetConditionList)) 258 v1.GET("/conditions/search", a.echoFilter.Auth(wrapper.ConditionServiceSearchCondition)) 259 v1.POST("/dashboard", a.echoFilter.Auth(wrapper.DashboardServiceAddDashboard)) 260 v1.DELETE("/dashboard/:id", a.echoFilter.Auth(wrapper.DashboardServiceDeleteDashboard)) 261 v1.GET("/dashboard/:id", a.echoFilter.Auth(wrapper.DashboardServiceGetDashboardById)) 262 v1.PUT("/dashboard/:id", a.echoFilter.Auth(wrapper.DashboardServiceUpdateDashboard)) 263 v1.POST("/dashboard_card", a.echoFilter.Auth(wrapper.DashboardCardServiceAddDashboardCard)) 264 v1.POST("/dashboard_card/import", a.echoFilter.Auth(wrapper.DashboardCardServiceImportDashboardCard)) 265 v1.DELETE("/dashboard_card/:id", a.echoFilter.Auth(wrapper.DashboardCardServiceDeleteDashboardCard)) 266 v1.GET("/dashboard_card/:id", a.echoFilter.Auth(wrapper.DashboardCardServiceGetDashboardCardById)) 267 v1.PUT("/dashboard_card/:id", a.echoFilter.Auth(wrapper.DashboardCardServiceUpdateDashboardCard)) 268 v1.POST("/dashboard_card_item", a.echoFilter.Auth(wrapper.DashboardCardItemServiceAddDashboardCardItem)) 269 v1.DELETE("/dashboard_card_item/:id", a.echoFilter.Auth(wrapper.DashboardCardItemServiceDeleteDashboardCardItem)) 270 v1.GET("/dashboard_card_item/:id", a.echoFilter.Auth(wrapper.DashboardCardItemServiceGetDashboardCardItemById)) 271 v1.PUT("/dashboard_card_item/:id", a.echoFilter.Auth(wrapper.DashboardCardItemServiceUpdateDashboardCardItem)) 272 v1.GET("/dashboard_card_items", a.echoFilter.Auth(wrapper.DashboardCardItemServiceGetDashboardCardItemList)) 273 v1.GET("/dashboard_cards", a.echoFilter.Auth(wrapper.DashboardCardServiceGetDashboardCardList)) 274 v1.POST("/dashboard_tab", a.echoFilter.Auth(wrapper.DashboardTabServiceAddDashboardTab)) 275 v1.DELETE("/dashboard_tab/:id", a.echoFilter.Auth(wrapper.DashboardTabServiceDeleteDashboardTab)) 276 v1.GET("/dashboard_tab/:id", a.echoFilter.Auth(wrapper.DashboardTabServiceGetDashboardTabById)) 277 v1.PUT("/dashboard_tab/:id", a.echoFilter.Auth(wrapper.DashboardTabServiceUpdateDashboardTab)) 278 v1.POST("/dashboard_tabs/import", a.echoFilter.Auth(wrapper.DashboardTabServiceImportDashboardTab)) 279 v1.GET("/dashboard_tabs", a.echoFilter.Auth(wrapper.DashboardTabServiceGetDashboardTabList)) 280 v1.GET("/dashboards", a.echoFilter.Auth(wrapper.DashboardServiceGetDashboardList)) 281 v1.POST("/dashboards/import", a.echoFilter.Auth(wrapper.DashboardServiceImportDashboard)) 282 v1.GET("/dashboards/search", a.echoFilter.Auth(wrapper.DashboardServiceSearchDashboard)) 283 v1.POST("/developer_tools/automation/call_action", a.echoFilter.Auth(wrapper.DeveloperToolsServiceCallAction)) 284 v1.POST("/developer_tools/automation/call_trigger", a.echoFilter.Auth(wrapper.DeveloperToolsServiceCallTrigger)) 285 v1.GET("/developer_tools/bus/state", a.echoFilter.Auth(wrapper.DeveloperToolsServiceGetEventBusStateList)) 286 v1.POST("/developer_tools/entity/reload", a.echoFilter.Auth(wrapper.DeveloperToolsServiceReloadEntity)) 287 v1.POST("/developer_tools/entity/set_state", a.echoFilter.Auth(wrapper.DeveloperToolsServiceEntitySetState)) 288 v1.GET("/entities", a.echoFilter.Auth(wrapper.EntityServiceGetEntityList)) 289 v1.POST("/entities/import", a.echoFilter.Auth(wrapper.EntityServiceImportEntity)) 290 v1.POST("/entity", a.echoFilter.Auth(wrapper.EntityServiceAddEntity)) 291 v1.GET("/entity/search", a.echoFilter.Auth(wrapper.EntityServiceSearchEntity)) 292 v1.DELETE("/entity/:id", a.echoFilter.Auth(wrapper.EntityServiceDeleteEntity)) 293 v1.GET("/entity/:id", a.echoFilter.Auth(wrapper.EntityServiceGetEntity)) 294 v1.PUT("/entity/:id", a.echoFilter.Auth(wrapper.EntityServiceUpdateEntity)) 295 v1.POST("/entity/:id/disable", a.echoFilter.Auth(wrapper.EntityServiceDisabledEntity)) 296 v1.POST("/entity/:id/enable", a.echoFilter.Auth(wrapper.EntityServiceEnabledEntity)) 297 v1.GET("/entity_storage", a.echoFilter.Auth(wrapper.EntityStorageServiceGetEntityStorageList)) 298 v1.GET("/entities/statistic", a.echoFilter.Auth(wrapper.EntityServiceGetStatistic)) 299 v1.POST("/image", a.echoFilter.Auth(wrapper.ImageServiceAddImage)) 300 v1.POST("/image/upload", a.echoFilter.Auth(wrapper.ImageServiceUploadImage)) 301 v1.DELETE("/image/:id", a.echoFilter.Auth(wrapper.ImageServiceDeleteImageById)) 302 v1.GET("/image/:id", a.echoFilter.Auth(wrapper.ImageServiceGetImageById)) 303 v1.PUT("/image/:id", a.echoFilter.Auth(wrapper.ImageServiceUpdateImageById)) 304 v1.GET("/images", a.echoFilter.Auth(wrapper.ImageServiceGetImageList)) 305 v1.GET("/images/filter_list", a.echoFilter.Auth(wrapper.ImageServiceGetImageFilterList)) 306 v1.GET("/images/filtered", a.echoFilter.Auth(wrapper.ImageServiceGetImageListByDate)) 307 v1.POST("/interact/entity/call_action", a.echoFilter.Auth(wrapper.InteractServiceEntityCallAction)) 308 v1.GET("/logs", a.echoFilter.Auth(wrapper.LogServiceGetLogList)) 309 v1.GET("/message_delivery", a.echoFilter.Auth(wrapper.MessageDeliveryServiceGetMessageDeliveryList)) 310 v1.GET("/metric", a.echoFilter.Auth(wrapper.MetricServiceGetMetric)) 311 v1.GET("/mqtt/client/:id", a.echoFilter.Auth(wrapper.MqttServiceGetClientById)) 312 v1.GET("/mqtt/clients", a.echoFilter.Auth(wrapper.MqttServiceGetClientList)) 313 v1.GET("/mqtt/subscriptions", a.echoFilter.Auth(wrapper.MqttServiceGetSubscriptionList)) 314 v1.POST("/password_reset", a.echoFilter.Auth(wrapper.AuthServicePasswordReset)) 315 v1.GET("/plugin/:name", a.echoFilter.Auth(wrapper.PluginServiceGetPlugin)) 316 v1.POST("/plugin/:name/disable", a.echoFilter.Auth(wrapper.PluginServiceDisablePlugin)) 317 v1.POST("/plugin/:name/enable", a.echoFilter.Auth(wrapper.PluginServiceEnablePlugin)) 318 v1.PUT("/plugin/:name/settings", a.echoFilter.Auth(wrapper.PluginServiceUpdatePluginSettings)) 319 v1.GET("/plugins", a.echoFilter.Auth(wrapper.PluginServiceGetPluginList)) 320 v1.GET("/plugins/search", a.echoFilter.Auth(wrapper.PluginServiceSearchPlugin)) 321 v1.GET("/plugin/:name/readme", a.echoFilter.Auth(wrapper.PluginServiceGetPluginReadme)) 322 v1.POST("/role", a.echoFilter.Auth(wrapper.RoleServiceAddRole)) 323 v1.DELETE("/role/:name", a.echoFilter.Auth(wrapper.RoleServiceDeleteRoleByName)) 324 v1.GET("/role/:name", a.echoFilter.Auth(wrapper.RoleServiceGetRoleByName)) 325 v1.PUT("/role/:name", a.echoFilter.Auth(wrapper.RoleServiceUpdateRoleByName)) 326 v1.GET("/role/:name/access_list", a.echoFilter.Auth(wrapper.RoleServiceGetRoleAccessList)) 327 v1.PUT("/role/:name/access_list", a.echoFilter.Auth(wrapper.RoleServiceUpdateRoleAccessList)) 328 v1.GET("/roles", a.echoFilter.Auth(wrapper.RoleServiceGetRoleList)) 329 v1.GET("/roles/search", a.echoFilter.Auth(wrapper.RoleServiceSearchRoleByName)) 330 v1.POST("/script", a.echoFilter.Auth(wrapper.ScriptServiceAddScript)) 331 v1.POST("/script/exec_src", a.echoFilter.Auth(wrapper.ScriptServiceExecSrcScriptById)) 332 v1.DELETE("/script/:id", a.echoFilter.Auth(wrapper.ScriptServiceDeleteScriptById)) 333 v1.GET("/script/:id", a.echoFilter.Auth(wrapper.ScriptServiceGetScriptById)) 334 v1.GET("/script/:id/compiled", a.echoFilter.Auth(wrapper.ScriptServiceGetCompiledScriptById)) 335 v1.PUT("/script/:id", a.echoFilter.Auth(wrapper.ScriptServiceUpdateScriptById)) 336 v1.POST("/script/:id/copy", a.echoFilter.Auth(wrapper.ScriptServiceCopyScriptById)) 337 v1.POST("/script/:id/exec", a.echoFilter.Auth(wrapper.ScriptServiceExecScriptById)) 338 v1.GET("/scripts", a.echoFilter.Auth(wrapper.ScriptServiceGetScriptList)) 339 v1.GET("/scripts/search", a.echoFilter.Auth(wrapper.ScriptServiceSearchScript)) 340 v1.GET("/scripts/statistic", a.echoFilter.Auth(wrapper.ScriptServiceGetStatistic)) 341 v1.GET("/tags/search", a.echoFilter.Auth(wrapper.TagServiceSearchTag)) 342 v1.GET("/tags", a.echoFilter.Auth(wrapper.TagServiceGetTagList)) 343 v1.DELETE("/tag/:id", a.echoFilter.Auth(wrapper.TagServiceDeleteTagById)) 344 v1.GET("/tag/:id", a.echoFilter.Auth(wrapper.TagServiceGetTagById)) 345 v1.PUT("/tag/:id", a.echoFilter.Auth(wrapper.TagServiceUpdateTagById)) 346 v1.POST("/signin", wrapper.AuthServiceSignin) 347 v1.POST("/signout", a.echoFilter.Auth(wrapper.AuthServiceSignout)) 348 v1.POST("/task", a.echoFilter.Auth(wrapper.AutomationServiceAddTask)) 349 v1.DELETE("/task/:id", a.echoFilter.Auth(wrapper.AutomationServiceDeleteTask)) 350 v1.GET("/task/:id", a.echoFilter.Auth(wrapper.AutomationServiceGetTask)) 351 v1.PUT("/task/:id", a.echoFilter.Auth(wrapper.AutomationServiceUpdateTask)) 352 v1.POST("/task/:id/disable", a.echoFilter.Auth(wrapper.AutomationServiceDisableTask)) 353 v1.POST("/task/:id/enable", a.echoFilter.Auth(wrapper.AutomationServiceEnableTask)) 354 v1.GET("/tasks", a.echoFilter.Auth(wrapper.AutomationServiceGetTaskList)) 355 v1.POST("/tasks/import", a.echoFilter.Auth(wrapper.AutomationServiceImportTask)) 356 v1.POST("/trigger", a.echoFilter.Auth(wrapper.TriggerServiceAddTrigger)) 357 v1.DELETE("/trigger/:id", a.echoFilter.Auth(wrapper.TriggerServiceDeleteTrigger)) 358 v1.GET("/trigger/:id", a.echoFilter.Auth(wrapper.TriggerServiceGetTriggerById)) 359 v1.PUT("/trigger/:id", a.echoFilter.Auth(wrapper.TriggerServiceUpdateTrigger)) 360 v1.GET("/triggers", a.echoFilter.Auth(wrapper.TriggerServiceGetTriggerList)) 361 v1.GET("/triggers/search", a.echoFilter.Auth(wrapper.TriggerServiceSearchTrigger)) 362 v1.POST("/triggers/:id/disable", a.echoFilter.Auth(wrapper.TriggerServiceDisableTrigger)) 363 v1.POST("/triggers/:id/enable", a.echoFilter.Auth(wrapper.TriggerServiceEnableTrigger)) 364 v1.POST("/user", a.echoFilter.Auth(wrapper.UserServiceAddUser)) 365 v1.DELETE("/user/:id", a.echoFilter.Auth(wrapper.UserServiceDeleteUserById)) 366 v1.GET("/user/:id", a.echoFilter.Auth(wrapper.UserServiceGetUserById)) 367 v1.PUT("/user/:id", a.echoFilter.Auth(wrapper.UserServiceUpdateUserById)) 368 v1.GET("/users", a.echoFilter.Auth(wrapper.UserServiceGetUserList)) 369 v1.POST("/variable", a.echoFilter.Auth(wrapper.VariableServiceAddVariable)) 370 v1.DELETE("/variable/:name", a.echoFilter.Auth(wrapper.VariableServiceDeleteVariable)) 371 v1.GET("/variable/:name", a.echoFilter.Auth(wrapper.VariableServiceGetVariableByName)) 372 v1.PUT("/variable/:name", a.echoFilter.Auth(wrapper.VariableServiceUpdateVariable)) 373 v1.GET("/variables", a.echoFilter.Auth(wrapper.VariableServiceGetVariableList)) 374 v1.GET("/variables/search", a.echoFilter.Auth(wrapper.VariableServiceSearchVariable)) 375 v1.GET("/zigbee2mqtt/bridge", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceGetBridgeList)) 376 v1.POST("/zigbee2mqtt/bridge", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceAddZigbee2mqttBridge)) 377 v1.DELETE("/zigbee2mqtt/bridge/:id", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceDeleteBridgeById)) 378 v1.GET("/zigbee2mqtt/bridge/:id", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceGetZigbee2mqttBridge)) 379 v1.PUT("/zigbee2mqtt/bridge/:id/bridge", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceUpdateBridgeById)) 380 v1.GET("/zigbee2mqtt/bridge/:id/devices", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceDeviceList)) 381 v1.GET("/zigbee2mqtt/bridge/:id/networkmap", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceNetworkmap)) 382 v1.POST("/zigbee2mqtt/bridge/:id/networkmap", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceUpdateNetworkmap)) 383 v1.POST("/zigbee2mqtt/bridge/:id/reset", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceResetBridgeById)) 384 v1.POST("/zigbee2mqtt/device_ban", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceDeviceBan)) 385 v1.POST("/zigbee2mqtt/device_rename", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceDeviceRename)) 386 v1.POST("/zigbee2mqtt/device_whitelist", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceDeviceWhitelist)) 387 v1.GET("/zigbee2mqtt/search_device", a.echoFilter.Auth(wrapper.Zigbee2mqttServiceSearchDevice)) 388 v1.GET("/ws", a.echoFilter.Auth(wrapper.StreamServiceSubscribe)) 389 390 // static files 391 a.echo.GET("/", echo.WrapHandler(a.controllers.Index(publicAssets.F))) 392 a.echo.GET("/*", echo.WrapHandler(http.FileServer(http.FS(publicAssets.F)))) 393 a.echo.GET("/assets/*", echo.WrapHandler(http.FileServer(http.FS(publicAssets.F)))) 394 fileServer := http.FileServer(http.Dir("./data/file_storage")) 395 a.echo.Any("/upload/*", echo.WrapHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 396 r.RequestURI = strings.ReplaceAll(r.RequestURI, "/upload/", "/") 397 r.URL, _ = r.URL.Parse(r.RequestURI) 398 fileServer.ServeHTTP(w, r) 399 }))) 400 staticServer := http.FileServer(http.Dir("./data/static")) 401 a.echo.Any("/static/*", echo.WrapHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 402 r.RequestURI = strings.ReplaceAll(r.RequestURI, "/static/", "/") 403 r.URL, _ = r.URL.Parse(r.RequestURI) 404 staticServer.ServeHTTP(w, r) 405 }))) 406 snapshotServer := http.FileServer(http.Dir("./snapshots")) 407 a.echo.GET("/snapshots/*", a.echoFilter.Auth(echo.WrapHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 408 r.RequestURI = strings.ReplaceAll(r.RequestURI, "/snapshots/", "/") 409 r.URL, _ = r.URL.Parse(r.RequestURI) 410 snapshotServer.ServeHTTP(w, r) 411 })))) 412 // webdav 413 webdav := echo.WrapHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 414 //r.RequestURI = strings.ReplaceAll(r.RequestURI, "/webdav/", "/") 415 //r.URL, _ = r.URL.Parse(r.RequestURI) 416 a.controllers.Webdav(w, r) 417 })) 418 a.echo.Any("/webdav", webdav) 419 a.echo.Any("/webdav/*", webdav) 420 421 // media 422 a.echo.Any("/stream/:entity_id/channel/:channel/mse", a.echoFilter.Auth(a.controllers.StreamMSE)) //Auth 423 //a.echo.Any("/stream/:entity_id/channel/:channel/hlsll/live/init.mp4", a.controllers.Media.StreamHLSLLInit) 424 //a.echo.Any("/stream/:entity_id/channel/:channel/hlsll/live/index.m3u8", a.controllers.Media.StreamHLSLLM3U8) 425 //a.echo.Any("/stream/:entity_id/channel/:channel/hlsll/live/segment/:segment/:any", a.controllers.Media.StreamHLSLLM4Segment) 426 //a.echo.Any("/stream/:entity_id/channel/:channel/hlsll/live/fragment/:segment/:fragment/:any", a.controllers.Media.StreamHLSLLM4Fragment) 427 428 // Cors 429 a.echo.Use(middleware.CORSWithConfig(middleware.CORSConfig{ 430 AllowOrigins: []string{"*"}, 431 AllowHeaders: []string{"*"}, 432 AllowCredentials: false, 433 AllowMethods: []string{http.MethodGet, http.MethodPut, http.MethodPost, http.MethodDelete, http.MethodHead}, 434 })) 435 436 } 437 438 func (a *Api) Echo() *echo.Echo { 439 return a.echo 440 } 441 442 func (a *Api) getCerts() { 443 certPublicVar, err := a.adaptors.Variable.GetByName(context.Background(), "certPublic") 444 if err != nil { 445 return 446 } 447 a.certPublic = strings.TrimSpace(certPublicVar.Value) 448 certKeyVar, err := a.adaptors.Variable.GetByName(context.Background(), "certKey") 449 if err != nil { 450 return 451 } 452 a.certKey = strings.TrimSpace(certKeyVar.Value) 453 } 454 455 func (a *Api) eventHandler(_ string, message interface{}) { 456 switch v := message.(type) { 457 case events.EventUpdatedVariableModel: 458 switch v.Name { 459 case "certPublic", "certKey": 460 log.Infof("updated settings name %s", v.Name) 461 a.tlsServer.Shutdown(context.Background()) 462 a.startTlsServer() 463 } 464 } 465 }