瀏覽代碼

[release] v0.9.6

Yann Stepienik 2 年之前
父節點
當前提交
7dc5ea5214

+ 3 - 1
changelog.md

@@ -1,4 +1,4 @@
-## Version 0.9.1 > 0.9.5
+## Version 0.9.1 > 0.9.6
  - Fix subdomain logic for composed TLDs
  - Fix subdomain logic for composed TLDs
  - Add option for custom wildcard domains
  - Add option for custom wildcard domains
  - Fix domain depupe logic
  - Fix domain depupe logic
@@ -6,6 +6,8 @@
  - Update LEGO
  - Update LEGO
  - Fix issue with hot-reloading between HTTP and HTTPS 
  - Fix issue with hot-reloading between HTTP and HTTPS 
  - Fix loading bar in container overview page
  - Fix loading bar in container overview page
+ - Flush Etag cache on restart
+ - Bootstrap containers when adding new routes to them
 
 
 ## Version 0.9.0
 ## Version 0.9.0
  - Rewrote the entire HTTPS / DNS challenge system to be more robust and easier to use
  - Rewrote the entire HTTPS / DNS challenge system to be more robust and easier to use

+ 1 - 1
client/src/pages/config/users/configman.jsx

@@ -560,7 +560,7 @@ const ConfigManagement = () => {
                       onChange={(e) => {
                       onChange={(e) => {
                         formik.setFieldValue("ForceHTTPSCertificateRenewal", true);
                         formik.setFieldValue("ForceHTTPSCertificateRenewal", true);
                       }}
                       }}
-                      label="(optional) Override Wildcard Domains (comma separated, need to add both wildcard AND root domain like in the placeholder)"
+                      label="(optional, only if you know what you are doing) Override Wildcard Domains (comma separated, need to add both wildcard AND root domain like in the placeholder)"
                       formik={formik}
                       formik={formik}
                       placeholder={"example.com,*.example.com"}
                       placeholder={"example.com,*.example.com"}
                     />
                     />

+ 1 - 15
client/src/pages/servapps/servapps.jsx

@@ -72,21 +72,7 @@ const ServApps = () => {
   }, []);
   }, []);
   
   
   function updateRoutes(newRoute) {
   function updateRoutes(newRoute) {
-    let con = {
-      ...config,
-      HTTPConfig: {
-        ...config.HTTPConfig,
-        ProxyConfig: {
-          ...config.HTTPConfig.ProxyConfig,
-          Routes: [
-            newRoute,
-            ...config.HTTPConfig.ProxyConfig.Routes,
-          ]
-        },
-      },
-    };
-    
-    API.config.set(con).then((res) => {
+    return API.config.addRoute(newRoute).then((res) => {
       setOpenModal(false);
       setOpenModal(false);
       setOpenRestartModal(true);
       setOpenRestartModal(true);
     });
     });

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "cosmos-server",
   "name": "cosmos-server",
-  "version": "0.9.5",
+  "version": "0.9.6",
   "description": "",
   "description": "",
   "main": "test-server.js",
   "main": "test-server.js",
   "bugs": {
   "bugs": {

+ 26 - 7
src/configapi/patch.go

@@ -3,6 +3,7 @@ package configapi
 import (
 import (
 	"encoding/json"
 	"encoding/json"
 	"net/http"
 	"net/http"
+	"strings"
 
 
 	"github.com/azukaar/cosmos-server/src/utils"
 	"github.com/azukaar/cosmos-server/src/utils"
 )
 )
@@ -18,13 +19,15 @@ func ConfigApiPatch(w http.ResponseWriter, req *http.Request) {
 		return
 		return
 	}
 	}
 
 
+	utils.Log("RouteSettingsUpdate: Patching config")
+
 	utils.ConfigLock.Lock()
 	utils.ConfigLock.Lock()
 	defer utils.ConfigLock.Unlock()
 	defer utils.ConfigLock.Unlock()
 
 
 	var updateReq UpdateRouteRequest
 	var updateReq UpdateRouteRequest
 	err := json.NewDecoder(req.Body).Decode(&updateReq)
 	err := json.NewDecoder(req.Body).Decode(&updateReq)
 	if err != nil {
 	if err != nil {
-		utils.Error("SettingsUpdate: Invalid Update Request", err)
+		utils.Error("RouteSettingsUpdate: Invalid Update Request", err)
 		utils.HTTPError(w, "Invalid Update Request", http.StatusBadRequest, "UR001")
 		utils.HTTPError(w, "Invalid Update Request", http.StatusBadRequest, "UR001")
 		return
 		return
 	}
 	}
@@ -35,7 +38,7 @@ func ConfigApiPatch(w http.ResponseWriter, req *http.Request) {
 
 
 	if updateReq.Operation != "add" {
 	if updateReq.Operation != "add" {
 		if updateReq.RouteName == "" {
 		if updateReq.RouteName == "" {
-			utils.Error("SettingsUpdate: RouteName must be provided", nil)
+			utils.Error("RouteSettingsUpdate: RouteName must be provided", nil)
 			utils.HTTPError(w, "RouteName must be provided", http.StatusBadRequest, "UR002")
 			utils.HTTPError(w, "RouteName must be provided", http.StatusBadRequest, "UR002")
 			return
 			return
 		}
 		}
@@ -48,7 +51,7 @@ func ConfigApiPatch(w http.ResponseWriter, req *http.Request) {
 		}
 		}
 	
 	
 		if routeIndex == -1 {
 		if routeIndex == -1 {
-			utils.Error("SettingsUpdate: Route not found: "+updateReq.RouteName, nil)
+			utils.Error("RouteSettingsUpdate: Route not found: "+updateReq.RouteName, nil)
 			utils.HTTPError(w, "Route not found", http.StatusNotFound, "UR002")
 			utils.HTTPError(w, "Route not found", http.StatusNotFound, "UR002")
 			return
 			return
 		}
 		}
@@ -56,40 +59,56 @@ func ConfigApiPatch(w http.ResponseWriter, req *http.Request) {
 
 
 	switch updateReq.Operation {
 	switch updateReq.Operation {
 		case "replace":
 		case "replace":
+			utils.Log("RouteSettingsUpdate: Replacing route: "+updateReq.RouteName)
 			if updateReq.NewRoute == nil {
 			if updateReq.NewRoute == nil {
-				utils.Error("SettingsUpdate: NewRoute must be provided for replace operation", nil)
+				utils.Error("RouteSettingsUpdate: NewRoute must be provided for replace operation", nil)
 				utils.HTTPError(w, "NewRoute must be provided for replace operation", http.StatusBadRequest, "UR003")
 				utils.HTTPError(w, "NewRoute must be provided for replace operation", http.StatusBadRequest, "UR003")
 				return
 				return
 			}
 			}
 			routes[routeIndex] = *updateReq.NewRoute
 			routes[routeIndex] = *updateReq.NewRoute
 		case "move_up":
 		case "move_up":
+			utils.Log("RouteSettingsUpdate: Moving up route: "+updateReq.RouteName)
 			if routeIndex > 0 {
 			if routeIndex > 0 {
 				routes[routeIndex-1], routes[routeIndex] = routes[routeIndex], routes[routeIndex-1]
 				routes[routeIndex-1], routes[routeIndex] = routes[routeIndex], routes[routeIndex-1]
 			}
 			}
 		case "move_down":
 		case "move_down":
+			utils.Log("RouteSettingsUpdate: Moving down route: "+updateReq.RouteName)
 			if routeIndex < len(routes)-1 {
 			if routeIndex < len(routes)-1 {
 				routes[routeIndex+1], routes[routeIndex] = routes[routeIndex], routes[routeIndex+1]
 				routes[routeIndex+1], routes[routeIndex] = routes[routeIndex], routes[routeIndex+1]
 			}
 			}
 		case "delete":
 		case "delete":
+			utils.Log("RouteSettingsUpdate: Deleting route: "+updateReq.RouteName)
 			routes = append(routes[:routeIndex], routes[routeIndex+1:]...)
 			routes = append(routes[:routeIndex], routes[routeIndex+1:]...)
 		case "add":
 		case "add":
+			utils.Log("RouteSettingsUpdate: Adding route")
 			if updateReq.NewRoute == nil {
 			if updateReq.NewRoute == nil {
-				utils.Error("SettingsUpdate: NewRoute must be provided for add operation", nil)
+				utils.Error("RouteSettingsUpdate: NewRoute must be provided for add operation", nil)
 				utils.HTTPError(w, "NewRoute must be provided for add operation", http.StatusBadRequest, "UR003")
 				utils.HTTPError(w, "NewRoute must be provided for add operation", http.StatusBadRequest, "UR003")
 				return
 				return
 			}
 			}
 			routes = append([]utils.ProxyRouteConfig{*updateReq.NewRoute}, routes...)
 			routes = append([]utils.ProxyRouteConfig{*updateReq.NewRoute}, routes...)
 		default:
 		default:
-			utils.Error("SettingsUpdate: Unsupported operation: "+updateReq.Operation, nil)
+			utils.Error("RouteSettingsUpdate: Unsupported operation: "+updateReq.Operation, nil)
 			utils.HTTPError(w, "Unsupported operation", http.StatusBadRequest, "UR004")
 			utils.HTTPError(w, "Unsupported operation", http.StatusBadRequest, "UR004")
 			return
 			return
 		}
 		}
 
 
 	config.HTTPConfig.ProxyConfig.Routes = routes
 	config.HTTPConfig.ProxyConfig.Routes = routes
 	utils.SetBaseMainConfig(config)
 	utils.SetBaseMainConfig(config)
-	//utils.NeedsRestart = true
 	
 	
 	utils.RestartHTTPServer()
 	utils.RestartHTTPServer()
+		
+	if updateReq.NewRoute.Mode == "SERVAPP" {
+		utils.Log("RouteSettingsUpdate: Service needs update: "+updateReq.NewRoute.Target)
+
+		target := updateReq.NewRoute.Target
+		tokens := strings.Split(target, ":")
+		name := tokens[1][2:]
+		
+		utils.Log("RouteSettingsUpdate: Service needs update: "+name)
+
+		utils.ReBootstrapContainer(name)
+	}
 
 
 	json.NewEncoder(w).Encode(map[string]interface{}{
 	json.NewEncoder(w).Encode(map[string]interface{}{
 		"status": "OK",
 		"status": "OK",

+ 1 - 1
src/docker/bootstrap.go

@@ -147,4 +147,4 @@ func BootstrapContainerFromTags(containerID string) error {
 	utils.Log("Done bootstrapping Container From Tags: " + container.Name)
 	utils.Log("Done bootstrapping Container From Tags: " + container.Name)
 
 
 	return nil
 	return nil
-}
+}

+ 2 - 0
src/httpServer.go

@@ -410,6 +410,8 @@ func StartServer() {
 
 
 func RestartServer() {
 func RestartServer() {
 	utils.LetsEncryptErrors = []string{}
 	utils.LetsEncryptErrors = []string{}
+	IconCache = map[string]CachedImage{}
+	
 	utils.Log("Restarting HTTP Server...")
 	utils.Log("Restarting HTTP Server...")
 	LoadConfig()
 	LoadConfig()
 
 

+ 5 - 5
src/icons.go

@@ -21,7 +21,7 @@ type CachedImage struct {
 	Body []byte
 	Body []byte
 }
 }
 
 
-var cache = make(map[string]CachedImage)
+var IconCache = make(map[string]CachedImage)
 
 
 func sendImage(w http.ResponseWriter, image CachedImage) {
 func sendImage(w http.ResponseWriter, image CachedImage) {
 		// Copy the response to the output
 		// Copy the response to the output
@@ -73,9 +73,9 @@ func GetFavicon(w http.ResponseWriter, req *http.Request) {
 		utils.Log("Fetch favicon for " + siteurl)
 		utils.Log("Fetch favicon for " + siteurl)
 
 
 		// Check if we have the favicon in cache
 		// Check if we have the favicon in cache
-		if _, ok := cache[siteurl]; ok {
+		if _, ok := IconCache[siteurl]; ok {
 			utils.Debug("Favicon in cache")
 			utils.Debug("Favicon in cache")
-			resp := cache[siteurl]
+			resp := IconCache[siteurl]
 			sendImage(w, resp)
 			sendImage(w, resp)
 			return
 			return
 		}
 		}
@@ -178,9 +178,9 @@ func GetFavicon(w http.ResponseWriter, req *http.Request) {
 						Body: body,
 						Body: body,
 					}
 					}
 
 
-					cache[siteurl] = finalImage
+					IconCache[siteurl] = finalImage
 
 
-					sendImage(w, cache[siteurl])
+					sendImage(w, IconCache[siteurl])
 					return
 					return
 				}
 				}
 			}
 			}

+ 2 - 0
src/index.go

@@ -13,6 +13,8 @@ import (
 
 
 func main() {
 func main() {
 	utils.Log("Starting...")
 	utils.Log("Starting...")
+	
+	utils.ReBootstrapContainer = docker.BootstrapContainerFromTags
 
 
 	rand.Seed(time.Now().UnixNano())
 	rand.Seed(time.Now().UnixNano())
 
 

+ 1 - 0
src/utils/utils.go

@@ -33,6 +33,7 @@ var NeedsRestart = false
 var UpdateAvailable = map[string]bool{}
 var UpdateAvailable = map[string]bool{}
 
 
 var RestartHTTPServer func()
 var RestartHTTPServer func()
+var ReBootstrapContainer func(string) error
 
 
 var LetsEncryptErrors = []string{}
 var LetsEncryptErrors = []string{}
 
 

+ 25 - 0
test-client.js

@@ -0,0 +1,25 @@
+const https = require('https');
+
+const options = {
+  hostname: 'radarr.yann-server.com', // Replace with your target URL
+  method: 'OPTIONS',
+  port: 443,
+  path: '/cosmos-ui', // Replace with your target path
+};
+
+const req = https.request(options, (res) => {
+  console.log('STATUS:', res.statusCode);
+  console.log('HEADERS:', JSON.stringify(res.headers, null, 2));
+
+  res.setEncoding('utf8');
+  res.on('data', (chunk) => {
+    console.log(`BODY: ${chunk}`);
+  });
+});
+
+req.on('error', (e) => {
+  console.error(`problem with request: ${e.message}`);
+});
+
+// Close the request
+req.end();

+ 17 - 31
test-server.js

@@ -1,37 +1,23 @@
+const https = require('https');
 
 
-const express = require('express')
-const app = express()
-const port = 3000
+const options = {
+  hostname: 'example.com', // Replace with your target URL
+  method: 'OPTIONS',
+};
 
 
-// console log every request sent
-app.use((req, res, next) => {
-  console.log(`[REQ] - ${req.method} ${req.url}`)
-  next()
-});
-
-app.get('/return/:status/:time', async (req, res) => {
-  const statusCode = parseInt(req.params.status);
-  const returnString =`Hello status ${statusCode} after ${req.params.time}ms !`
-
-  console.log(`[RES] - ${statusCode} ${returnString}`)
-  
-  await new Promise(resolve => setTimeout(resolve, req.params.time));
+const req = https.request(options, (res) => {
+  console.log('STATUS:', res.statusCode);
+  console.log('HEADERS:', JSON.stringify(res.headers, null, 2));
 
 
-  return res.status(statusCode).send(returnString)
+  res.setEncoding('utf8');
+  res.on('data', (chunk) => {
+    console.log(`BODY: ${chunk}`);
+  });
 });
 });
 
 
-app.get('/', (req, res) => {
-  console.log("[RES] - Hello World!")
-  res.send('Hello World!')
-})
-
-app.listen(port, () => {
-  console.log(`Example app listening on port ${port}`)
-})
+req.on('error', (e) => {
+  console.error(`problem with request: ${e.message}`);
+});
 
 
-// app.ws('/ws', function(ws, req) {
-//   ws.on('message', function(msg) {
-//     console.log(msg);
-//     ws.send(msg);
-//   });
-// });
+// Close the request
+req.end();