From 00fb7552bfb860491a55f922325d199638c06c24 Mon Sep 17 00:00:00 2001 From: Jacky Date: Mon, 7 Oct 2024 11:06:00 +0800 Subject: [PATCH] enhance: proxy settings --- api/openai/openai.go | 9 +- app/pnpm-lock.yaml | 52 ++-- docs/package.json | 4 +- docs/pnpm-lock.yaml | 356 +++++++++++++-------------- go.mod | 11 +- go.sum | 9 +- internal/analytic/node.go | 188 +++++++------- internal/cache/cache.go | 10 +- internal/cert/cert.go | 10 +- internal/cert/sync.go | 12 +- internal/config/sync.go | 10 +- internal/middleware/proxy.go | 18 +- internal/transport/transport.go | 44 ++++ internal/transport/transport_test.go | 42 ++++ model/acme_user.go | 11 +- 15 files changed, 439 insertions(+), 347 deletions(-) create mode 100644 internal/transport/transport.go create mode 100644 internal/transport/transport_test.go diff --git a/api/openai/openai.go b/api/openai/openai.go index 672f00a0..04ca388b 100644 --- a/api/openai/openai.go +++ b/api/openai/openai.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/internal/chatbot" + "github.com/0xJacky/Nginx-UI/internal/transport" "github.com/0xJacky/Nginx-UI/settings" "github.com/gin-gonic/gin" "github.com/pkg/errors" @@ -53,7 +54,7 @@ func MakeChatCompletionRequest(c *gin.Context) { config := openai.DefaultConfig(settings.OpenAISettings.Token) if settings.OpenAISettings.Proxy != "" { - proxyUrl, err := url.Parse(settings.OpenAISettings.Proxy) + t, err := transport.NewTransport(transport.WithProxy(settings.OpenAISettings.Proxy)) if err != nil { c.Stream(func(w io.Writer) bool { c.SSEvent("message", gin.H{ @@ -64,12 +65,8 @@ func MakeChatCompletionRequest(c *gin.Context) { }) return } - transport := &http.Transport{ - Proxy: http.ProxyURL(proxyUrl), - TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify}, - } config.HTTPClient = &http.Client{ - Transport: transport, + Transport: t, } } diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml index 5fd41b70..9659bfc6 100644 --- a/app/pnpm-lock.yaml +++ b/app/pnpm-lock.yaml @@ -110,7 +110,7 @@ importers: devDependencies: '@antfu/eslint-config-vue': specifier: ^0.43.1 - version: 0.43.1(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)(typescript@5.3.3) + version: 0.43.1(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)(typescript@5.3.3) '@simplewebauthn/types': specifier: ^10.0.0 version: 10.0.0 @@ -152,7 +152,7 @@ importers: version: 8.57.1 eslint-import-resolver-alias: specifier: ^1.1.2 - version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)) + version: 1.1.2(eslint-plugin-import@2.31.0) eslint-import-resolver-typescript: specifier: ^3.6.3 version: 3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1) @@ -1260,8 +1260,8 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - confbox@0.1.7: - resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -2269,8 +2269,8 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} - mlly@1.7.1: - resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} + mlly@1.7.2: + resolution: {integrity: sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -3197,14 +3197,14 @@ snapshots: '@ant-design/icons-svg': 4.4.2 vue: 3.5.11(typescript@5.3.3) - '@antfu/eslint-config-basic@0.43.1(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)(typescript@5.3.3)': + '@antfu/eslint-config-basic@0.43.1(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)(typescript@5.3.3)': dependencies: '@stylistic/eslint-plugin-js': 0.0.4 eslint: 8.57.1 eslint-plugin-antfu: 0.43.1(eslint@8.57.1)(typescript@5.3.3) eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.1) eslint-plugin-html: 7.1.0 - eslint-plugin-import: eslint-plugin-i@2.28.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: eslint-plugin-i@2.28.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) eslint-plugin-jsdoc: 46.10.1(eslint@8.57.1) eslint-plugin-jsonc: 2.16.0(eslint@8.57.1) eslint-plugin-markdown: 3.0.1(eslint@8.57.1) @@ -3224,9 +3224,9 @@ snapshots: - supports-color - typescript - '@antfu/eslint-config-ts@0.43.1(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)(typescript@5.3.3)': + '@antfu/eslint-config-ts@0.43.1(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)(typescript@5.3.3)': dependencies: - '@antfu/eslint-config-basic': 0.43.1(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)(typescript@5.3.3) + '@antfu/eslint-config-basic': 0.43.1(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)(typescript@5.3.3) '@stylistic/eslint-plugin-ts': 0.0.4(eslint@8.57.1)(typescript@5.3.3) '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3) '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.3.3) @@ -3239,10 +3239,10 @@ snapshots: - jest - supports-color - '@antfu/eslint-config-vue@0.43.1(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)(typescript@5.3.3)': + '@antfu/eslint-config-vue@0.43.1(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)(typescript@5.3.3)': dependencies: - '@antfu/eslint-config-basic': 0.43.1(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)(typescript@5.3.3) - '@antfu/eslint-config-ts': 0.43.1(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)(typescript@5.3.3) + '@antfu/eslint-config-basic': 0.43.1(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)(typescript@5.3.3) + '@antfu/eslint-config-ts': 0.43.1(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)(typescript@5.3.3) eslint: 8.57.1 eslint-plugin-vue: 9.28.0(eslint@8.57.1) local-pkg: 0.4.3 @@ -4354,7 +4354,7 @@ snapshots: concat-map@0.0.1: {} - confbox@0.1.7: {} + confbox@0.1.8: {} convert-source-map@2.0.0: {} @@ -4643,7 +4643,7 @@ snapshots: eslint: 8.57.1 semver: 7.6.3 - eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)): + eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0): dependencies: eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) @@ -4661,7 +4661,7 @@ snapshots: debug: 4.3.7 enhanced-resolve: 5.17.1 eslint: 8.57.1 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 @@ -4674,7 +4674,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: @@ -4710,13 +4710,13 @@ snapshots: dependencies: htmlparser2: 8.0.2 - eslint-plugin-i@2.28.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): + eslint-plugin-i@2.28.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): dependencies: debug: 3.2.7 doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) get-tsconfig: 4.8.1 is-glob: 4.0.3 minimatch: 3.1.2 @@ -4739,7 +4739,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -5395,7 +5395,7 @@ snapshots: local-pkg@0.5.0: dependencies: - mlly: 1.7.1 + mlly: 1.7.2 pkg-types: 1.2.0 locate-path@5.0.0: @@ -5503,7 +5503,7 @@ snapshots: minipass@7.1.2: {} - mlly@1.7.1: + mlly@1.7.2: dependencies: acorn: 8.12.1 pathe: 1.1.2 @@ -5693,8 +5693,8 @@ snapshots: pkg-types@1.2.0: dependencies: - confbox: 0.1.7 - mlly: 1.7.1 + confbox: 0.1.8 + mlly: 1.7.2 pathe: 1.1.2 pluralize@8.0.0: {} @@ -6211,7 +6211,7 @@ snapshots: fast-glob: 3.3.2 local-pkg: 0.5.0 magic-string: 0.30.11 - mlly: 1.7.1 + mlly: 1.7.2 pathe: 1.1.2 pkg-types: 1.2.0 scule: 1.3.0 @@ -6256,7 +6256,7 @@ snapshots: local-pkg: 0.5.0 magic-string: 0.30.11 minimatch: 9.0.5 - mlly: 1.7.1 + mlly: 1.7.2 unplugin: 1.14.1(webpack-sources@3.2.3) vue: 3.5.11(typescript@5.3.3) optionalDependencies: diff --git a/docs/package.json b/docs/package.json index 2e1b8721..a01a0c9c 100644 --- a/docs/package.json +++ b/docs/package.json @@ -8,10 +8,10 @@ }, "dependencies": { "vitepress": "^1.3.4", - "vue": "^3.5.6" + "vue": "^3.5.11" }, "devDependencies": { - "@types/node": "^20.16.5", + "@types/node": "^22.7.4", "less": "^4.2.0" }, "license": "AGPL-3.0", diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml index f4959aac..e06d03fe 100644 --- a/docs/pnpm-lock.yaml +++ b/docs/pnpm-lock.yaml @@ -10,14 +10,14 @@ importers: dependencies: vitepress: specifier: ^1.3.4 - version: 1.3.4(@algolia/client-search@4.24.0)(@types/node@20.16.5)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0) + version: 1.3.4(@algolia/client-search@4.24.0)(@types/node@22.7.4)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0) vue: - specifier: ^3.5.6 - version: 3.5.6 + specifier: ^3.5.11 + version: 3.5.11 devDependencies: '@types/node': - specifier: ^20.16.5 - version: 20.16.5 + specifier: ^22.7.4 + version: 22.7.4 less: specifier: ^4.2.0 version: 4.2.0 @@ -89,31 +89,31 @@ packages: '@algolia/transporter@4.24.0': resolution: {integrity: sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==} - '@babel/helper-string-parser@7.24.8': - resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} + '@babel/helper-string-parser@7.25.7': + resolution: {integrity: sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.24.7': - resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + '@babel/helper-validator-identifier@7.25.7': + resolution: {integrity: sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==} engines: {node: '>=6.9.0'} - '@babel/parser@7.25.6': - resolution: {integrity: sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==} + '@babel/parser@7.25.7': + resolution: {integrity: sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/types@7.25.6': - resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==} + '@babel/types@7.25.7': + resolution: {integrity: sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==} engines: {node: '>=6.9.0'} - '@docsearch/css@3.6.1': - resolution: {integrity: sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==} + '@docsearch/css@3.6.2': + resolution: {integrity: sha512-vKNZepO2j7MrYBTZIGXvlUOIR+v9KRf70FApRgovWrj3GTs1EITz/Xb0AOlm1xsQBp16clVZj1SY/qaOJbQtZw==} - '@docsearch/js@3.6.1': - resolution: {integrity: sha512-erI3RRZurDr1xES5hvYJ3Imp7jtrXj6f1xYIzDzxiS7nNBufYWPbJwrmMqWC5g9y165PmxEmN9pklGCdLi0Iqg==} + '@docsearch/js@3.6.2': + resolution: {integrity: sha512-pS4YZF+VzUogYrkblCucQ0Oy2m8Wggk8Kk7lECmZM60hTbaydSIhJTTiCrmoxtBqV8wxORnOqcqqOfbmkkQEcA==} - '@docsearch/react@3.6.1': - resolution: {integrity: sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==} + '@docsearch/react@3.6.2': + resolution: {integrity: sha512-rtZce46OOkVflCQH71IdbXSFK+S8iJZlUF56XBW5rIgx/eG5qoomC7Ag3anZson1bBac/JFQn7XOBfved/IMRA==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' react: '>= 16.8.0 < 19.0.0' @@ -350,23 +350,23 @@ packages: cpu: [x64] os: [win32] - '@shikijs/core@1.17.7': - resolution: {integrity: sha512-ZnIDxFu/yvje3Q8owSHaEHd+bu/jdWhHAaJ17ggjXofHx5rc4bhpCSW+OjC6smUBi5s5dd023jWtZ1gzMu/yrw==} + '@shikijs/core@1.21.1': + resolution: {integrity: sha512-scBQo4V4O4WZLEDg11e75UPmXoCMq4Ya2A16U6efi/aTiR4o7T/GMNWZs2rq1U8dEvFKGxJZxiUy+tXgmr/4vw==} - '@shikijs/engine-javascript@1.17.7': - resolution: {integrity: sha512-wwSf7lKPsm+hiYQdX+1WfOXujtnUG6fnN4rCmExxa4vo+OTmvZ9B1eKauilvol/LHUPrQgW12G3gzem7pY5ckw==} + '@shikijs/engine-javascript@1.21.1': + resolution: {integrity: sha512-29EG4KYKlAona8yikEx8uoKbK7N2YoXUO26LS1GOIxpMMIAlQS9UFONg95lkGmIfp1rRcvCvSpYYIJ/blsQxvg==} - '@shikijs/engine-oniguruma@1.17.7': - resolution: {integrity: sha512-pvSYGnVeEIconU28NEzBXqSQC/GILbuNbAHwMoSfdTBrobKAsV1vq2K4cAgiaW1TJceLV9QMGGh18hi7cCzbVQ==} + '@shikijs/engine-oniguruma@1.21.1': + resolution: {integrity: sha512-PvfEtXCDbQZc9ud0SC0bPiuMbul44Cv0Ky2go4SsvVkYAAKYJsMe/Hx7nxThW8yS0r+w8USa0WfOtQKsD9DU9A==} - '@shikijs/transformers@1.17.7': - resolution: {integrity: sha512-Nu7DaUT/qHDqbEsWBBqX6MyPMFbR4hUZcK11TA+zU/nPu9eDFE8v0p+n+eT4A3+3mxX6czMSF81W4QNsQ/NSpQ==} + '@shikijs/transformers@1.21.1': + resolution: {integrity: sha512-97csTb0Gv8eLbglPDhNZTuAI9eCXOujNqD4qK6H0cjFNK+NBhkRIU02RgmYHZ7yNyLary6cEzY6WmUWb+al3MQ==} - '@shikijs/types@1.17.7': - resolution: {integrity: sha512-+qA4UyhWLH2q4EFd+0z4K7GpERDU+c+CN2XYD3sC+zjvAr5iuwD1nToXZMt1YODshjkEGEDV86G7j66bKjqDdg==} + '@shikijs/types@1.21.1': + resolution: {integrity: sha512-yLuTJTCHmYznerJ0nxF+f2rBKHQf2FMAd08QL/3du2xNBy/7yQ8CjuKN4Zc+Pk0vfIFzdBoxdzvEXE4JtXoR4Q==} - '@shikijs/vscode-textmate@9.2.2': - resolution: {integrity: sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg==} + '@shikijs/vscode-textmate@9.3.0': + resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -386,8 +386,8 @@ packages: '@types/mdurl@2.0.0': resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} - '@types/node@20.16.5': - resolution: {integrity: sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==} + '@types/node@22.7.4': + resolution: {integrity: sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==} '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -398,50 +398,50 @@ packages: '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@vitejs/plugin-vue@5.1.3': - resolution: {integrity: sha512-3xbWsKEKXYlmX82aOHufFQVnkbMC/v8fLpWwh6hWOUrK5fbbtBh9Q/WWse27BFgSy2/e2c0fz5Scgya9h2GLhw==} + '@vitejs/plugin-vue@5.1.4': + resolution: {integrity: sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: vite: ^5.0.0 vue: ^3.2.25 - '@vue/compiler-core@3.5.6': - resolution: {integrity: sha512-r+gNu6K4lrvaQLQGmf+1gc41p3FO2OUJyWmNqaIITaJU6YFiV5PtQSFZt8jfztYyARwqhoCayjprC7KMvT3nRA==} + '@vue/compiler-core@3.5.11': + resolution: {integrity: sha512-PwAdxs7/9Hc3ieBO12tXzmTD+Ln4qhT/56S+8DvrrZ4kLDn4Z/AMUr8tXJD0axiJBS0RKIoNaR0yMuQB9v9Udg==} - '@vue/compiler-dom@3.5.6': - resolution: {integrity: sha512-xRXqxDrIqK8v8sSScpistyYH0qYqxakpsIvqMD2e5sV/PXQ1mTwtXp4k42yHK06KXxKSmitop9e45Ui/3BrTEw==} + '@vue/compiler-dom@3.5.11': + resolution: {integrity: sha512-pyGf8zdbDDRkBrEzf8p7BQlMKNNF5Fk/Cf/fQ6PiUz9at4OaUfyXW0dGJTo2Vl1f5U9jSLCNf0EZJEogLXoeew==} - '@vue/compiler-sfc@3.5.6': - resolution: {integrity: sha512-pjWJ8Kj9TDHlbF5LywjVso+BIxCY5wVOLhkEXRhuCHDxPFIeX1zaFefKs8RYoHvkSMqRWt93a0f2gNJVJixHwg==} + '@vue/compiler-sfc@3.5.11': + resolution: {integrity: sha512-gsbBtT4N9ANXXepprle+X9YLg2htQk1sqH/qGJ/EApl+dgpUBdTv3yP7YlR535uHZY3n6XaR0/bKo0BgwwDniw==} - '@vue/compiler-ssr@3.5.6': - resolution: {integrity: sha512-VpWbaZrEOCqnmqjE83xdwegtr5qO/2OPUC6veWgvNqTJ3bYysz6vY3VqMuOijubuUYPRpG3OOKIh9TD0Stxb9A==} + '@vue/compiler-ssr@3.5.11': + resolution: {integrity: sha512-P4+GPjOuC2aFTk1Z4WANvEhyOykcvEd5bIj2KVNGKGfM745LaXGr++5njpdBTzVz5pZifdlR1kpYSJJpIlSePA==} - '@vue/devtools-api@7.4.5': - resolution: {integrity: sha512-PX9uXirHOY2P99kb1cP3DxWZojFW3acNMqd+l4i5nKcqY59trXTOfwDZXt2Qifu0OU1izAQb76Ur6NPVldF2KQ==} + '@vue/devtools-api@7.4.6': + resolution: {integrity: sha512-XipBV5k0/IfTr0sNBDTg7OBUCp51cYMMXyPxLXJZ4K/wmUeMqt8cVdr2ZZGOFq+si/jTyCYnNxeKoyev5DOUUA==} - '@vue/devtools-kit@7.4.5': - resolution: {integrity: sha512-Uuki4Z6Bc/ExvtlPkeDNGSAe4580R+HPcVABfTE9TF7BTz3Nntk7vxIRUyWblZkUEcB/x+wn2uofyt5i2LaUew==} + '@vue/devtools-kit@7.4.6': + resolution: {integrity: sha512-NbYBwPWgEic1AOd9bWExz9weBzFdjiIfov0yRn4DrRfR+EQJCI9dn4I0XS7IxYGdkmUJi8mFW42LLk18WsGqew==} - '@vue/devtools-shared@7.4.5': - resolution: {integrity: sha512-2XgUOkL/7QDmyYI9J7cm+rz/qBhcGv+W5+i1fhwdQ0HQ1RowhdK66F0QBuJSz/5k12opJY8eN6m03/XZMs7imQ==} + '@vue/devtools-shared@7.4.6': + resolution: {integrity: sha512-rPeSBzElnHYMB05Cc056BQiJpgocQjY8XVulgni+O9a9Gr9tNXgPteSzFFD+fT/iWMxNuUgGKs9CuW5DZewfIg==} - '@vue/reactivity@3.5.6': - resolution: {integrity: sha512-shZ+KtBoHna5GyUxWfoFVBCVd7k56m6lGhk5e+J9AKjheHF6yob5eukssHRI+rzvHBiU1sWs/1ZhNbLExc5oYQ==} + '@vue/reactivity@3.5.11': + resolution: {integrity: sha512-Nqo5VZEn8MJWlCce8XoyVqHZbd5P2NH+yuAaFzuNSR96I+y1cnuUiq7xfSG+kyvLSiWmaHTKP1r3OZY4mMD50w==} - '@vue/runtime-core@3.5.6': - resolution: {integrity: sha512-FpFULR6+c2lI+m1fIGONLDqPQO34jxV8g6A4wBOgne8eSRHP6PQL27+kWFIx5wNhhjkO7B4rgtsHAmWv7qKvbg==} + '@vue/runtime-core@3.5.11': + resolution: {integrity: sha512-7PsxFGqwfDhfhh0OcDWBG1DaIQIVOLgkwA5q6MtkPiDFjp5gohVnJEahSktwSFLq7R5PtxDKy6WKURVN1UDbzA==} - '@vue/runtime-dom@3.5.6': - resolution: {integrity: sha512-SDPseWre45G38ENH2zXRAHL1dw/rr5qp91lS4lt/nHvMr0MhsbCbihGAWLXNB/6VfFOJe2O+RBRkXU+CJF7/sw==} + '@vue/runtime-dom@3.5.11': + resolution: {integrity: sha512-GNghjecT6IrGf0UhuYmpgaOlN7kxzQBhxWEn08c/SQDxv1yy4IXI1bn81JgEpQ4IXjRxWtPyI8x0/7TF5rPfYQ==} - '@vue/server-renderer@3.5.6': - resolution: {integrity: sha512-zivnxQnOnwEXVaT9CstJ64rZFXMS5ZkKxCjDQKiMSvUhXRzFLWZVbaBiNF4HGDqGNNsTgmjcCSmU6TB/0OOxLA==} + '@vue/server-renderer@3.5.11': + resolution: {integrity: sha512-cVOwYBxR7Wb1B1FoxYvtjJD8X/9E5nlH4VSkJy2uMA1MzYNdzAAB//l8nrmN9py/4aP+3NjWukf9PZ3TeWULaA==} peerDependencies: - vue: 3.5.6 + vue: 3.5.11 - '@vue/shared@3.5.6': - resolution: {integrity: sha512-eidH0HInnL39z6wAt6SFIwBrvGOpDWsDxlw3rCgo1B+CQ1781WzQUSU3YjxgdkcJo9Q8S6LmXTkvI+cLHGkQfA==} + '@vue/shared@3.5.11': + resolution: {integrity: sha512-W8GgysJVnFo81FthhzurdRAWP/byq3q2qIw70e0JWblzVhjgOMiC2GyovXrZTFQJnFVryYaKGP3Tc9vYzYm6PQ==} '@vueuse/core@11.1.0': resolution: {integrity: sha512-P6dk79QYA6sKQnghrUz/1tHi0n9mrb/iO1WTMk/ElLmTyNqgDeSZ3wcDf6fRBGzRJbeG1dxzEOvLENMjr+E3fg==} @@ -658,8 +658,8 @@ packages: resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} engines: {node: ^10 || ^12 || >=14} - preact@10.24.0: - resolution: {integrity: sha512-aK8Cf+jkfyuZ0ZZRG9FbYqwmEiGQ4y/PUO4SuTWoyWL244nZZh7bd5h2APd4rSNDYTBNghg1L+5iJN3Skxtbsw==} + preact@10.24.2: + resolution: {integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==} property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} @@ -667,8 +667,8 @@ packages: prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} - regex@4.3.2: - resolution: {integrity: sha512-kK/AA3A9K6q2js89+VMymcboLOlF5lZRCYJv3gzszXFHBr6kO6qLGzbm+UIugBEV8SMMKCTR59txoY6ctRHYVw==} + regex@4.3.3: + resolution: {integrity: sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==} rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} @@ -691,8 +691,8 @@ packages: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true - shiki@1.17.7: - resolution: {integrity: sha512-Zf6hNtWhFyF4XP5OOsXkBTEx9JFPiN0TQx4wSe+Vqeuczewgk2vT4IZhF4gka55uelm052BD5BaHavNqUNZd+A==} + shiki@1.21.1: + resolution: {integrity: sha512-jSOKRHyQJxGOW3kJflmwzHJbp/kjg6hP8LYuVbCPw5oyX+fSNNoCywvcCD3w9eHbj2rvNljt7YMa5BP5Xi+nHg==} source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} @@ -753,8 +753,8 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite@5.4.6: - resolution: {integrity: sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==} + vite@5.4.8: + resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -807,8 +807,8 @@ packages: '@vue/composition-api': optional: true - vue@3.5.6: - resolution: {integrity: sha512-zv+20E2VIYbcJOzJPUWp03NOGFhMmpCKOfSxVTmCYyYFFko48H9tmuQFzYj7tu4qX1AeXlp9DmhIP89/sSxxhw==} + vue@3.5.11: + resolution: {integrity: sha512-/8Wurrd9J3lb72FTQS7gRMNQD4nztTtKPmuDuPuhqXmmpD6+skVjAeahNpVzsuky6Sy9gy7wn8UadqPtt9SQIg==} peerDependencies: typescript: '*' peerDependenciesMeta: @@ -924,26 +924,26 @@ snapshots: '@algolia/logger-common': 4.24.0 '@algolia/requester-common': 4.24.0 - '@babel/helper-string-parser@7.24.8': {} + '@babel/helper-string-parser@7.25.7': {} - '@babel/helper-validator-identifier@7.24.7': {} + '@babel/helper-validator-identifier@7.25.7': {} - '@babel/parser@7.25.6': + '@babel/parser@7.25.7': dependencies: - '@babel/types': 7.25.6 + '@babel/types': 7.25.7 - '@babel/types@7.25.6': + '@babel/types@7.25.7': dependencies: - '@babel/helper-string-parser': 7.24.8 - '@babel/helper-validator-identifier': 7.24.7 + '@babel/helper-string-parser': 7.25.7 + '@babel/helper-validator-identifier': 7.25.7 to-fast-properties: 2.0.0 - '@docsearch/css@3.6.1': {} + '@docsearch/css@3.6.2': {} - '@docsearch/js@3.6.1(@algolia/client-search@4.24.0)(search-insights@2.13.0)': + '@docsearch/js@3.6.2(@algolia/client-search@4.24.0)(search-insights@2.13.0)': dependencies: - '@docsearch/react': 3.6.1(@algolia/client-search@4.24.0)(search-insights@2.13.0) - preact: 10.24.0 + '@docsearch/react': 3.6.2(@algolia/client-search@4.24.0)(search-insights@2.13.0) + preact: 10.24.2 transitivePeerDependencies: - '@algolia/client-search' - '@types/react' @@ -951,11 +951,11 @@ snapshots: - react-dom - search-insights - '@docsearch/react@3.6.1(@algolia/client-search@4.24.0)(search-insights@2.13.0)': + '@docsearch/react@3.6.2(@algolia/client-search@4.24.0)(search-insights@2.13.0)': dependencies: '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0)(search-insights@2.13.0) '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0) - '@docsearch/css': 3.6.1 + '@docsearch/css': 3.6.2 algoliasearch: 4.24.0 optionalDependencies: search-insights: 2.13.0 @@ -1081,36 +1081,36 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.24.0': optional: true - '@shikijs/core@1.17.7': + '@shikijs/core@1.21.1': dependencies: - '@shikijs/engine-javascript': 1.17.7 - '@shikijs/engine-oniguruma': 1.17.7 - '@shikijs/types': 1.17.7 - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/engine-javascript': 1.21.1 + '@shikijs/engine-oniguruma': 1.21.1 + '@shikijs/types': 1.21.1 + '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 hast-util-to-html: 9.0.3 - '@shikijs/engine-javascript@1.17.7': + '@shikijs/engine-javascript@1.21.1': dependencies: - '@shikijs/types': 1.17.7 - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/types': 1.21.1 + '@shikijs/vscode-textmate': 9.3.0 oniguruma-to-js: 0.4.3 - '@shikijs/engine-oniguruma@1.17.7': + '@shikijs/engine-oniguruma@1.21.1': dependencies: - '@shikijs/types': 1.17.7 - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/types': 1.21.1 + '@shikijs/vscode-textmate': 9.3.0 - '@shikijs/transformers@1.17.7': + '@shikijs/transformers@1.21.1': dependencies: - shiki: 1.17.7 + shiki: 1.21.1 - '@shikijs/types@1.17.7': + '@shikijs/types@1.21.1': dependencies: - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 - '@shikijs/vscode-textmate@9.2.2': {} + '@shikijs/vscode-textmate@9.3.0': {} '@types/estree@1.0.6': {} @@ -1131,7 +1131,7 @@ snapshots: '@types/mdurl@2.0.0': {} - '@types/node@20.16.5': + '@types/node@22.7.4': dependencies: undici-types: 6.19.8 @@ -1141,48 +1141,48 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-vue@5.1.3(vite@5.4.6(@types/node@20.16.5)(less@4.2.0))(vue@3.5.6)': + '@vitejs/plugin-vue@5.1.4(vite@5.4.8(@types/node@22.7.4)(less@4.2.0))(vue@3.5.11)': dependencies: - vite: 5.4.6(@types/node@20.16.5)(less@4.2.0) - vue: 3.5.6 + vite: 5.4.8(@types/node@22.7.4)(less@4.2.0) + vue: 3.5.11 - '@vue/compiler-core@3.5.6': + '@vue/compiler-core@3.5.11': dependencies: - '@babel/parser': 7.25.6 - '@vue/shared': 3.5.6 + '@babel/parser': 7.25.7 + '@vue/shared': 3.5.11 entities: 4.5.0 estree-walker: 2.0.2 source-map-js: 1.2.1 - '@vue/compiler-dom@3.5.6': + '@vue/compiler-dom@3.5.11': dependencies: - '@vue/compiler-core': 3.5.6 - '@vue/shared': 3.5.6 + '@vue/compiler-core': 3.5.11 + '@vue/shared': 3.5.11 - '@vue/compiler-sfc@3.5.6': + '@vue/compiler-sfc@3.5.11': dependencies: - '@babel/parser': 7.25.6 - '@vue/compiler-core': 3.5.6 - '@vue/compiler-dom': 3.5.6 - '@vue/compiler-ssr': 3.5.6 - '@vue/shared': 3.5.6 + '@babel/parser': 7.25.7 + '@vue/compiler-core': 3.5.11 + '@vue/compiler-dom': 3.5.11 + '@vue/compiler-ssr': 3.5.11 + '@vue/shared': 3.5.11 estree-walker: 2.0.2 magic-string: 0.30.11 postcss: 8.4.47 source-map-js: 1.2.1 - '@vue/compiler-ssr@3.5.6': + '@vue/compiler-ssr@3.5.11': dependencies: - '@vue/compiler-dom': 3.5.6 - '@vue/shared': 3.5.6 + '@vue/compiler-dom': 3.5.11 + '@vue/shared': 3.5.11 - '@vue/devtools-api@7.4.5': + '@vue/devtools-api@7.4.6': dependencies: - '@vue/devtools-kit': 7.4.5 + '@vue/devtools-kit': 7.4.6 - '@vue/devtools-kit@7.4.5': + '@vue/devtools-kit@7.4.6': dependencies: - '@vue/devtools-shared': 7.4.5 + '@vue/devtools-shared': 7.4.6 birpc: 0.2.17 hookable: 5.5.3 mitt: 3.0.1 @@ -1190,49 +1190,49 @@ snapshots: speakingurl: 14.0.1 superjson: 2.2.1 - '@vue/devtools-shared@7.4.5': + '@vue/devtools-shared@7.4.6': dependencies: rfdc: 1.4.1 - '@vue/reactivity@3.5.6': + '@vue/reactivity@3.5.11': dependencies: - '@vue/shared': 3.5.6 + '@vue/shared': 3.5.11 - '@vue/runtime-core@3.5.6': + '@vue/runtime-core@3.5.11': dependencies: - '@vue/reactivity': 3.5.6 - '@vue/shared': 3.5.6 + '@vue/reactivity': 3.5.11 + '@vue/shared': 3.5.11 - '@vue/runtime-dom@3.5.6': + '@vue/runtime-dom@3.5.11': dependencies: - '@vue/reactivity': 3.5.6 - '@vue/runtime-core': 3.5.6 - '@vue/shared': 3.5.6 + '@vue/reactivity': 3.5.11 + '@vue/runtime-core': 3.5.11 + '@vue/shared': 3.5.11 csstype: 3.1.3 - '@vue/server-renderer@3.5.6(vue@3.5.6)': + '@vue/server-renderer@3.5.11(vue@3.5.11)': dependencies: - '@vue/compiler-ssr': 3.5.6 - '@vue/shared': 3.5.6 - vue: 3.5.6 + '@vue/compiler-ssr': 3.5.11 + '@vue/shared': 3.5.11 + vue: 3.5.11 - '@vue/shared@3.5.6': {} + '@vue/shared@3.5.11': {} - '@vueuse/core@11.1.0(vue@3.5.6)': + '@vueuse/core@11.1.0(vue@3.5.11)': dependencies: '@types/web-bluetooth': 0.0.20 '@vueuse/metadata': 11.1.0 - '@vueuse/shared': 11.1.0(vue@3.5.6) - vue-demi: 0.14.10(vue@3.5.6) + '@vueuse/shared': 11.1.0(vue@3.5.11) + vue-demi: 0.14.10(vue@3.5.11) transitivePeerDependencies: - '@vue/composition-api' - vue - '@vueuse/integrations@11.1.0(focus-trap@7.6.0)(vue@3.5.6)': + '@vueuse/integrations@11.1.0(focus-trap@7.6.0)(vue@3.5.11)': dependencies: - '@vueuse/core': 11.1.0(vue@3.5.6) - '@vueuse/shared': 11.1.0(vue@3.5.6) - vue-demi: 0.14.10(vue@3.5.6) + '@vueuse/core': 11.1.0(vue@3.5.11) + '@vueuse/shared': 11.1.0(vue@3.5.11) + vue-demi: 0.14.10(vue@3.5.11) optionalDependencies: focus-trap: 7.6.0 transitivePeerDependencies: @@ -1241,9 +1241,9 @@ snapshots: '@vueuse/metadata@11.1.0': {} - '@vueuse/shared@11.1.0(vue@3.5.6)': + '@vueuse/shared@11.1.0(vue@3.5.11)': dependencies: - vue-demi: 0.14.10(vue@3.5.6) + vue-demi: 0.14.10(vue@3.5.11) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -1443,7 +1443,7 @@ snapshots: oniguruma-to-js@0.4.3: dependencies: - regex: 4.3.2 + regex: 4.3.3 parse-node-version@1.0.1: {} @@ -1460,14 +1460,14 @@ snapshots: picocolors: 1.1.0 source-map-js: 1.2.1 - preact@10.24.0: {} + preact@10.24.2: {} property-information@6.5.0: {} prr@1.0.1: optional: true - regex@4.3.2: {} + regex@4.3.3: {} rfdc@1.4.1: {} @@ -1504,13 +1504,13 @@ snapshots: semver@5.7.2: optional: true - shiki@1.17.7: + shiki@1.21.1: dependencies: - '@shikijs/core': 1.17.7 - '@shikijs/engine-javascript': 1.17.7 - '@shikijs/engine-oniguruma': 1.17.7 - '@shikijs/types': 1.17.7 - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/core': 1.21.1 + '@shikijs/engine-javascript': 1.21.1 + '@shikijs/engine-oniguruma': 1.21.1 + '@shikijs/types': 1.21.1 + '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 source-map-js@1.2.1: {} @@ -1574,34 +1574,34 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite@5.4.6(@types/node@20.16.5)(less@4.2.0): + vite@5.4.8(@types/node@22.7.4)(less@4.2.0): dependencies: esbuild: 0.21.5 postcss: 8.4.47 rollup: 4.24.0 optionalDependencies: - '@types/node': 20.16.5 + '@types/node': 22.7.4 fsevents: 2.3.3 less: 4.2.0 - vitepress@1.3.4(@algolia/client-search@4.24.0)(@types/node@20.16.5)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0): + vitepress@1.3.4(@algolia/client-search@4.24.0)(@types/node@22.7.4)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0): dependencies: - '@docsearch/css': 3.6.1 - '@docsearch/js': 3.6.1(@algolia/client-search@4.24.0)(search-insights@2.13.0) - '@shikijs/core': 1.17.7 - '@shikijs/transformers': 1.17.7 + '@docsearch/css': 3.6.2 + '@docsearch/js': 3.6.2(@algolia/client-search@4.24.0)(search-insights@2.13.0) + '@shikijs/core': 1.21.1 + '@shikijs/transformers': 1.21.1 '@types/markdown-it': 14.1.2 - '@vitejs/plugin-vue': 5.1.3(vite@5.4.6(@types/node@20.16.5)(less@4.2.0))(vue@3.5.6) - '@vue/devtools-api': 7.4.5 - '@vue/shared': 3.5.6 - '@vueuse/core': 11.1.0(vue@3.5.6) - '@vueuse/integrations': 11.1.0(focus-trap@7.6.0)(vue@3.5.6) + '@vitejs/plugin-vue': 5.1.4(vite@5.4.8(@types/node@22.7.4)(less@4.2.0))(vue@3.5.11) + '@vue/devtools-api': 7.4.6 + '@vue/shared': 3.5.11 + '@vueuse/core': 11.1.0(vue@3.5.11) + '@vueuse/integrations': 11.1.0(focus-trap@7.6.0)(vue@3.5.11) focus-trap: 7.6.0 mark.js: 8.11.1 minisearch: 7.1.0 - shiki: 1.17.7 - vite: 5.4.6(@types/node@20.16.5)(less@4.2.0) - vue: 3.5.6 + shiki: 1.21.1 + vite: 5.4.8(@types/node@22.7.4)(less@4.2.0) + vue: 3.5.11 optionalDependencies: postcss: 8.4.47 transitivePeerDependencies: @@ -1632,16 +1632,16 @@ snapshots: - typescript - universal-cookie - vue-demi@0.14.10(vue@3.5.6): + vue-demi@0.14.10(vue@3.5.11): dependencies: - vue: 3.5.6 + vue: 3.5.11 - vue@3.5.6: + vue@3.5.11: dependencies: - '@vue/compiler-dom': 3.5.6 - '@vue/compiler-sfc': 3.5.6 - '@vue/runtime-dom': 3.5.6 - '@vue/server-renderer': 3.5.6(vue@3.5.6) - '@vue/shared': 3.5.6 + '@vue/compiler-dom': 3.5.11 + '@vue/compiler-sfc': 3.5.11 + '@vue/runtime-dom': 3.5.11 + '@vue/server-renderer': 3.5.11(vue@3.5.11) + '@vue/shared': 3.5.11 zwitch@2.0.4: {} diff --git a/go.mod b/go.mod index 814bbcc8..321b95b1 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/0xJacky/Nginx-UI -go 1.23.0 +go 1.23.2 require ( github.com/0xJacky/pofile v0.2.1 @@ -8,12 +8,12 @@ require ( github.com/caarlos0/env/v11 v11.2.2 github.com/casdoor/casdoor-go-sdk v0.52.0 github.com/creack/pty v1.1.23 - github.com/dgraph-io/ristretto v0.2.0 + github.com/dgraph-io/ristretto v1.0.0 github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.17.0 github.com/gin-contrib/static v1.1.2 github.com/gin-gonic/gin v1.10.0 - github.com/go-acme/lego/v4 v4.19.1 + github.com/go-acme/lego/v4 v4.19.2 github.com/go-co-op/gocron v1.37.0 github.com/go-playground/validator/v10 v10.22.1 github.com/go-webauthn/webauthn v0.11.2 @@ -269,7 +269,4 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) -replace ( - github.com/tufanbarisyildirim/gonginx v0.0.0-20240109151651-bb3e845a7a2a => github.com/0xJacky/gonginx v0.0.0-20240119024214-c0d76957d0c7 - gopkg.in/ns1/ns1-go.v2 v2.7.8 => gopkg.in/ns1/ns1-go.v2 v2.7.6 -) +replace github.com/tufanbarisyildirim/gonginx v0.0.0-20240109151651-bb3e845a7a2a => github.com/0xJacky/gonginx v0.0.0-20240119024214-c0d76957d0c7 diff --git a/go.sum b/go.sum index 61e4448a..06e29da3 100644 --- a/go.sum +++ b/go.sum @@ -39,6 +39,7 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -178,6 +179,7 @@ cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvj cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.28.1 h1:XwPcZjgMCnU2tkwY10VleUjSAfpTj9RDn+kGrbYsi8o= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= @@ -751,6 +753,7 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -802,6 +805,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE= github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU= +github.com/dgraph-io/ristretto v1.0.0 h1:SYG07bONKMlFDUYu5pEu3DGAh8c2OFNzKm6G9J4Si84= +github.com/dgraph-io/ristretto v1.0.0/go.mod h1:jTi2FiYEhQ1NsMmA7DeBykizjOuY88NhKBkepyu1jPc= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= @@ -863,8 +868,8 @@ github.com/gin-contrib/static v1.1.2 h1:c3kT4bFkUJn2aoRU3s6XnMjJT8J6nNWJkR0Nglqm github.com/gin-contrib/static v1.1.2/go.mod h1:Fw90ozjHCmZBWbgrsqrDvO28YbhKEKzKp8GixhR4yLw= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= -github.com/go-acme/lego/v4 v4.19.1 h1:2Tuu5zBzFeLo3s3k45aGKqAzNvlHHg5WSDPjRQhRfEc= -github.com/go-acme/lego/v4 v4.19.1/go.mod h1:wtDe3dDkmV4/oI2nydpNXSJpvV10J9RCyZ6MbYxNtlQ= +github.com/go-acme/lego/v4 v4.19.2 h1:Y8hrmMvWETdqzzkRly7m98xtPJJivWFsgWi8fcvZo+Y= +github.com/go-acme/lego/v4 v4.19.2/go.mod h1:wtDe3dDkmV4/oI2nydpNXSJpvV10J9RCyZ6MbYxNtlQ= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= diff --git a/internal/analytic/node.go b/internal/analytic/node.go index 35300830..1376a9e4 100644 --- a/internal/analytic/node.go +++ b/internal/analytic/node.go @@ -1,44 +1,43 @@ package analytic import ( - "crypto/tls" - "encoding/json" - "github.com/0xJacky/Nginx-UI/internal/logger" - "github.com/0xJacky/Nginx-UI/internal/upgrader" - "github.com/0xJacky/Nginx-UI/model" - "github.com/0xJacky/Nginx-UI/settings" - "github.com/shirou/gopsutil/v3/load" - "github.com/shirou/gopsutil/v3/net" - "io" - "net/http" - "net/url" - "sync" - "time" + "encoding/json" + "github.com/0xJacky/Nginx-UI/internal/logger" + "github.com/0xJacky/Nginx-UI/internal/transport" + "github.com/0xJacky/Nginx-UI/internal/upgrader" + "github.com/0xJacky/Nginx-UI/model" + "github.com/shirou/gopsutil/v3/load" + "github.com/shirou/gopsutil/v3/net" + "io" + "net/http" + "net/url" + "sync" + "time" ) type NodeInfo struct { - NodeRuntimeInfo upgrader.RuntimeInfo `json:"node_runtime_info"` - Version string `json:"version"` - CPUNum int `json:"cpu_num"` - MemoryTotal string `json:"memory_total"` - DiskTotal string `json:"disk_total"` + NodeRuntimeInfo upgrader.RuntimeInfo `json:"node_runtime_info"` + Version string `json:"version"` + CPUNum int `json:"cpu_num"` + MemoryTotal string `json:"memory_total"` + DiskTotal string `json:"disk_total"` } type NodeStat struct { - AvgLoad *load.AvgStat `json:"avg_load"` - CPUPercent float64 `json:"cpu_percent"` - MemoryPercent float64 `json:"memory_percent"` - DiskPercent float64 `json:"disk_percent"` - Network net.IOCountersStat `json:"network"` - Status bool `json:"status"` - ResponseAt time.Time `json:"response_at"` + AvgLoad *load.AvgStat `json:"avg_load"` + CPUPercent float64 `json:"cpu_percent"` + MemoryPercent float64 `json:"memory_percent"` + DiskPercent float64 `json:"disk_percent"` + Network net.IOCountersStat `json:"network"` + Status bool `json:"status"` + ResponseAt time.Time `json:"response_at"` } type Node struct { - EnvironmentID int `json:"environment_id,omitempty"` - *model.Environment - NodeStat - NodeInfo + EnvironmentID int `json:"environment_id,omitempty"` + *model.Environment + NodeStat + NodeInfo } var mutex sync.Mutex @@ -48,75 +47,76 @@ type TNodeMap map[int]*Node var NodeMap TNodeMap func init() { - NodeMap = make(TNodeMap) + NodeMap = make(TNodeMap) } func GetNode(env *model.Environment) (n *Node) { - if env == nil { - // this should never happen - logger.Error("env is nil") - return - } - if !env.Enabled { - return &Node{ - Environment: env, - } - } - n, ok := NodeMap[env.ID] - if !ok { - n = &Node{} - } - n.Environment = env - return n + if env == nil { + // this should never happen + logger.Error("env is nil") + return + } + if !env.Enabled { + return &Node{ + Environment: env, + } + } + n, ok := NodeMap[env.ID] + if !ok { + n = &Node{} + } + n.Environment = env + return n } func InitNode(env *model.Environment) (n *Node) { - n = &Node{ - Environment: env, - } - - u, err := url.JoinPath(env.URL, "/api/node") - - if err != nil { - logger.Error(err) - return - } - - client := http.Client{ - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify}, - }, - } - - req, err := http.NewRequest("GET", u, nil) - if err != nil { - logger.Error(err) - return - } - - req.Header.Set("X-Node-Secret", env.Token) - - resp, err := client.Do(req) - - if err != nil { - logger.Error(err) - return - } - - defer resp.Body.Close() - bytes, _ := io.ReadAll(resp.Body) - - if resp.StatusCode != http.StatusOK { - logger.Error(string(bytes)) - return - } - - err = json.Unmarshal(bytes, &n.NodeInfo) - if err != nil { - logger.Error(err) - return - } - - return + n = &Node{ + Environment: env, + } + + u, err := url.JoinPath(env.URL, "/api/node") + + if err != nil { + logger.Error(err) + return + } + + t, err := transport.NewTransport() + if err != nil { + return + } + client := http.Client{ + Transport: t, + } + + req, err := http.NewRequest("GET", u, nil) + if err != nil { + logger.Error(err) + return + } + + req.Header.Set("X-Node-Secret", env.Token) + + resp, err := client.Do(req) + + if err != nil { + logger.Error(err) + return + } + + defer resp.Body.Close() + bytes, _ := io.ReadAll(resp.Body) + + if resp.StatusCode != http.StatusOK { + logger.Error(string(bytes)) + return + } + + err = json.Unmarshal(bytes, &n.NodeInfo) + if err != nil { + logger.Error(err) + return + } + + return } diff --git a/internal/cache/cache.go b/internal/cache/cache.go index 7c550cc4..597cfe7d 100644 --- a/internal/cache/cache.go +++ b/internal/cache/cache.go @@ -6,11 +6,11 @@ import ( "time" ) -var cache *ristretto.Cache +var cache *ristretto.Cache[string, any] func Init() { var err error - cache, err = ristretto.NewCache(&ristretto.Config{ + cache, err = ristretto.NewCache[string, any](&ristretto.Config[string, any]{ NumCounters: 1e7, // number of keys to track frequency of (10M). MaxCost: 1 << 30, // maximum cost of cache (1GB). BufferItems: 64, // number of keys per Get buffer. @@ -21,15 +21,15 @@ func Init() { } } -func Set(key interface{}, value interface{}, ttl time.Duration) { +func Set(key string, value interface{}, ttl time.Duration) { cache.SetWithTTL(key, value, 0, ttl) cache.Wait() } -func Get(key interface{}) (value interface{}, ok bool) { +func Get(key string) (value interface{}, ok bool) { return cache.Get(key) } -func Del(key interface{}) { +func Del(key string) { cache.Del(key) } diff --git a/internal/cert/cert.go b/internal/cert/cert.go index 999c95b5..83d63e00 100644 --- a/internal/cert/cert.go +++ b/internal/cert/cert.go @@ -1,10 +1,10 @@ package cert import ( - "crypto/tls" "github.com/0xJacky/Nginx-UI/internal/cert/dns" "github.com/0xJacky/Nginx-UI/internal/logger" "github.com/0xJacky/Nginx-UI/internal/nginx" + "github.com/0xJacky/Nginx-UI/internal/transport" "github.com/0xJacky/Nginx-UI/query" "github.com/0xJacky/Nginx-UI/settings" "github.com/go-acme/lego/v4/challenge/dns01" @@ -14,7 +14,6 @@ import ( dnsproviders "github.com/go-acme/lego/v4/providers/dns" "github.com/pkg/errors" "log" - "net/http" "os" "time" ) @@ -63,10 +62,11 @@ func IssueCert(payload *ConfigPayload, logChan chan string, errChan chan error) // Skip TLS check if config.HTTPClient != nil { - config.HTTPClient.Transport = &http.Transport{ - Proxy: http.ProxyFromEnvironment, - TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify}, + t, err := transport.NewTransport() + if err != nil { + return } + config.HTTPClient.Transport = t } config.Certificate.KeyType = payload.GetKeyType() diff --git a/internal/cert/sync.go b/internal/cert/sync.go index 58c6cce2..9991e69a 100644 --- a/internal/cert/sync.go +++ b/internal/cert/sync.go @@ -2,16 +2,15 @@ package cert import ( "bytes" - "crypto/tls" "encoding/json" "fmt" "github.com/0xJacky/Nginx-UI/internal/helper" "github.com/0xJacky/Nginx-UI/internal/logger" "github.com/0xJacky/Nginx-UI/internal/nginx" "github.com/0xJacky/Nginx-UI/internal/notification" + "github.com/0xJacky/Nginx-UI/internal/transport" "github.com/0xJacky/Nginx-UI/model" "github.com/0xJacky/Nginx-UI/query" - "github.com/0xJacky/Nginx-UI/settings" "github.com/go-acme/lego/v4/certcrypto" "io" "net/http" @@ -88,11 +87,12 @@ type SyncNotificationPayload struct { } func deploy(env *model.Environment, c *model.Cert, payloadBytes []byte) (err error) { + t, err := transport.NewTransport() + if err != nil { + return + } client := http.Client{ - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify}, - }, + Transport: t, } url, err := env.GetUrl("/api/cert_sync") if err != nil { diff --git a/internal/config/sync.go b/internal/config/sync.go index 5b46bacd..76080815 100644 --- a/internal/config/sync.go +++ b/internal/config/sync.go @@ -9,6 +9,7 @@ import ( "github.com/0xJacky/Nginx-UI/internal/logger" "github.com/0xJacky/Nginx-UI/internal/nginx" "github.com/0xJacky/Nginx-UI/internal/notification" + "github.com/0xJacky/Nginx-UI/internal/transport" "github.com/0xJacky/Nginx-UI/model" "github.com/0xJacky/Nginx-UI/query" "github.com/0xJacky/Nginx-UI/settings" @@ -122,11 +123,12 @@ type SyncNotificationPayload struct { } func (p *SyncConfigPayload) deploy(env *model.Environment, c *model.Config, payloadBytes []byte) (err error) { + t, err := transport.NewTransport() + if err != nil { + return + } client := http.Client{ - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify}, - }, + Transport: t, } url, err := env.GetUrl("/api/config") if err != nil { diff --git a/internal/middleware/proxy.go b/internal/middleware/proxy.go index 30eb281a..ef9914a6 100644 --- a/internal/middleware/proxy.go +++ b/internal/middleware/proxy.go @@ -1,10 +1,9 @@ package middleware import ( - "crypto/tls" "github.com/0xJacky/Nginx-UI/internal/logger" + "github.com/0xJacky/Nginx-UI/internal/transport" "github.com/0xJacky/Nginx-UI/query" - "github.com/0xJacky/Nginx-UI/settings" "github.com/gin-gonic/gin" "github.com/spf13/cast" "io" @@ -57,11 +56,18 @@ func Proxy() gin.HandlerFunc { } logger.Debug("Proxy request", proxyUrl.String()) + + t, err := transport.NewTransport() + if err != nil { + logger.Error(err) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ + "message": err.Error(), + }) + return + } + client := http.Client{ - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify}, - }, + Transport: t, } req, err := http.NewRequest(c.Request.Method, proxyUrl.String(), c.Request.Body) diff --git a/internal/transport/transport.go b/internal/transport/transport.go new file mode 100644 index 00000000..cb499b32 --- /dev/null +++ b/internal/transport/transport.go @@ -0,0 +1,44 @@ +package transport + +import ( + "crypto/tls" + "github.com/0xJacky/Nginx-UI/settings" + "net/http" + "net/url" +) + +// NewTransport creates a new http.Transport with the provided options. +func NewTransport(options ...func(transport *http.Transport) error) (t *http.Transport, err error) { + t = &http.Transport{ + Proxy: http.ProxyFromEnvironment, + TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify}, + } + + for _, option := range options { + if err := option(t); err != nil { + return nil, err + } + } + + return +} + +// WithProxy returns a function that sets the proxy of the http.Transport to the provided proxy URL. +func WithProxy(proxyUrl string) func(transport *http.Transport) error { + if proxyUrl == "" { + return func(transport *http.Transport) error { + return nil + } + } + proxy, err := url.Parse(proxyUrl) + if err != nil { + return func(transport *http.Transport) error { + return err + } + } + + return func(transport *http.Transport) error { + transport.Proxy = http.ProxyURL(proxy) + return nil + } +} diff --git a/internal/transport/transport_test.go b/internal/transport/transport_test.go new file mode 100644 index 00000000..b138c547 --- /dev/null +++ b/internal/transport/transport_test.go @@ -0,0 +1,42 @@ +package transport + +import ( + "net/http" + "net/url" + "testing" + + "github.com/0xJacky/Nginx-UI/settings" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCreatesTransportWithDefaultSettings(t *testing.T) { + transport, err := NewTransport() + require.NoError(t, err) + assert.NotNil(t, transport) + assert.ObjectsAreEqual(http.ProxyFromEnvironment, transport.Proxy) + assert.Equal(t, settings.ServerSettings.InsecureSkipVerify, transport.TLSClientConfig.InsecureSkipVerify) +} + +func TestCreatesTransportWithCustomProxy(t *testing.T) { + proxyUrl := "https://proxy.example.com" + transport, err := NewTransport(WithProxy(proxyUrl)) + require.NoError(t, err) + assert.NotNil(t, transport) + parsedProxy, _ := url.Parse(proxyUrl) + assert.ObjectsAreEqual(http.ProxyURL(parsedProxy), transport.Proxy) +} + +func TestCreatesTransportWithInvalidProxyUrl(t *testing.T) { + invalidProxyUrl := "https://[::1]:namedport" + transport, err := NewTransport(WithProxy(invalidProxyUrl)) + assert.Error(t, err) + assert.Nil(t, transport) +} + +func TestCreatesTransportWithEmptyProxyUrl(t *testing.T) { + transport, err := NewTransport(WithProxy("")) + require.NoError(t, err) + assert.NotNil(t, transport) + assert.ObjectsAreEqual(http.ProxyFromEnvironment, transport.Proxy) +} diff --git a/model/acme_user.go b/model/acme_user.go index 3a2d85d3..83e09fa5 100644 --- a/model/acme_user.go +++ b/model/acme_user.go @@ -5,12 +5,10 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" - "crypto/tls" - "github.com/0xJacky/Nginx-UI/settings" + "github.com/0xJacky/Nginx-UI/internal/transport" "github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/registration" "math/big" - "net/http" ) type PrivateKey struct { @@ -63,10 +61,11 @@ func (u *AcmeUser) Register() error { // Skip TLS check if config.HTTPClient != nil { - config.HTTPClient.Transport = &http.Transport{ - Proxy: http.ProxyFromEnvironment, - TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify}, + t, err := transport.NewTransport() + if err != nil { + return err } + config.HTTPClient.Transport = t } client, err := lego.NewClient(config)