diff --git a/client/src/api/docker.jsx b/client/src/api/docker.jsx index a66e2b8..0c36bd9 100644 --- a/client/src/api/docker.jsx +++ b/client/src/api/docker.jsx @@ -23,6 +23,11 @@ function getContainerLogs(containerId, searchQuery, limit, lastReceivedLogs, err if(limit < 50) limit = 50; + // remove starting / from containerId + if(containerId.startsWith('/')) { + containerId = containerId.substring(1); + } + const queryParams = new URLSearchParams({ search: searchQuery || "", limit: limit || "", diff --git a/package.json b/package.json index 06413f0..13c79fa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cosmos-server", - "version": "0.21.0-unstable9", + "version": "0.21.0-unstable91", "description": "", "main": "test-server.js", "bugs": { diff --git a/src/constellation/index.go b/src/constellation/index.go index 4e6e340..e41a91c 100644 --- a/src/constellation/index.go +++ b/src/constellation/index.go @@ -6,6 +6,7 @@ import ( ) var NebulaStarted = false +var NebulaHasStarted = false var CachedDeviceNames = map[string]string{} var CachedDevices = map[string]utils.ConstellationDevice{} var needToSyncCA = false diff --git a/src/constellation/nebula.go b/src/constellation/nebula.go index 5ea324e..a21f248 100644 --- a/src/constellation/nebula.go +++ b/src/constellation/nebula.go @@ -138,15 +138,18 @@ func startNebula() error { if err != nil { utils.Error("failed to create nebula instance, need to restart the process", err) - // TODO: need a way to avoid restart loops (check if Nebula ever started?) - // We need a full restart - // utils.RestartServer(1) + // Nebula restart failure, we need to kill the process for OS cleanup + // Check that Nebula has ever started to avoid restart loop + if NebulaHasStarted { + utils.RestartServer(1) + } } // Actually start the nebula service (brings up TUN interface) control.Start() NebulaStarted = true + NebulaHasStarted = true utils.Log("Constellation: nebula started successfully") return nil diff --git a/src/httpServer.go b/src/httpServer.go index 92c7559..bd41002 100644 --- a/src/httpServer.go +++ b/src/httpServer.go @@ -20,6 +20,7 @@ import ( "os" "net" "strings" + "path" "github.com/go-chi/httprate" "crypto/tls" "github.com/foomo/tlsconfig" @@ -446,6 +447,23 @@ func InitServer() *mux.Router { router := mux.NewRouter().StrictSlash(true).SkipClean(true) + // Clean paths for API routes before mux routing. + // SkipClean(true) is needed for proxy routes, but API routes use exact + // segment matching so double slashes cause 404s. + // router.Use runs after the main router matches but before subrouters match, + // so this cleans the path in time for API subrouter matching. + router.Use(func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if strings.HasPrefix(r.URL.Path, "/cosmos/") || strings.HasPrefix(r.URL.Path, "/cosmos-ui/") { + cleaned := path.Clean(r.URL.Path) + if cleaned != r.URL.Path { + r.URL.Path = cleaned + } + } + next.ServeHTTP(w, r) + }) + }) + router.Use(utils.ClientRealIP) router.Use(utils.BlockBannedIPs) @@ -474,7 +492,6 @@ func InitServer() *mux.Router { srapiStrict := router.PathPrefix("/cosmos").Subrouter() srapiStrict.Use(utils.ContentTypeMiddleware("application/json")) - srapiStrict.HandleFunc("/api/login", user.UserLogin) srapiStrict.HandleFunc("/api/sudo", user.UserSudo) @@ -636,6 +653,10 @@ func InitServer() *mux.Router { } srapiAdmin.Use(utils.Restrictions(config.AdminConstellationOnly, config.AdminWhitelistIPs)) + + srapi.Use(proxy.CleanPathMiddleware) + srapiStrict.Use(proxy.CleanPathMiddleware) + srapiAdmin.Use(proxy.CleanPathMiddleware) srapi.Use(utils.SetSecurityHeaders) srapiStrict.Use(utils.SetSecurityHeaders) diff --git a/src/proxy/routerGen.go b/src/proxy/routerGen.go index 9cea054..71b56cf 100644 --- a/src/proxy/routerGen.go +++ b/src/proxy/routerGen.go @@ -17,7 +17,7 @@ import ( ) // Borrowed from the net/http package. (Thanks mux!) -func cleanPathMiddleware(next http.Handler) http.Handler { +func CleanPathMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { p := r.URL.Path if p == "" { @@ -234,7 +234,7 @@ func RouterGen(route utils.ProxyRouteConfig, router *mux.Router, destination htt destination = tokenMiddleware(route)(utils.SetCosmosHeader(destination)) if !route.SkipURLClean { - destination = cleanPathMiddleware(destination) + destination = CleanPathMiddleware(destination) } origin.Handler(destination)