From 7ef4fec89611d915110af3e0bc396e858fc9f627 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 21 Jul 2024 18:21:27 +0800 Subject: [PATCH] fix: cannot ota upgrade when connect to remote node #424 --- api/system/router.go | 3 + app/README.md | 44 ++++++ app/src/version.json | 2 +- app/version.json | 2 +- app/vite.config.ts | 1 + ....timestamp-1721542436572-91822f5b8889d.mjs | 87 ------------ model/environment.go | 2 - router/routers.go | 130 +++++++++--------- 8 files changed, 115 insertions(+), 156 deletions(-) delete mode 100644 app/vite.config.ts.timestamp-1721542436572-91822f5b8889d.mjs diff --git a/api/system/router.go b/api/system/router.go index 728c4550..cd22866b 100644 --- a/api/system/router.go +++ b/api/system/router.go @@ -13,5 +13,8 @@ func InitPublicRouter(r *gin.RouterGroup) { func InitPrivateRouter(r *gin.RouterGroup) { r.GET("upgrade/release", GetRelease) r.GET("upgrade/current", GetCurrentVersion) +} + +func InitWebSocketRouter(r *gin.RouterGroup) { r.GET("upgrade/perform", PerformCoreUpgrade) } diff --git a/app/README.md b/app/README.md index 98f4a52a..63ba81c6 100644 --- a/app/README.md +++ b/app/README.md @@ -21,3 +21,47 @@ manual `h(...)` calls), you can enable Volar's Take Over mode by following these 2. Reload the VS Code window by running `Developer: Reload Window` from the command palette. You can learn more about Take Over mode [here](https://github.com/johnsoncodehk/volar/discussions/471). + +## Project Setup + +```sh +pnpm install +``` + +**Note:** The default target of the api proxy is `http://localhost:9000`, +if you need to change this, create the `.env` file in root directory and set your target in it. + +```env +VITE_PROXY_TARGET=http://localhost:9001 +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +**Note:** The default port of the dev server is `3002`, +if you need to change this, create the `.env` file in root directory and set your port in it. + +```env +VITE_PORT=3456 +``` + +### Code Style Check + +```sh +pnpm lint +``` + +### Type Check + +```sh +pnpm typecheck +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/app/src/version.json b/app/src/version.json index 426c3090..77eb052d 100644 --- a/app/src/version.json +++ b/app/src/version.json @@ -1 +1 @@ -{"version":"2.0.0-beta.26","build_id":141,"total_build":345} \ No newline at end of file +{"version":"2.0.0-beta.26","build_id":142,"total_build":346} \ No newline at end of file diff --git a/app/version.json b/app/version.json index 426c3090..77eb052d 100644 --- a/app/version.json +++ b/app/version.json @@ -1 +1 @@ -{"version":"2.0.0-beta.26","build_id":141,"total_build":345} \ No newline at end of file +{"version":"2.0.0-beta.26","build_id":142,"total_build":346} \ No newline at end of file diff --git a/app/vite.config.ts b/app/vite.config.ts index aabd1581..84d04c53 100644 --- a/app/vite.config.ts +++ b/app/vite.config.ts @@ -71,6 +71,7 @@ export default defineConfig(({ mode }) => { }, }, server: { + port: Number.parseInt(env.VITE_PORT) || 3002, proxy: { '/api': { target: env.VITE_PROXY_TARGET || 'http://localhost:9000', diff --git a/app/vite.config.ts.timestamp-1721542436572-91822f5b8889d.mjs b/app/vite.config.ts.timestamp-1721542436572-91822f5b8889d.mjs deleted file mode 100644 index 3d68ce47..00000000 --- a/app/vite.config.ts.timestamp-1721542436572-91822f5b8889d.mjs +++ /dev/null @@ -1,87 +0,0 @@ -// vite.config.ts -import { URL, fileURLToPath } from "node:url"; -import { defineConfig, loadEnv } from "file:///Users/Jacky/Sites/nginx-ui/app/node_modules/.pnpm/vite@5.3.4_@types+node@20.14.11_less@4.2.0/node_modules/vite/dist/node/index.js"; -import vue from "file:///Users/Jacky/Sites/nginx-ui/app/node_modules/.pnpm/@vitejs+plugin-vue@5.0.5_vite@5.3.4_@types+node@20.14.11_less@4.2.0__vue@3.4.33_typescript@5.3.3_/node_modules/@vitejs/plugin-vue/dist/index.mjs"; -import Components from "file:///Users/Jacky/Sites/nginx-ui/app/node_modules/.pnpm/unplugin-vue-components@0.26.0_@babel+parser@7.24.8_rollup@4.18.1_vue@3.4.33_typescript@5.3.3_/node_modules/unplugin-vue-components/dist/vite.js"; -import { AntDesignVueResolver } from "file:///Users/Jacky/Sites/nginx-ui/app/node_modules/.pnpm/unplugin-vue-components@0.26.0_@babel+parser@7.24.8_rollup@4.18.1_vue@3.4.33_typescript@5.3.3_/node_modules/unplugin-vue-components/dist/resolvers.js"; -import vueJsx from "file:///Users/Jacky/Sites/nginx-ui/app/node_modules/.pnpm/@vitejs+plugin-vue-jsx@3.1.0_vite@5.3.4_@types+node@20.14.11_less@4.2.0__vue@3.4.33_typescript@5.3.3_/node_modules/@vitejs/plugin-vue-jsx/dist/index.mjs"; -import vitePluginBuildId from "file:///Users/Jacky/Sites/nginx-ui/app/node_modules/.pnpm/vite-plugin-build-id@0.2.9_less@4.2.0/node_modules/vite-plugin-build-id/dist/index.js"; -import svgLoader from "file:///Users/Jacky/Sites/nginx-ui/app/node_modules/.pnpm/vite-svg-loader@5.1.0_vue@3.4.33_typescript@5.3.3_/node_modules/vite-svg-loader/index.js"; -import AutoImport from "file:///Users/Jacky/Sites/nginx-ui/app/node_modules/.pnpm/unplugin-auto-import@0.17.8_@vueuse+core@10.11.0_vue@3.4.33_typescript@5.3.3___rollup@4.18.1/node_modules/unplugin-auto-import/dist/vite.js"; -import DefineOptions from "file:///Users/Jacky/Sites/nginx-ui/app/node_modules/.pnpm/unplugin-vue-define-options@1.4.5_rollup@4.18.1_vue@3.4.33_typescript@5.3.3_/node_modules/unplugin-vue-define-options/dist/vite.mjs"; -var __vite_injected_original_import_meta_url = "file:///Users/Jacky/Sites/nginx-ui/app/vite.config.ts"; -var vite_config_default = defineConfig(({ mode }) => { - const env = loadEnv(mode, process.cwd(), ""); - return { - base: "./", - resolve: { - alias: { - "@": fileURLToPath(new URL("./src", __vite_injected_original_import_meta_url)) - }, - extensions: [ - ".mjs", - ".js", - ".ts", - ".jsx", - ".tsx", - ".json", - ".vue", - ".less" - ] - }, - plugins: [ - vue(), - vueJsx(), - vitePluginBuildId(), - svgLoader(), - Components({ - resolvers: [AntDesignVueResolver({ importStyle: false })], - directoryAsNamespace: true - }), - AutoImport({ - imports: [ - "vue", - "vue-router", - "pinia", - { - "@/gettext": [ - "$gettext", - "$pgettext", - "$ngettext", - "$npgettext" - ] - } - ], - vueTemplate: true - }), - DefineOptions() - ], - css: { - preprocessorOptions: { - less: { - modifyVars: { - "border-radius-base": "5px" - }, - javascriptEnabled: true - } - } - }, - server: { - proxy: { - "/api": { - target: env.VITE_PROXY_TARGET || "http://localhost:9000", - changeOrigin: true, - secure: false, - ws: true - } - } - }, - build: { - chunkSizeWarningLimit: 1e3 - } - }; -}); -export { - vite_config_default as default -}; -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvVXNlcnMvSmFja3kvU2l0ZXMvbmdpbngtdWkvYXBwXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvVXNlcnMvSmFja3kvU2l0ZXMvbmdpbngtdWkvYXBwL3ZpdGUuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9KYWNreS9TaXRlcy9uZ2lueC11aS9hcHAvdml0ZS5jb25maWcudHNcIjtpbXBvcnQgeyBVUkwsIGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCdcbmltcG9ydCB7IGRlZmluZUNvbmZpZywgbG9hZEVudiB9IGZyb20gJ3ZpdGUnXG5pbXBvcnQgdnVlIGZyb20gJ0B2aXRlanMvcGx1Z2luLXZ1ZSdcbmltcG9ydCBDb21wb25lbnRzIGZyb20gJ3VucGx1Z2luLXZ1ZS1jb21wb25lbnRzL3ZpdGUnXG5pbXBvcnQgeyBBbnREZXNpZ25WdWVSZXNvbHZlciB9IGZyb20gJ3VucGx1Z2luLXZ1ZS1jb21wb25lbnRzL3Jlc29sdmVycydcbmltcG9ydCB2dWVKc3ggZnJvbSAnQHZpdGVqcy9wbHVnaW4tdnVlLWpzeCdcblxuaW1wb3J0IHZpdGVQbHVnaW5CdWlsZElkIGZyb20gJ3ZpdGUtcGx1Z2luLWJ1aWxkLWlkJ1xuaW1wb3J0IHN2Z0xvYWRlciBmcm9tICd2aXRlLXN2Zy1sb2FkZXInXG5pbXBvcnQgQXV0b0ltcG9ydCBmcm9tICd1bnBsdWdpbi1hdXRvLWltcG9ydC92aXRlJ1xuaW1wb3J0IERlZmluZU9wdGlvbnMgZnJvbSAndW5wbHVnaW4tdnVlLWRlZmluZS1vcHRpb25zL3ZpdGUnXG5cbi8vIGh0dHBzOi8vdml0ZWpzLmRldi9jb25maWcvXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoKHsgbW9kZSB9KSA9PiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuL3ByZWZlci1nbG9iYWwvcHJvY2Vzc1xuICBjb25zdCBlbnYgPSBsb2FkRW52KG1vZGUsIHByb2Nlc3MuY3dkKCksICcnKVxuXG4gIHJldHVybiB7XG4gICAgYmFzZTogJy4vJyxcbiAgICByZXNvbHZlOiB7XG4gICAgICBhbGlhczoge1xuICAgICAgICAnQCc6IGZpbGVVUkxUb1BhdGgobmV3IFVSTCgnLi9zcmMnLCBpbXBvcnQubWV0YS51cmwpKSxcbiAgICAgIH0sXG4gICAgICBleHRlbnNpb25zOiBbXG4gICAgICAgICcubWpzJyxcbiAgICAgICAgJy5qcycsXG4gICAgICAgICcudHMnLFxuICAgICAgICAnLmpzeCcsXG4gICAgICAgICcudHN4JyxcbiAgICAgICAgJy5qc29uJyxcbiAgICAgICAgJy52dWUnLFxuICAgICAgICAnLmxlc3MnLFxuICAgICAgXSxcbiAgICB9LFxuICAgIHBsdWdpbnM6IFtcbiAgICAgIHZ1ZSgpLFxuICAgICAgdnVlSnN4KCksXG5cbiAgICAgIHZpdGVQbHVnaW5CdWlsZElkKCksXG4gICAgICBzdmdMb2FkZXIoKSxcbiAgICAgIENvbXBvbmVudHMoe1xuICAgICAgICByZXNvbHZlcnM6IFtBbnREZXNpZ25WdWVSZXNvbHZlcih7IGltcG9ydFN0eWxlOiBmYWxzZSB9KV0sXG4gICAgICAgIGRpcmVjdG9yeUFzTmFtZXNwYWNlOiB0cnVlLFxuICAgICAgfSksXG4gICAgICBBdXRvSW1wb3J0KHtcbiAgICAgICAgaW1wb3J0czogW1xuICAgICAgICAgICd2dWUnLFxuICAgICAgICAgICd2dWUtcm91dGVyJyxcbiAgICAgICAgICAncGluaWEnLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgICdAL2dldHRleHQnOiBbXG4gICAgICAgICAgICAgICckZ2V0dGV4dCcsXG4gICAgICAgICAgICAgICckcGdldHRleHQnLFxuICAgICAgICAgICAgICAnJG5nZXR0ZXh0JyxcbiAgICAgICAgICAgICAgJyRucGdldHRleHQnLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICB2dWVUZW1wbGF0ZTogdHJ1ZSxcbiAgICAgIH0pLFxuICAgICAgRGVmaW5lT3B0aW9ucygpLFxuICAgIF0sXG4gICAgY3NzOiB7XG4gICAgICBwcmVwcm9jZXNzb3JPcHRpb25zOiB7XG4gICAgICAgIGxlc3M6IHtcbiAgICAgICAgICBtb2RpZnlWYXJzOiB7XG4gICAgICAgICAgICAnYm9yZGVyLXJhZGl1cy1iYXNlJzogJzVweCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBqYXZhc2NyaXB0RW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBzZXJ2ZXI6IHtcbiAgICAgIHByb3h5OiB7XG4gICAgICAgICcvYXBpJzoge1xuICAgICAgICAgIHRhcmdldDogZW52LlZJVEVfUFJPWFlfVEFSR0VUIHx8ICdodHRwOi8vbG9jYWxob3N0OjkwMDAnLFxuICAgICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcbiAgICAgICAgICBzZWN1cmU6IGZhbHNlLFxuICAgICAgICAgIHdzOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICAgIGJ1aWxkOiB7XG4gICAgICBjaHVua1NpemVXYXJuaW5nTGltaXQ6IDEwMDAsXG4gICAgfSxcbiAgfVxufSlcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBK1EsU0FBUyxLQUFLLHFCQUFxQjtBQUNsVCxTQUFTLGNBQWMsZUFBZTtBQUN0QyxPQUFPLFNBQVM7QUFDaEIsT0FBTyxnQkFBZ0I7QUFDdkIsU0FBUyw0QkFBNEI7QUFDckMsT0FBTyxZQUFZO0FBRW5CLE9BQU8sdUJBQXVCO0FBQzlCLE9BQU8sZUFBZTtBQUN0QixPQUFPLGdCQUFnQjtBQUN2QixPQUFPLG1CQUFtQjtBQVY0SSxJQUFNLDJDQUEyQztBQWF2TixJQUFPLHNCQUFRLGFBQWEsQ0FBQyxFQUFFLEtBQUssTUFBTTtBQUV4QyxRQUFNLE1BQU0sUUFBUSxNQUFNLFFBQVEsSUFBSSxHQUFHLEVBQUU7QUFFM0MsU0FBTztBQUFBLElBQ0wsTUFBTTtBQUFBLElBQ04sU0FBUztBQUFBLE1BQ1AsT0FBTztBQUFBLFFBQ0wsS0FBSyxjQUFjLElBQUksSUFBSSxTQUFTLHdDQUFlLENBQUM7QUFBQSxNQUN0RDtBQUFBLE1BQ0EsWUFBWTtBQUFBLFFBQ1Y7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxJQUNBLFNBQVM7QUFBQSxNQUNQLElBQUk7QUFBQSxNQUNKLE9BQU87QUFBQSxNQUVQLGtCQUFrQjtBQUFBLE1BQ2xCLFVBQVU7QUFBQSxNQUNWLFdBQVc7QUFBQSxRQUNULFdBQVcsQ0FBQyxxQkFBcUIsRUFBRSxhQUFhLE1BQU0sQ0FBQyxDQUFDO0FBQUEsUUFDeEQsc0JBQXNCO0FBQUEsTUFDeEIsQ0FBQztBQUFBLE1BQ0QsV0FBVztBQUFBLFFBQ1QsU0FBUztBQUFBLFVBQ1A7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxZQUNFLGFBQWE7QUFBQSxjQUNYO0FBQUEsY0FDQTtBQUFBLGNBQ0E7QUFBQSxjQUNBO0FBQUEsWUFDRjtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQUEsUUFDQSxhQUFhO0FBQUEsTUFDZixDQUFDO0FBQUEsTUFDRCxjQUFjO0FBQUEsSUFDaEI7QUFBQSxJQUNBLEtBQUs7QUFBQSxNQUNILHFCQUFxQjtBQUFBLFFBQ25CLE1BQU07QUFBQSxVQUNKLFlBQVk7QUFBQSxZQUNWLHNCQUFzQjtBQUFBLFVBQ3hCO0FBQUEsVUFDQSxtQkFBbUI7QUFBQSxRQUNyQjtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsSUFDQSxRQUFRO0FBQUEsTUFDTixPQUFPO0FBQUEsUUFDTCxRQUFRO0FBQUEsVUFDTixRQUFRLElBQUkscUJBQXFCO0FBQUEsVUFDakMsY0FBYztBQUFBLFVBQ2QsUUFBUTtBQUFBLFVBQ1IsSUFBSTtBQUFBLFFBQ047QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLElBQ0EsT0FBTztBQUFBLE1BQ0wsdUJBQXVCO0FBQUEsSUFDekI7QUFBQSxFQUNGO0FBQ0YsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K diff --git a/model/environment.go b/model/environment.go index 1f9b1bc0..42ccc7dc 100644 --- a/model/environment.go +++ b/model/environment.go @@ -65,9 +65,7 @@ func (e *Environment) GetWebSocketURL(uri string) (decodedUri string, err error) if err != nil { return } - // http will be replaced with ws, https will be replaced with wss decodedUri = strings.ReplaceAll(decodedUri, "http", "ws") - return } diff --git a/router/routers.go b/router/routers.go index eaacc0c5..599a497b 100644 --- a/router/routers.go +++ b/router/routers.go @@ -1,79 +1,79 @@ package router import ( - "github.com/0xJacky/Nginx-UI/api/analytic" - "github.com/0xJacky/Nginx-UI/api/certificate" - "github.com/0xJacky/Nginx-UI/api/cluster" - "github.com/0xJacky/Nginx-UI/api/config" - "github.com/0xJacky/Nginx-UI/api/nginx" - "github.com/0xJacky/Nginx-UI/api/notification" - "github.com/0xJacky/Nginx-UI/api/openai" - "github.com/0xJacky/Nginx-UI/api/settings" - "github.com/0xJacky/Nginx-UI/api/sites" - "github.com/0xJacky/Nginx-UI/api/streams" - "github.com/0xJacky/Nginx-UI/api/system" - "github.com/0xJacky/Nginx-UI/api/template" - "github.com/0xJacky/Nginx-UI/api/terminal" - "github.com/0xJacky/Nginx-UI/api/upstream" - "github.com/0xJacky/Nginx-UI/api/user" - "github.com/gin-contrib/static" - "github.com/gin-gonic/gin" - "net/http" + "github.com/0xJacky/Nginx-UI/api/analytic" + "github.com/0xJacky/Nginx-UI/api/certificate" + "github.com/0xJacky/Nginx-UI/api/cluster" + "github.com/0xJacky/Nginx-UI/api/config" + "github.com/0xJacky/Nginx-UI/api/nginx" + "github.com/0xJacky/Nginx-UI/api/notification" + "github.com/0xJacky/Nginx-UI/api/openai" + "github.com/0xJacky/Nginx-UI/api/settings" + "github.com/0xJacky/Nginx-UI/api/sites" + "github.com/0xJacky/Nginx-UI/api/streams" + "github.com/0xJacky/Nginx-UI/api/system" + "github.com/0xJacky/Nginx-UI/api/template" + "github.com/0xJacky/Nginx-UI/api/terminal" + "github.com/0xJacky/Nginx-UI/api/upstream" + "github.com/0xJacky/Nginx-UI/api/user" + "github.com/gin-contrib/static" + "github.com/gin-gonic/gin" + "net/http" ) func InitRouter() *gin.Engine { - r := gin.New() - r.Use(gin.Logger()) - r.Use(recovery()) - r.Use(cacheJs()) - r.Use(ipWhiteList()) + r := gin.New() + r.Use(gin.Logger()) + r.Use(recovery()) + r.Use(cacheJs()) + r.Use(ipWhiteList()) - //r.Use(OperationSync()) + //r.Use(OperationSync()) - r.Use(static.Serve("/", mustFS(""))) + r.Use(static.Serve("/", mustFS(""))) - r.NoRoute(func(c *gin.Context) { - c.JSON(http.StatusNotFound, gin.H{ - "message": "not found", - }) - }) + r.NoRoute(func(c *gin.Context) { + c.JSON(http.StatusNotFound, gin.H{ + "message": "not found", + }) + }) - root := r.Group("/api") - { - system.InitPublicRouter(root) - user.InitAuthRouter(root) + root := r.Group("/api") + { + system.InitPublicRouter(root) + user.InitAuthRouter(root) - // Authorization required not websocket request - g := root.Group("/", authRequired(), proxy()) - { - analytic.InitRouter(g) - user.InitManageUserRouter(g) - nginx.InitRouter(g) - sites.InitRouter(g) - streams.InitRouter(g) - config.InitRouter(g) - template.InitRouter(g) - certificate.InitCertificateRouter(g) - certificate.InitDNSCredentialRouter(g) - certificate.InitAcmeUserRouter(g) - system.InitPrivateRouter(g) - settings.InitRouter(g) - openai.InitRouter(g) - cluster.InitRouter(g) - notification.InitRouter(g) - } + // Authorization required not websocket request + g := root.Group("/", authRequired(), proxy()) + { + analytic.InitRouter(g) + user.InitManageUserRouter(g) + nginx.InitRouter(g) + sites.InitRouter(g) + streams.InitRouter(g) + config.InitRouter(g) + template.InitRouter(g) + certificate.InitCertificateRouter(g) + certificate.InitDNSCredentialRouter(g) + certificate.InitAcmeUserRouter(g) + system.InitPrivateRouter(g) + settings.InitRouter(g) + openai.InitRouter(g) + cluster.InitRouter(g) + notification.InitRouter(g) + } - // Authorization required and websocket request - w := root.Group("/", authRequired(), proxyWs()) - { - analytic.InitWebSocketRouter(w) - certificate.InitCertificateWebSocketRouter(w) - terminal.InitRouter(w) - nginx.InitNginxLogRouter(w) - upstream.InitRouter(w) - } + // Authorization required and websocket request + w := root.Group("/", authRequired(), proxyWs()) + { + analytic.InitWebSocketRouter(w) + certificate.InitCertificateWebSocketRouter(w) + terminal.InitRouter(w) + nginx.InitNginxLogRouter(w) + upstream.InitRouter(w) + system.InitWebSocketRouter(w) + } + } - } - - return r + return r }