mirror of
https://github.com/yusing/godoxy.git
synced 2025-05-20 20:52:33 +02:00
Compare commits
No commits in common. "main" and "v0.13.0" have entirely different histories.
49 changed files with 546 additions and 1054 deletions
|
@ -2,16 +2,8 @@ name: Docker Image CI (socket-proxy)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
paths:
|
||||||
- "socket-proxy/**"
|
- "socket-proxy/**"
|
||||||
tags-ignore:
|
|
||||||
- '**'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
4
.github/workflows/docker-image.yml
vendored
4
.github/workflows/docker-image.yml
vendored
|
@ -84,10 +84,10 @@ jobs:
|
||||||
outputs: type=image,name=${{ env.REGISTRY }}/${{ inputs.image_name }},push-by-digest=true,name-canonical=true,push=true
|
outputs: type=image,name=${{ env.REGISTRY }}/${{ inputs.image_name }},push-by-digest=true,name-canonical=true,push=true
|
||||||
cache-from: |
|
cache-from: |
|
||||||
type=registry,ref=${{ env.REGISTRY }}/${{ inputs.image_name }}:buildcache-${{ env.PLATFORM_PAIR }}
|
type=registry,ref=${{ env.REGISTRY }}/${{ inputs.image_name }}:buildcache-${{ env.PLATFORM_PAIR }}
|
||||||
type=gha,scope=${{ github.workflow }}-${{ env.PLATFORM_PAIR }}
|
type=gha,scope=${{ github.workflow }}
|
||||||
cache-to: |
|
cache-to: |
|
||||||
type=registry,ref=${{ env.REGISTRY }}/${{ inputs.image_name }}:buildcache-${{ env.PLATFORM_PAIR }},mode=max
|
type=registry,ref=${{ env.REGISTRY }}/${{ inputs.image_name }}:buildcache-${{ env.PLATFORM_PAIR }},mode=max
|
||||||
type=gha,scope=${{ github.workflow }}-${{ env.PLATFORM_PAIR }},mode=max
|
type=gha,scope=${{ github.workflow }},mode=max
|
||||||
build-args: |
|
build-args: |
|
||||||
VERSION=${{ github.ref_name }}
|
VERSION=${{ github.ref_name }}
|
||||||
MAKE_ARGS=${{ env.MAKE_ARGS }}
|
MAKE_ARGS=${{ env.MAKE_ARGS }}
|
||||||
|
|
|
@ -17,7 +17,6 @@ linters:
|
||||||
- gocognit
|
- gocognit
|
||||||
- goconst
|
- goconst
|
||||||
- gocyclo
|
- gocyclo
|
||||||
- gomoddirectives
|
|
||||||
- gosec
|
- gosec
|
||||||
- gosmopolitan
|
- gosmopolitan
|
||||||
- ireturn
|
- ireturn
|
||||||
|
|
22
README.md
22
README.md
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
# GoDoxy
|
# GoDoxy
|
||||||
|
|
||||||
[](https://sonarcloud.io/summary/new_code?id=yusing_go-proxy)
|
[](https://sonarcloud.io/summary/new_code?id=yusing_godoxy)
|
||||||

|

|
||||||
[](https://sonarcloud.io/summary/new_code?id=go-proxy)
|
[](https://sonarcloud.io/summary/new_code?id=yusing_godoxy)
|
||||||

|

|
||||||
[](https://discord.gg/umReR62nRd)
|
[](https://discord.gg/umReR62nRd)
|
||||||
|
|
||||||
A lightweight, simple, and performant reverse proxy with WebUI.
|
A lightweight, simple, and [performant](https://github.com/yusing/godoxy/wiki/Benchmarks) reverse proxy with WebUI.
|
||||||
|
|
||||||
<h5>
|
<h5>
|
||||||
<a href="https://docs.godoxy.dev">Website</a> | <a href="https://docs.godoxy.dev/Home.html">Wiki</a> | <a href="https://discord.gg/umReR62nRd">Discord</a>
|
<a href="https://docs.godoxy.dev">Website</a> | <a href="https://docs.godoxy.dev/Home.html">Wiki</a> | <a href="https://discord.gg/umReR62nRd">Discord</a>
|
||||||
|
@ -47,8 +47,8 @@ A lightweight, simple, and performant reverse proxy with WebUI.
|
||||||
## Key Features
|
## Key Features
|
||||||
|
|
||||||
- **Simple**
|
- **Simple**
|
||||||
- Effortless configuration with [simple labels](https://docs.godoxy.dev/Docker-labels-and-Route-Files) or WebUI
|
- Effortless configuration with [simple labels](https://github.com/yusing/godoxy/wiki/Docker-labels-and-Route-Files) or WebUI
|
||||||
- [Simple multi-node setup](https://docs.godoxy.dev/Configurations#multi-docker-nodes-setup)
|
- [Simple multi-node setup](https://github.com/yusing/godoxy/wiki/Configurations#multi-docker-nodes-setup)
|
||||||
- Detailed error messages for easy troubleshooting.
|
- Detailed error messages for easy troubleshooting.
|
||||||
- **ACL**: connection / request level access control
|
- **ACL**: connection / request level access control
|
||||||
- IP/CIDR
|
- IP/CIDR
|
||||||
|
@ -56,7 +56,7 @@ A lightweight, simple, and performant reverse proxy with WebUI.
|
||||||
- Timezone **(Maxmind account required)**
|
- Timezone **(Maxmind account required)**
|
||||||
- **Access logging**
|
- **Access logging**
|
||||||
- **Advanced Automation**
|
- **Advanced Automation**
|
||||||
- Automatic SSL certificate management with Let's Encrypt ([using DNS-01 Challenge](https://docs.godoxy.dev/DNS-01-Providers))
|
- Automatic SSL certificate management with Let's Encrypt ([using DNS-01 Challenge](https://github.com/yusing/go-proxy/wiki/Supported-DNS%E2%80%9001-Providers))
|
||||||
- Auto-configuration for Docker containers
|
- Auto-configuration for Docker containers
|
||||||
- Hot-reloading of configurations and container state changes
|
- Hot-reloading of configurations and container state changes
|
||||||
- **Idle-sleep**: stop and wake containers based on traffic _(see [screenshots](#idlesleeper))_
|
- **Idle-sleep**: stop and wake containers based on traffic _(see [screenshots](#idlesleeper))_
|
||||||
|
@ -67,8 +67,8 @@ A lightweight, simple, and performant reverse proxy with WebUI.
|
||||||
- TCP/UDP port forwarding
|
- TCP/UDP port forwarding
|
||||||
- **OpenID Connect support**: SSO and secure your apps easily
|
- **OpenID Connect support**: SSO and secure your apps easily
|
||||||
- **Customization**
|
- **Customization**
|
||||||
- [HTTP middlewares](https://docs.godoxy.dev/Middlewares)
|
- [HTTP middlewares](https://github.com/yusing/go-proxy/wiki/Middlewares)
|
||||||
- [Custom error pages support](https://docs.godoxy.dev/Custom-Error-Pages)
|
- [Custom error pages support](https://github.com/yusing/go-proxy/wiki/Middlewares#custom-error-pages)
|
||||||
- **Web UI**
|
- **Web UI**
|
||||||
- App Dashboard
|
- App Dashboard
|
||||||
- Config Editor
|
- Config Editor
|
||||||
|
@ -103,9 +103,9 @@ Configure Wildcard DNS Record(s) to point to machine running `GoDoxy`, e.g.
|
||||||
|
|
||||||
3. Start the docker compose service from generated `compose.yml`:
|
3. Start the docker compose service from generated `compose.yml`:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
4. You may now do some extra configuration on WebUI `https://godoxy.yourdomain.com`
|
4. You may now do some extra configuration on WebUI `https://godoxy.yourdomain.com`
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||

|

|
||||||
[](https://discord.gg/umReR62nRd)
|
[](https://discord.gg/umReR62nRd)
|
||||||
|
|
||||||
輕量、易用、 高效能,且帶有主頁和配置面板的反向代理
|
輕量、易用、 [高效能](https://github.com/yusing/godoxy/wiki/Benchmarks),且帶有主頁和配置面板的反向代理
|
||||||
|
|
||||||
<h5>
|
<h5>
|
||||||
<a href="https://docs.godoxy.dev">網站</a> | <a href="https://docs.godoxy.dev/Home.html">文檔</a> | <a href="https://discord.gg/umReR62nRd">Discord</a>
|
<a href="https://docs.godoxy.dev">網站</a> | <a href="https://docs.godoxy.dev/Home.html">文檔</a> | <a href="https://discord.gg/umReR62nRd">Discord</a>
|
||||||
|
@ -45,38 +45,20 @@
|
||||||
|
|
||||||
## 主要特點
|
## 主要特點
|
||||||
|
|
||||||
- **簡單易用**
|
- 容易使用
|
||||||
- 透過 Docker[標籤](https://docs.godoxy.dev/Docker-labels-and-Route-Files)或 WebUI 輕鬆設定
|
- 輕鬆配置
|
||||||
- [簡單的多節點設置](https://docs.godoxy.dev/Configurations#multi-docker-nodes-setup)
|
- 簡單的多節點設置
|
||||||
- 詳細的錯誤訊息,便於故障排除
|
- 錯誤訊息清晰詳細,易於排除故障
|
||||||
- **存取控制 (ACL)**:連線/請求層級存取控制
|
- 自動 SSL 憑證管理(參見 [支援的 DNS-01 驗證提供商](https://github.com/yusing/godoxy/wiki/Supported-DNS%E2%80%9001-Providers))
|
||||||
- IP/CIDR
|
- 自動配置 Docker 容器
|
||||||
- 國家 **(需要 Maxmind 帳戶)**
|
- 容器狀態/配置文件變更時自動熱重載
|
||||||
- 時區 **(需要 Maxmind 帳戶)**
|
- **閒置休眠**:在閒置時停止容器,有流量時喚醒(_可選,參見[截圖](#閒置休眠)_)
|
||||||
- **存取日誌記錄**
|
- OpenID Connect:輕鬆實現單點登入
|
||||||
- **自動化**
|
- HTTP(s) 反向代理和 TCP 和 UDP 埠轉發
|
||||||
- 使用 Let's Encrypt 自動管理 SSL 憑證 ([使用 DNS-01 驗證](https://docs.godoxy.dev/DNS-01-Providers))
|
- [HTTP 中介軟體](https://github.com/yusing/godoxy/wiki/Middlewares) 和 [自定義錯誤頁面](https://github.com/yusing/godoxy/wiki/Middlewares#custom-error-pages)
|
||||||
- Docker 容器自動配置
|
- **網頁介面,具有應用儀表板和配置編輯器**
|
||||||
- 設定檔與容器狀態變更時自動熱重載
|
- 支援 linux/amd64、linux/arm64
|
||||||
- **閒置休眠**:根據流量停止和喚醒容器 _(參見[截圖](#閒置休眠))_
|
- 使用 **[Go](https://go.dev)** 編寫
|
||||||
- Docker 容器
|
|
||||||
- Proxmox LXC 容器
|
|
||||||
- **流量管理**
|
|
||||||
- HTTP 反向代理
|
|
||||||
- TCP/UDP 連接埠轉送
|
|
||||||
- **OpenID Connect 支援**:輕鬆實現單點登入 (SSO) 並保護您的應用程式
|
|
||||||
- **客製化**
|
|
||||||
- [HTTP 中介軟體](https://docs.godoxy.dev/Middlewares)
|
|
||||||
- [支援自訂錯誤頁面](https://docs.godoxy.dev/Custom-Error-Pages)
|
|
||||||
- **網頁使用者介面 (Web UI)**
|
|
||||||
- 應用程式一覽
|
|
||||||
- 設定編輯器
|
|
||||||
- 執行時間與系統指標
|
|
||||||
- Docker 日誌檢視器
|
|
||||||
- **跨平台支援**
|
|
||||||
- 支援 **linux/amd64** 與 **linux/arm64**
|
|
||||||
- **高效能**
|
|
||||||
- 以 **[Go](https://go.dev)** 語言編寫
|
|
||||||
|
|
||||||
[🔼 回到頂部](#目錄)
|
[🔼 回到頂部](#目錄)
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ require (
|
||||||
github.com/docker/docker v28.1.1+incompatible // indirect
|
github.com/docker/docker v28.1.1+incompatible // indirect
|
||||||
github.com/docker/go-connections v0.5.0 // indirect
|
github.com/docker/go-connections v0.5.0 // indirect
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/ebitengine/purego v0.8.3 // indirect
|
github.com/ebitengine/purego v0.8.2 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
||||||
github.com/go-acme/lego/v4 v4.23.1 // indirect
|
github.com/go-acme/lego/v4 v4.23.1 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.1.0 // indirect
|
github.com/go-jose/go-jose/v4 v4.1.0 // indirect
|
||||||
|
@ -64,7 +64,7 @@ require (
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||||
github.com/puzpuzpuz/xsync/v4 v4.1.0 // indirect
|
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
|
||||||
github.com/quic-go/qpack v0.5.1 // indirect
|
github.com/quic-go/qpack v0.5.1 // indirect
|
||||||
github.com/quic-go/quic-go v0.51.0 // indirect
|
github.com/quic-go/quic-go v0.51.0 // indirect
|
||||||
github.com/samber/lo v1.50.0 // indirect
|
github.com/samber/lo v1.50.0 // indirect
|
||||||
|
|
38
agent/go.sum
38
agent/go.sum
|
@ -14,6 +14,8 @@ github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9F
|
||||||
github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
||||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||||
|
github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
|
||||||
|
github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -31,10 +33,12 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj
|
||||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc=
|
github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I=
|
||||||
github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||||
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab h1:h1UgjJdAAhj+uPL68n7XASS6bU+07ZX1WJvVS2eyoeY=
|
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab h1:h1UgjJdAAhj+uPL68n7XASS6bU+07ZX1WJvVS2eyoeY=
|
||||||
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab/go.mod h1:GLo/8fDswSAniFG+BFIaiSPcK610jyzgEhWYPQwuQdw=
|
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab/go.mod h1:GLo/8fDswSAniFG+BFIaiSPcK610jyzgEhWYPQwuQdw=
|
||||||
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
||||||
github.com/go-acme/lego/v4 v4.23.1 h1:lZ5fGtGESA2L9FB8dNTvrQUq3/X4QOb8ExkKyY7LSV4=
|
github.com/go-acme/lego/v4 v4.23.1 h1:lZ5fGtGESA2L9FB8dNTvrQUq3/X4QOb8ExkKyY7LSV4=
|
||||||
|
@ -60,6 +64,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||||
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
||||||
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||||
|
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||||
|
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||||
github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY=
|
github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY=
|
||||||
github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
@ -69,6 +75,8 @@ github.com/godoxy-app/gopsutil/v4 v4.0.0-20250502022742-408a348f1b97 h1:i52gBYam
|
||||||
github.com/godoxy-app/gopsutil/v4 v4.0.0-20250502022742-408a348f1b97/go.mod h1:XvbfPmmrdpLrsKwj3irYkxt5ygyMcDsTQTJ7cnZ9RNQ=
|
github.com/godoxy-app/gopsutil/v4 v4.0.0-20250502022742-408a348f1b97/go.mod h1:XvbfPmmrdpLrsKwj3irYkxt5ygyMcDsTQTJ7cnZ9RNQ=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
@ -82,8 +90,8 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
|
||||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/gotify/server/v2 v2.6.3 h1:2sLDRsQ/No1+hcFwFDvjNtwKepfCSIR8L3BkXl/Vz1I=
|
github.com/gotify/server/v2 v2.6.3 h1:2sLDRsQ/No1+hcFwFDvjNtwKepfCSIR8L3BkXl/Vz1I=
|
||||||
github.com/gotify/server/v2 v2.6.3/go.mod h1:IyeQ/iL3vetcuqUAzkCMVObIMGGJx4zb13/mVatIwE8=
|
github.com/gotify/server/v2 v2.6.3/go.mod h1:IyeQ/iL3vetcuqUAzkCMVObIMGGJx4zb13/mVatIwE8=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
|
||||||
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
|
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
|
||||||
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
|
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||||
|
@ -150,8 +158,8 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||||
github.com/puzpuzpuz/xsync/v4 v4.1.0 h1:x9eHRl4QhZFIPJ17yl4KKW9xLyVWbb3/Yq4SXpjF71U=
|
github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
|
||||||
github.com/puzpuzpuz/xsync/v4 v4.1.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo=
|
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||||
github.com/quic-go/quic-go v0.51.0 h1:K8exxe9zXxeRKxaXxi/GpUqYiTrtdiWP8bo1KFya6Wc=
|
github.com/quic-go/quic-go v0.51.0 h1:K8exxe9zXxeRKxaXxi/GpUqYiTrtdiWP8bo1KFya6Wc=
|
||||||
|
@ -200,8 +208,8 @@ go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H
|
||||||
go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
|
go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||||
go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI=
|
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||||
go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc=
|
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||||
|
@ -241,6 +249,8 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||||
|
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||||
|
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -312,12 +322,12 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU=
|
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f h1:tjZsroqekhC63+WMqzmWyW5Twj/ZfR5HAlpd5YQ1Vs0=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:Cd8IzgPo5Akum2c9R6FsXNaZbH3Jpa2gpHlW89FqlyQ=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 h1:IkAfh6J/yllPtpYFU0zZN1hUPYdT0ogkBT/9hMxHjvg=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 h1:IqsN8hx+lWLqlN+Sc3DoMy/watjofWiU8sRFgQ8fhKM=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
|
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
||||||
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|
|
@ -10,7 +10,7 @@ var (
|
||||||
AGENT_PORT="{{.Port}}" \
|
AGENT_PORT="{{.Port}}" \
|
||||||
AGENT_CA_CERT="{{.CACert}}" \
|
AGENT_CA_CERT="{{.CACert}}" \
|
||||||
AGENT_SSL_CERT="{{.SSLCert}}" \
|
AGENT_SSL_CERT="{{.SSLCert}}" \
|
||||||
bash -c "$(curl -fsSL https://raw.githubusercontent.com/yusing/godoxy/main/scripts/install-agent.sh)"`
|
bash -c "$(curl -fsSL https://raw.githubusercontent.com/yusing/go-proxy/main/scripts/install-agent.sh)"`
|
||||||
installScriptTemplate = template.Must(template.New("install.sh").Parse(installScript))
|
installScriptTemplate = template.Must(template.New("install.sh").Parse(installScript))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package agent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
|
@ -11,37 +12,20 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"fmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CertsDNSName = "godoxy.agent"
|
CertsDNSName = "godoxy.agent"
|
||||||
|
KeySize = 2048
|
||||||
)
|
)
|
||||||
|
|
||||||
func toPEMPair(certDER []byte, key *ecdsa.PrivateKey) *PEMPair {
|
func toPEMPair(certDER []byte, key *rsa.PrivateKey) *PEMPair {
|
||||||
marshaledKey, err := marshalECPrivateKey(key)
|
|
||||||
if err != nil {
|
|
||||||
// This is a critical internal error during PEM encoding of a newly generated key.
|
|
||||||
// Panicking is acceptable here as it indicates a fundamental issue.
|
|
||||||
panic(fmt.Sprintf("failed to marshal EC private key for PEM encoding: %v", err))
|
|
||||||
}
|
|
||||||
return &PEMPair{
|
return &PEMPair{
|
||||||
Cert: pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}),
|
Cert: pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}),
|
||||||
Key: pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: marshaledKey}),
|
Key: pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
|
|
||||||
derBytes, err := x509.MarshalECPrivateKey(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to marshal EC private key: %w", err)
|
|
||||||
}
|
|
||||||
return derBytes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func b64Encode(data []byte) string {
|
func b64Encode(data []byte) string {
|
||||||
return base64.StdEncoding.EncodeToString(data)
|
return base64.StdEncoding.EncodeToString(data)
|
||||||
}
|
}
|
||||||
|
@ -79,23 +63,10 @@ func (p *PEMPair) ToTLSCert() (*tls.Certificate, error) {
|
||||||
return &cert, err
|
return &cert, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSerialNumber() (*big.Int, error) {
|
|
||||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) // 128-bit random number
|
|
||||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to generate serial number: %w", err)
|
|
||||||
}
|
|
||||||
return serialNumber, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewAgent() (ca, srv, client *PEMPair, err error) {
|
func NewAgent() (ca, srv, client *PEMPair, err error) {
|
||||||
caSerialNumber, err := newSerialNumber()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
// Create the CA's certificate
|
// Create the CA's certificate
|
||||||
caTemplate := &x509.Certificate{
|
caTemplate := &x509.Certificate{
|
||||||
SerialNumber: caSerialNumber,
|
SerialNumber: big.NewInt(1),
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
Organization: []string{"GoDoxy"},
|
Organization: []string{"GoDoxy"},
|
||||||
CommonName: CertsDNSName,
|
CommonName: CertsDNSName,
|
||||||
|
@ -105,12 +76,9 @@ func NewAgent() (ca, srv, client *PEMPair, err error) {
|
||||||
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
|
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
|
||||||
BasicConstraintsValid: true,
|
BasicConstraintsValid: true,
|
||||||
IsCA: true,
|
IsCA: true,
|
||||||
MaxPathLen: 0,
|
|
||||||
MaxPathLenZero: true,
|
|
||||||
SignatureAlgorithm: x509.ECDSAWithSHA256,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
caKey, err := rsa.GenerateKey(rand.Reader, KeySize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -123,29 +91,20 @@ func NewAgent() (ca, srv, client *PEMPair, err error) {
|
||||||
ca = toPEMPair(caDER, caKey)
|
ca = toPEMPair(caDER, caKey)
|
||||||
|
|
||||||
// Generate a new private key for the server certificate
|
// Generate a new private key for the server certificate
|
||||||
serverKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
serverKey, err := rsa.GenerateKey(rand.Reader, KeySize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
serverSerialNumber, err := newSerialNumber()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
srvTemplate := &x509.Certificate{
|
srvTemplate := &x509.Certificate{
|
||||||
SerialNumber: serverSerialNumber,
|
SerialNumber: big.NewInt(2),
|
||||||
Issuer: caTemplate.Subject,
|
Issuer: caTemplate.Subject,
|
||||||
Subject: pkix.Name{
|
Subject: caTemplate.Subject,
|
||||||
Organization: caTemplate.Subject.Organization,
|
DNSNames: []string{CertsDNSName},
|
||||||
OrganizationalUnit: []string{"Server"},
|
NotBefore: time.Now(),
|
||||||
CommonName: CertsDNSName,
|
NotAfter: time.Now().AddDate(1000, 0, 0), // Add validity period
|
||||||
},
|
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||||
DNSNames: []string{CertsDNSName},
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||||
NotBefore: time.Now(),
|
|
||||||
NotAfter: time.Now().AddDate(1000, 0, 0), // Add validity period
|
|
||||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
|
||||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
|
||||||
SignatureAlgorithm: x509.ECDSAWithSHA256,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
srvCertDER, err := x509.CreateCertificate(rand.Reader, srvTemplate, caTemplate, &serverKey.PublicKey, caKey)
|
srvCertDER, err := x509.CreateCertificate(rand.Reader, srvTemplate, caTemplate, &serverKey.PublicKey, caKey)
|
||||||
|
@ -155,29 +114,20 @@ func NewAgent() (ca, srv, client *PEMPair, err error) {
|
||||||
|
|
||||||
srv = toPEMPair(srvCertDER, serverKey)
|
srv = toPEMPair(srvCertDER, serverKey)
|
||||||
|
|
||||||
clientKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
clientKey, err := rsa.GenerateKey(rand.Reader, KeySize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
clientSerialNumber, err := newSerialNumber()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
clientTemplate := &x509.Certificate{
|
clientTemplate := &x509.Certificate{
|
||||||
SerialNumber: clientSerialNumber,
|
SerialNumber: big.NewInt(3),
|
||||||
Issuer: caTemplate.Subject,
|
Issuer: caTemplate.Subject,
|
||||||
Subject: pkix.Name{
|
Subject: caTemplate.Subject,
|
||||||
Organization: caTemplate.Subject.Organization,
|
DNSNames: []string{CertsDNSName},
|
||||||
OrganizationalUnit: []string{"Client"},
|
NotBefore: time.Now(),
|
||||||
CommonName: CertsDNSName,
|
NotAfter: time.Now().AddDate(1000, 0, 0),
|
||||||
},
|
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||||
DNSNames: []string{CertsDNSName},
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||||
NotBefore: time.Now(),
|
|
||||||
NotAfter: time.Now().AddDate(1000, 0, 0),
|
|
||||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
|
||||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
|
||||||
SignatureAlgorithm: x509.ECDSAWithSHA256,
|
|
||||||
}
|
}
|
||||||
clientCertDER, err := x509.CreateCertificate(rand.Reader, clientTemplate, caTemplate, &clientKey.PublicKey, caKey)
|
clientCertDER, err := x509.CreateCertificate(rand.Reader, clientTemplate, caTemplate, &clientKey.PublicKey, caKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
30
go.mod
30
go.mod
|
@ -23,7 +23,7 @@ require (
|
||||||
github.com/gobwas/glob v0.2.3 // glob matcher for route rules
|
github.com/gobwas/glob v0.2.3 // glob matcher for route rules
|
||||||
github.com/gotify/server/v2 v2.6.3 // reference the Message struct for json response
|
github.com/gotify/server/v2 v2.6.3 // reference the Message struct for json response
|
||||||
github.com/lithammer/fuzzysearch v1.1.8 // fuzzy search for searching icons and filtering metrics
|
github.com/lithammer/fuzzysearch v1.1.8 // fuzzy search for searching icons and filtering metrics
|
||||||
github.com/puzpuzpuz/xsync/v4 v4.1.0 // lock free map for concurrent operations
|
github.com/puzpuzpuz/xsync/v3 v3.5.1 // lock free map for concurrent operations
|
||||||
github.com/rs/zerolog v1.34.0 // logging
|
github.com/rs/zerolog v1.34.0 // logging
|
||||||
github.com/shirou/gopsutil/v4 v4.25.4 // system info metrics
|
github.com/shirou/gopsutil/v4 v4.25.4 // system info metrics
|
||||||
github.com/vincent-petithory/dataurl v1.0.0 // data url for fav icon
|
github.com/vincent-petithory/dataurl v1.0.0 // data url for fav icon
|
||||||
|
@ -51,10 +51,10 @@ require (
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/auth v0.16.1 // indirect
|
cloud.google.com/go/auth v0.16.1 // indirect
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.7.0 // indirect
|
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||||
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
|
||||||
|
@ -80,12 +80,12 @@ require (
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect
|
||||||
github.com/aws/smithy-go v1.22.3 // indirect
|
github.com/aws/smithy-go v1.22.3 // indirect
|
||||||
github.com/baidubce/bce-sdk-go v0.9.226 // indirect
|
github.com/baidubce/bce-sdk-go v0.9.225 // indirect
|
||||||
github.com/benbjohnson/clock v1.3.5 // indirect
|
github.com/benbjohnson/clock v1.3.5 // indirect
|
||||||
github.com/boombuler/barcode v1.0.2 // indirect
|
github.com/boombuler/barcode v1.0.2 // indirect
|
||||||
github.com/buger/goterm v1.0.4 // indirect
|
github.com/buger/goterm v1.0.4 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/civo/civogo v0.5.0 // indirect
|
github.com/civo/civogo v0.4.1 // indirect
|
||||||
github.com/cloudflare/cloudflare-go v0.115.0 // indirect
|
github.com/cloudflare/cloudflare-go v0.115.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/diskfs/go-diskfs v1.6.0 // indirect
|
github.com/diskfs/go-diskfs v1.6.0 // indirect
|
||||||
|
@ -94,7 +94,7 @@ require (
|
||||||
github.com/dnsimple/dnsimple-go v1.7.0 // indirect
|
github.com/dnsimple/dnsimple-go v1.7.0 // indirect
|
||||||
github.com/docker/go-connections v0.5.0
|
github.com/docker/go-connections v0.5.0
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/ebitengine/purego v0.8.3 // indirect
|
github.com/ebitengine/purego v0.8.2 // indirect
|
||||||
github.com/exoscale/egoscale/v3 v3.1.17 // indirect
|
github.com/exoscale/egoscale/v3 v3.1.17 // indirect
|
||||||
github.com/fatih/structs v1.1.0 // indirect
|
github.com/fatih/structs v1.1.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
|
@ -118,14 +118,15 @@ require (
|
||||||
github.com/google/s2a-go v0.1.9 // indirect
|
github.com/google/s2a-go v0.1.9 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
|
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
|
||||||
github.com/gophercloud/gophercloud v1.14.1 // indirect
|
github.com/gophercloud/gophercloud v1.14.1 // indirect
|
||||||
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
|
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
|
||||||
github.com/gorilla/websocket v1.5.3 // indirect
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.149 // indirect
|
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148 // indirect
|
||||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
||||||
github.com/infobloxopen/infoblox-go-client/v2 v2.10.0 // indirect
|
github.com/infobloxopen/infoblox-go-client/v2 v2.10.0 // indirect
|
||||||
github.com/jinzhu/copier v0.4.0 // indirect
|
github.com/jinzhu/copier v0.4.0 // indirect
|
||||||
|
@ -167,7 +168,7 @@ require (
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
||||||
github.com/oracle/oci-go-sdk/v65 v65.91.0 // indirect
|
github.com/oracle/oci-go-sdk/v65 v65.90.0 // indirect
|
||||||
github.com/ovh/go-ovh v1.7.0 // indirect
|
github.com/ovh/go-ovh v1.7.0 // indirect
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
|
@ -201,7 +202,7 @@ require (
|
||||||
github.com/spf13/pflag v1.0.6 // indirect
|
github.com/spf13/pflag v1.0.6 // indirect
|
||||||
github.com/spf13/viper v1.20.1 // indirect
|
github.com/spf13/viper v1.20.1 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1164 // indirect
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1161 // indirect
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 // indirect
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 // indirect
|
||||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
||||||
|
@ -221,7 +222,7 @@ require (
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.6.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||||
go.uber.org/automaxprocs v1.6.0 // indirect
|
go.uber.org/automaxprocs v1.6.0 // indirect
|
||||||
go.uber.org/mock v0.5.2 // indirect
|
go.uber.org/mock v0.5.2 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
|
@ -231,9 +232,10 @@ require (
|
||||||
golang.org/x/sys v0.33.0 // indirect
|
golang.org/x/sys v0.33.0 // indirect
|
||||||
golang.org/x/text v0.25.0
|
golang.org/x/text v0.25.0
|
||||||
golang.org/x/tools v0.33.0 // indirect
|
golang.org/x/tools v0.33.0 // indirect
|
||||||
google.golang.org/api v0.233.0 // indirect
|
google.golang.org/api v0.232.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f // indirect
|
||||||
google.golang.org/grpc v1.72.1 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 // indirect
|
||||||
|
google.golang.org/grpc v1.72.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
|
67
go.sum
67
go.sum
|
@ -179,8 +179,8 @@ cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZ
|
||||||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
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=
|
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
|
||||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||||
cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU=
|
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||||
cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
|
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||||
cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY=
|
cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY=
|
||||||
cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck=
|
cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck=
|
||||||
cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w=
|
cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w=
|
||||||
|
@ -606,8 +606,8 @@ github.com/AdamSLevy/jsonrpc2/v14 v14.1.0/go.mod h1:ZakZtbCXxCz82NJvq7MoREtiQesn
|
||||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 h1:j8BorDEigD8UFOSZQiSqAMOOleyQOOQPnUAwV+Ls1gA=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
|
||||||
|
@ -710,8 +710,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjK
|
||||||
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||||
github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
|
github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
|
||||||
github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
||||||
github.com/baidubce/bce-sdk-go v0.9.226 h1:VKEKcJC9P33yIfYJZr12Q/4Bvj18RFbgO8w8XOfU8AI=
|
github.com/baidubce/bce-sdk-go v0.9.225 h1:4zz/cGgrEpAIOM6pkEU3UnlNgEcpO4SV2oVpa0gAZKI=
|
||||||
github.com/baidubce/bce-sdk-go v0.9.226/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
github.com/baidubce/bce-sdk-go v0.9.225/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
||||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
|
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
|
||||||
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
|
@ -749,8 +749,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||||
github.com/civo/civogo v0.5.0 h1:YDG38z+hmgaAhpDad1n/9sZrBtwRTeKVvMgdrS8Gwy4=
|
github.com/civo/civogo v0.4.1 h1:C+lwZ7hBqKy6eKy6qgviuselF0V5Z/um0x7X/eLEQ64=
|
||||||
github.com/civo/civogo v0.5.0/go.mod h1:LaEbkszc+9nXSh4YNG0sYXFGYqdQFmXXzQg0gESs2hc=
|
github.com/civo/civogo v0.4.1/go.mod h1:LaEbkszc+9nXSh4YNG0sYXFGYqdQFmXXzQg0gESs2hc=
|
||||||
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
|
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cloudflare/cloudflare-go v0.115.0 h1:84/dxeeXweCc0PN5Cto44iTA8AkG1fyT11yPO5ZB7sM=
|
github.com/cloudflare/cloudflare-go v0.115.0 h1:84/dxeeXweCc0PN5Cto44iTA8AkG1fyT11yPO5ZB7sM=
|
||||||
|
@ -811,8 +811,8 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
|
||||||
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc=
|
github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I=
|
||||||
github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||||
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab h1:h1UgjJdAAhj+uPL68n7XASS6bU+07ZX1WJvVS2eyoeY=
|
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab h1:h1UgjJdAAhj+uPL68n7XASS6bU+07ZX1WJvVS2eyoeY=
|
||||||
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab/go.mod h1:GLo/8fDswSAniFG+BFIaiSPcK610jyzgEhWYPQwuQdw=
|
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab/go.mod h1:GLo/8fDswSAniFG+BFIaiSPcK610jyzgEhWYPQwuQdw=
|
||||||
|
@ -1065,8 +1065,8 @@ github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMd
|
||||||
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
|
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
|
||||||
github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
||||||
github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
||||||
github.com/googleapis/gax-go/v2 v2.14.2 h1:eBLnkZ9635krYIPD+ag1USrOAI0Nr0QYF3+/3GqO0k0=
|
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
|
||||||
github.com/googleapis/gax-go/v2 v2.14.2/go.mod h1:ON64QhlJkhVtSqp4v1uaK92VyZ2gmvDQsweuyLV+8+w=
|
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
|
||||||
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
||||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||||
github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
|
github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
|
||||||
|
@ -1089,7 +1089,6 @@ github.com/gotify/server/v2 v2.6.3/go.mod h1:IyeQ/iL3vetcuqUAzkCMVObIMGGJx4zb13/
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
|
||||||
|
@ -1150,8 +1149,8 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J
|
||||||
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
||||||
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.149 h1:gDzo/eYE8/mwF5fi7v10pdBW2027PUvaHvRPA5aOPoM=
|
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148 h1:PdWSbniKnPhKe1B19KUHW/9ahYbFH2EY6Iq6sxOnomo=
|
||||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.149/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
|
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
|
||||||
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
|
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
|
||||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
@ -1398,8 +1397,8 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr
|
||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
|
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
|
||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
|
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
|
||||||
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
|
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
|
||||||
github.com/oracle/oci-go-sdk/v65 v65.91.0 h1:maO6AxKxVfszH0X4tbbtN21jOk03lCRR3IqiA8/FzZc=
|
github.com/oracle/oci-go-sdk/v65 v65.90.0 h1:XGoPkq0oThnIzmreyWOG3PkP3r1I1JrEWxOlGocJXt0=
|
||||||
github.com/oracle/oci-go-sdk/v65 v65.91.0/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
|
github.com/oracle/oci-go-sdk/v65 v65.90.0/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
|
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
|
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
|
||||||
github.com/ovh/go-ovh v1.7.0 h1:V14nF7FwDjQrZt9g7jzcvAAQ3HN6DNShRFRMC3jLoPw=
|
github.com/ovh/go-ovh v1.7.0 h1:V14nF7FwDjQrZt9g7jzcvAAQ3HN6DNShRFRMC3jLoPw=
|
||||||
|
@ -1480,16 +1479,16 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
|
||||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/puzpuzpuz/xsync/v4 v4.1.0 h1:x9eHRl4QhZFIPJ17yl4KKW9xLyVWbb3/Yq4SXpjF71U=
|
github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
|
||||||
github.com/puzpuzpuz/xsync/v4 v4.1.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo=
|
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||||
github.com/quic-go/quic-go v0.51.0 h1:K8exxe9zXxeRKxaXxi/GpUqYiTrtdiWP8bo1KFya6Wc=
|
github.com/quic-go/quic-go v0.51.0 h1:K8exxe9zXxeRKxaXxi/GpUqYiTrtdiWP8bo1KFya6Wc=
|
||||||
github.com/quic-go/quic-go v0.51.0/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ=
|
github.com/quic-go/quic-go v0.51.0/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI=
|
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
|
||||||
github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
|
||||||
github.com/regfish/regfish-dnsapi-go v0.1.1 h1:TJFtbePHkd47q5GZwYl1h3DIYXmoxdLjW/SBsPtB5IE=
|
github.com/regfish/regfish-dnsapi-go v0.1.1 h1:TJFtbePHkd47q5GZwYl1h3DIYXmoxdLjW/SBsPtB5IE=
|
||||||
github.com/regfish/regfish-dnsapi-go v0.1.1/go.mod h1:ubIgXSfqarSnl3XHSn8hIFwFF3h0yrq0ZiWD93Y2VjY=
|
github.com/regfish/regfish-dnsapi-go v0.1.1/go.mod h1:ubIgXSfqarSnl3XHSn8hIFwFF3h0yrq0ZiWD93Y2VjY=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
@ -1616,8 +1615,8 @@ github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNG
|
||||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1164 h1:qEzZCZf1sgvvrZ8ngws0gZlyW+sOdY0K9VXGm4AcvTE=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1161 h1:S4dJSWhOtaPjp0/GO/yhzUC6DfZvpWhrnsEKaLxr73c=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1164/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1161/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 h1:kMIdSU5IvpOROh27ToVQ3hlm6ym3lCRs9tnGCOBoZqk=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 h1:kMIdSU5IvpOROh27ToVQ3hlm6ym3lCRs9tnGCOBoZqk=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136/go.mod h1:FpyIz3mymKaExVs6Fz27kxDBS42jqZn7vbACtxdeEH4=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136/go.mod h1:FpyIz3mymKaExVs6Fz27kxDBS42jqZn7vbACtxdeEH4=
|
||||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||||
|
@ -1715,8 +1714,8 @@ go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J
|
||||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
|
go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
|
||||||
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
|
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
|
||||||
go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI=
|
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||||
go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc=
|
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
|
@ -2294,8 +2293,8 @@ google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60c
|
||||||
google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0=
|
google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0=
|
||||||
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
|
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
|
||||||
google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms=
|
google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms=
|
||||||
google.golang.org/api v0.233.0 h1:iGZfjXAJiUFSSaekVB7LzXl6tRfEKhUN7FkZN++07tI=
|
google.golang.org/api v0.232.0 h1:qGnmaIMf7KcuwHOlF3mERVzChloDYwRfOJOrHt8YC3I=
|
||||||
google.golang.org/api v0.233.0/go.mod h1:TCIVLLlcwunlMpZIhIp7Ltk77W+vUSdUKAAIlbxY44c=
|
google.golang.org/api v0.232.0/go.mod h1:p9QCfBWZk1IJETUdbTKloR5ToFdKbYh2fkjsUL6vNoY=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
@ -2436,12 +2435,10 @@ google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOl
|
||||||
google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||||
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||||
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 h1:1tXaIXCracvtsRxSBsYDiSBN0cuJvM7QYW+MrpIRY78=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f h1:tjZsroqekhC63+WMqzmWyW5Twj/ZfR5HAlpd5YQ1Vs0=
|
||||||
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:49MsLSx0oWMOZqcpB3uL8ZOkAh1+TndpJ8ONoCBWiZk=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:Cd8IzgPo5Akum2c9R6FsXNaZbH3Jpa2gpHlW89FqlyQ=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 h1:vPV0tzlsK6EzEDHNNH5sa7Hs9bd7iXR7B1tSiPepkV0=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 h1:IqsN8hx+lWLqlN+Sc3DoMy/watjofWiU8sRFgQ8fhKM=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:pKLAc5OolXC3ViWGI62vvC0n10CpwAtRcTNCFwTKBEw=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 h1:IkAfh6J/yllPtpYFU0zZN1hUPYdT0ogkBT/9hMxHjvg=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
@ -2484,8 +2481,8 @@ google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5v
|
||||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
||||||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
||||||
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
||||||
google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
|
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
||||||
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
|
|
@ -4,10 +4,9 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/puzpuzpuz/xsync/v4"
|
"github.com/puzpuzpuz/xsync/v3"
|
||||||
"github.com/yusing/go-proxy/internal/common"
|
"github.com/yusing/go-proxy/internal/common"
|
||||||
"github.com/yusing/go-proxy/internal/gperr"
|
"github.com/yusing/go-proxy/internal/gperr"
|
||||||
"github.com/yusing/go-proxy/internal/logging"
|
|
||||||
"github.com/yusing/go-proxy/internal/logging/accesslog"
|
"github.com/yusing/go-proxy/internal/logging/accesslog"
|
||||||
"github.com/yusing/go-proxy/internal/maxmind"
|
"github.com/yusing/go-proxy/internal/maxmind"
|
||||||
"github.com/yusing/go-proxy/internal/task"
|
"github.com/yusing/go-proxy/internal/task"
|
||||||
|
@ -22,13 +21,12 @@ type Config struct {
|
||||||
Log *accesslog.ACLLoggerConfig `json:"log"`
|
Log *accesslog.ACLLoggerConfig `json:"log"`
|
||||||
|
|
||||||
config
|
config
|
||||||
valErr gperr.Error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
defaultAllow bool
|
defaultAllow bool
|
||||||
allowLocal bool
|
allowLocal bool
|
||||||
ipCache *xsync.Map[string, *checkCache]
|
ipCache *xsync.MapOf[string, *checkCache]
|
||||||
logAllowed bool
|
logAllowed bool
|
||||||
logger *accesslog.AccessLogger
|
logger *accesslog.AccessLogger
|
||||||
}
|
}
|
||||||
|
@ -59,8 +57,7 @@ func (c *Config) Validate() gperr.Error {
|
||||||
case ACLDeny:
|
case ACLDeny:
|
||||||
c.defaultAllow = false
|
c.defaultAllow = false
|
||||||
default:
|
default:
|
||||||
c.valErr = gperr.New("invalid default value").Subject(c.Default)
|
return gperr.New("invalid default value").Subject(c.Default)
|
||||||
return c.valErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.AllowLocal != nil {
|
if c.AllowLocal != nil {
|
||||||
|
@ -73,17 +70,12 @@ func (c *Config) Validate() gperr.Error {
|
||||||
c.logAllowed = c.Log.LogAllowed
|
c.logAllowed = c.Log.LogAllowed
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.allowLocal && !c.defaultAllow && len(c.Allow) == 0 {
|
c.ipCache = xsync.NewMapOf[string, *checkCache]()
|
||||||
c.valErr = gperr.New("allow_local is false and default is deny, but no allow rules are configured")
|
|
||||||
return c.valErr
|
|
||||||
}
|
|
||||||
|
|
||||||
c.ipCache = xsync.NewMap[string, *checkCache]()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Valid() bool {
|
func (c *Config) Valid() bool {
|
||||||
return c != nil && c.valErr == nil
|
return c != nil && (len(c.Allow) > 0 || len(c.Deny) > 0 || c.allowLocal)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Start(parent *task.Task) gperr.Error {
|
func (c *Config) Start(parent *task.Task) gperr.Error {
|
||||||
|
@ -94,15 +86,6 @@ func (c *Config) Start(parent *task.Task) gperr.Error {
|
||||||
}
|
}
|
||||||
c.logger = logger
|
c.logger = logger
|
||||||
}
|
}
|
||||||
if c.valErr != nil {
|
|
||||||
return c.valErr
|
|
||||||
}
|
|
||||||
logging.Info().
|
|
||||||
Str("default", c.Default).
|
|
||||||
Bool("allow_local", c.allowLocal).
|
|
||||||
Int("allow_rules", len(c.Allow)).
|
|
||||||
Int("deny_rules", len(c.Deny)).
|
|
||||||
Msg("ACL started")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +114,8 @@ func (c *Config) IPAllowed(ip net.IP) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// always allow loopback, not logged
|
// always allow loopback
|
||||||
|
// loopback is not logged
|
||||||
if ip.IsLoopback() {
|
if ip.IsLoopback() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -149,15 +133,19 @@ func (c *Config) IPAllowed(ip net.IP) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
ipAndStr := &maxmind.IPInfo{IP: ip, Str: ipStr}
|
ipAndStr := &maxmind.IPInfo{IP: ip, Str: ipStr}
|
||||||
if c.Allow.Match(ipAndStr) {
|
for _, m := range c.Allow {
|
||||||
c.log(ipAndStr, true)
|
if m(ipAndStr) {
|
||||||
c.cacheRecord(ipAndStr, true)
|
c.log(ipAndStr, true)
|
||||||
return true
|
c.cacheRecord(ipAndStr, true)
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if c.Deny.Match(ipAndStr) {
|
for _, m := range c.Deny {
|
||||||
c.log(ipAndStr, false)
|
if m(ipAndStr) {
|
||||||
c.cacheRecord(ipAndStr, false)
|
c.log(ipAndStr, false)
|
||||||
return false
|
c.cacheRecord(ipAndStr, false)
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log(ipAndStr, c.defaultAllow)
|
c.log(ipAndStr, c.defaultAllow)
|
||||||
|
|
|
@ -8,11 +8,7 @@ import (
|
||||||
"github.com/yusing/go-proxy/internal/maxmind"
|
"github.com/yusing/go-proxy/internal/maxmind"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MatcherFunc func(*maxmind.IPInfo) bool
|
type Matcher func(*maxmind.IPInfo) bool
|
||||||
|
|
||||||
type Matcher struct {
|
|
||||||
match MatcherFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
type Matchers []Matcher
|
type Matchers []Matcher
|
||||||
|
|
||||||
|
@ -23,9 +19,6 @@ const (
|
||||||
MatcherTypeCountry = "country"
|
MatcherTypeCountry = "country"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: use this error in the future
|
|
||||||
//
|
|
||||||
//nolint:unused
|
|
||||||
var errMatcherFormat = gperr.Multiline().AddLines(
|
var errMatcherFormat = gperr.Multiline().AddLines(
|
||||||
"invalid matcher format, expect {type}:{value}",
|
"invalid matcher format, expect {type}:{value}",
|
||||||
"Available types: ip|cidr|tz|country",
|
"Available types: ip|cidr|tz|country",
|
||||||
|
@ -36,62 +29,68 @@ var errMatcherFormat = gperr.Multiline().AddLines(
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errSyntax = gperr.New("syntax error")
|
errSyntax = gperr.New("syntax error")
|
||||||
errInvalidIP = gperr.New("invalid IP")
|
errInvalidIP = gperr.New("invalid IP")
|
||||||
errInvalidCIDR = gperr.New("invalid CIDR")
|
errInvalidCIDR = gperr.New("invalid CIDR")
|
||||||
|
errMaxMindNotConfigured = gperr.New("MaxMind not configured")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (matcher *Matcher) Parse(s string) error {
|
func ParseMatcher(s string) (Matcher, gperr.Error) {
|
||||||
parts := strings.Split(s, ":")
|
parts := strings.Split(s, ":")
|
||||||
if len(parts) != 2 {
|
if len(parts) != 2 {
|
||||||
return errSyntax
|
return nil, errSyntax
|
||||||
}
|
}
|
||||||
|
|
||||||
switch parts[0] {
|
switch parts[0] {
|
||||||
case MatcherTypeIP:
|
case MatcherTypeIP:
|
||||||
ip := net.ParseIP(parts[1])
|
ip := net.ParseIP(parts[1])
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
return errInvalidIP
|
return nil, errInvalidIP
|
||||||
}
|
}
|
||||||
matcher.match = matchIP(ip)
|
return matchIP(ip), nil
|
||||||
case MatcherTypeCIDR:
|
case MatcherTypeCIDR:
|
||||||
_, net, err := net.ParseCIDR(parts[1])
|
_, net, err := net.ParseCIDR(parts[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errInvalidCIDR
|
return nil, errInvalidCIDR
|
||||||
}
|
}
|
||||||
matcher.match = matchCIDR(net)
|
return matchCIDR(net), nil
|
||||||
case MatcherTypeTimeZone:
|
case MatcherTypeTimeZone:
|
||||||
matcher.match = matchTimeZone(parts[1])
|
if !maxmind.HasInstance() {
|
||||||
|
return nil, errMaxMindNotConfigured
|
||||||
|
}
|
||||||
|
return matchTimeZone(parts[1]), nil
|
||||||
case MatcherTypeCountry:
|
case MatcherTypeCountry:
|
||||||
matcher.match = matchISOCode(parts[1])
|
if !maxmind.HasInstance() {
|
||||||
|
return nil, errMaxMindNotConfigured
|
||||||
|
}
|
||||||
|
return matchISOCode(parts[1]), nil
|
||||||
default:
|
default:
|
||||||
return errSyntax
|
return nil, errSyntax
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (matchers Matchers) Match(ip *maxmind.IPInfo) bool {
|
func (matchers Matchers) Match(ip *maxmind.IPInfo) bool {
|
||||||
for _, m := range matchers {
|
for _, m := range matchers {
|
||||||
if m.match(ip) {
|
if m(ip) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchIP(ip net.IP) MatcherFunc {
|
func matchIP(ip net.IP) Matcher {
|
||||||
return func(ip2 *maxmind.IPInfo) bool {
|
return func(ip2 *maxmind.IPInfo) bool {
|
||||||
return ip.Equal(ip2.IP)
|
return ip.Equal(ip2.IP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchCIDR(n *net.IPNet) MatcherFunc {
|
func matchCIDR(n *net.IPNet) Matcher {
|
||||||
return func(ip *maxmind.IPInfo) bool {
|
return func(ip *maxmind.IPInfo) bool {
|
||||||
return n.Contains(ip.IP)
|
return n.Contains(ip.IP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchTimeZone(tz string) MatcherFunc {
|
func matchTimeZone(tz string) Matcher {
|
||||||
return func(ip *maxmind.IPInfo) bool {
|
return func(ip *maxmind.IPInfo) bool {
|
||||||
city, ok := maxmind.LookupCity(ip)
|
city, ok := maxmind.LookupCity(ip)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -101,7 +100,7 @@ func matchTimeZone(tz string) MatcherFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchISOCode(iso string) MatcherFunc {
|
func matchISOCode(iso string) Matcher {
|
||||||
return func(ip *maxmind.IPInfo) bool {
|
return func(ip *maxmind.IPInfo) bool {
|
||||||
city, ok := maxmind.LookupCity(ip)
|
city, ok := maxmind.LookupCity(ip)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
package acl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
maxmind "github.com/yusing/go-proxy/internal/maxmind/types"
|
|
||||||
"github.com/yusing/go-proxy/internal/utils"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMatchers(t *testing.T) {
|
|
||||||
strMatchers := []string{
|
|
||||||
"ip:127.0.0.1",
|
|
||||||
"cidr:10.0.0.0/8",
|
|
||||||
}
|
|
||||||
|
|
||||||
var mathers Matchers
|
|
||||||
err := utils.Convert(reflect.ValueOf(strMatchers), reflect.ValueOf(&mathers), false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
ip string
|
|
||||||
want bool
|
|
||||||
}{
|
|
||||||
{"127.0.0.1", true},
|
|
||||||
{"10.0.0.1", true},
|
|
||||||
{"127.0.0.2", false},
|
|
||||||
{"192.168.0.1", false},
|
|
||||||
{"11.0.0.1", false},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
ip := net.ParseIP(test.ip)
|
|
||||||
if ip == nil {
|
|
||||||
t.Fatalf("invalid ip: %s", test.ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
got := mathers.Match(&maxmind.IPInfo{
|
|
||||||
IP: ip,
|
|
||||||
Str: test.ip,
|
|
||||||
})
|
|
||||||
if got != test.want {
|
|
||||||
t.Errorf("mathers.Match(%s) = %v, want %v", test.ip, got, test.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,12 +10,12 @@ type UDPListener struct {
|
||||||
lis net.PacketConn
|
lis net.PacketConn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapUDP(lis net.PacketConn) net.PacketConn {
|
func (cfg *Config) WrapUDP(lis net.PacketConn) net.PacketConn {
|
||||||
if c == nil {
|
if cfg == nil {
|
||||||
return lis
|
return lis
|
||||||
}
|
}
|
||||||
return &UDPListener{
|
return &UDPListener{
|
||||||
acl: c,
|
acl: cfg,
|
||||||
lis: lis,
|
lis: lis,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/yusing/go-proxy/internal/common"
|
"github.com/yusing/go-proxy/internal/common"
|
||||||
|
@ -48,7 +49,12 @@ func RequireAuth(next http.HandlerFunc) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
if err := defaultAuth.CheckToken(r); err != nil {
|
if err := defaultAuth.CheckToken(r); err != nil {
|
||||||
gphttp.Unauthorized(w, err.Error())
|
if IsFrontend(r) {
|
||||||
|
r = r.WithContext(context.WithValue(r.Context(), nextHandlerContextKey, next))
|
||||||
|
defaultAuth.LoginHandler(w, r)
|
||||||
|
} else {
|
||||||
|
gphttp.Unauthorized(w, err.Error())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
next(w, r)
|
next(w, r)
|
||||||
|
|
|
@ -248,6 +248,8 @@ func (cfg *Config) load() gperr.Error {
|
||||||
err := model.ACL.Start(cfg.task)
|
err := model.ACL.Start(cfg.task)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs.Add(err)
|
errs.Add(err)
|
||||||
|
} else {
|
||||||
|
logging.Info().Msg("ACL started")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,16 +6,16 @@ replace github.com/yusing/go-proxy => ../..
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-acme/lego/v4 v4.23.1
|
github.com/go-acme/lego/v4 v4.23.1
|
||||||
github.com/yusing/go-proxy v0.0.0-00010101000000-000000000000
|
github.com/yusing/go-proxy v0.12.3
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/auth v0.16.1 // indirect
|
cloud.google.com/go/auth v0.16.1 // indirect
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.7.0 // indirect
|
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||||
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
|
||||||
|
@ -39,11 +39,11 @@ require (
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect
|
||||||
github.com/aws/smithy-go v1.22.3 // indirect
|
github.com/aws/smithy-go v1.22.3 // indirect
|
||||||
github.com/baidubce/bce-sdk-go v0.9.226 // indirect
|
github.com/baidubce/bce-sdk-go v0.9.225 // indirect
|
||||||
github.com/benbjohnson/clock v1.3.5 // indirect
|
github.com/benbjohnson/clock v1.3.5 // indirect
|
||||||
github.com/boombuler/barcode v1.0.2 // indirect
|
github.com/boombuler/barcode v1.0.2 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/civo/civogo v0.5.0 // indirect
|
github.com/civo/civogo v0.4.1 // indirect
|
||||||
github.com/cloudflare/cloudflare-go v0.115.0 // indirect
|
github.com/cloudflare/cloudflare-go v0.115.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/dnsimple/dnsimple-go v1.7.0 // indirect
|
github.com/dnsimple/dnsimple-go v1.7.0 // indirect
|
||||||
|
@ -71,14 +71,14 @@ require (
|
||||||
github.com/google/s2a-go v0.1.9 // indirect
|
github.com/google/s2a-go v0.1.9 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
|
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
|
||||||
github.com/gophercloud/gophercloud v1.14.1 // indirect
|
github.com/gophercloud/gophercloud v1.14.1 // indirect
|
||||||
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
|
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
|
||||||
github.com/gotify/server/v2 v2.6.3 // indirect
|
github.com/gotify/server/v2 v2.6.3 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.149 // indirect
|
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148 // indirect
|
||||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
||||||
github.com/infobloxopen/infoblox-go-client/v2 v2.10.0 // indirect
|
github.com/infobloxopen/infoblox-go-client/v2 v2.10.0 // indirect
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
|
@ -113,7 +113,7 @@ require (
|
||||||
github.com/nrdcg/porkbun v0.4.0 // indirect
|
github.com/nrdcg/porkbun v0.4.0 // indirect
|
||||||
github.com/nzdjb/go-metaname v1.0.0 // indirect
|
github.com/nzdjb/go-metaname v1.0.0 // indirect
|
||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
||||||
github.com/oracle/oci-go-sdk/v65 v65.91.0 // indirect
|
github.com/oracle/oci-go-sdk/v65 v65.90.0 // indirect
|
||||||
github.com/ovh/go-ovh v1.7.0 // indirect
|
github.com/ovh/go-ovh v1.7.0 // indirect
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
|
@ -122,7 +122,7 @@ require (
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/pquerna/otp v1.4.0 // indirect
|
github.com/pquerna/otp v1.4.0 // indirect
|
||||||
github.com/puzpuzpuz/xsync/v4 v4.1.0 // indirect
|
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
|
||||||
github.com/regfish/regfish-dnsapi-go v0.1.1 // indirect
|
github.com/regfish/regfish-dnsapi-go v0.1.1 // indirect
|
||||||
github.com/rs/zerolog v1.34.0 // indirect
|
github.com/rs/zerolog v1.34.0 // indirect
|
||||||
github.com/sacloud/api-client-go v0.2.10 // indirect
|
github.com/sacloud/api-client-go v0.2.10 // indirect
|
||||||
|
@ -146,7 +146,7 @@ require (
|
||||||
github.com/spf13/viper v1.20.1 // indirect
|
github.com/spf13/viper v1.20.1 // indirect
|
||||||
github.com/stretchr/testify v1.10.0 // indirect
|
github.com/stretchr/testify v1.10.0 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1164 // indirect
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1161 // indirect
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 // indirect
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 // indirect
|
||||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
github.com/transip/gotransip/v6 v6.26.0 // indirect
|
github.com/transip/gotransip/v6 v6.26.0 // indirect
|
||||||
|
@ -174,9 +174,9 @@ require (
|
||||||
golang.org/x/text v0.25.0 // indirect
|
golang.org/x/text v0.25.0 // indirect
|
||||||
golang.org/x/time v0.11.0 // indirect
|
golang.org/x/time v0.11.0 // indirect
|
||||||
golang.org/x/tools v0.33.0 // indirect
|
golang.org/x/tools v0.33.0 // indirect
|
||||||
google.golang.org/api v0.233.0 // indirect
|
google.golang.org/api v0.232.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 // indirect
|
||||||
google.golang.org/grpc v1.72.1 // indirect
|
google.golang.org/grpc v1.72.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
|
|
@ -179,8 +179,8 @@ cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZ
|
||||||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
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=
|
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
|
||||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||||
cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU=
|
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||||
cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
|
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||||
cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY=
|
cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY=
|
||||||
cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck=
|
cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck=
|
||||||
cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w=
|
cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w=
|
||||||
|
@ -606,8 +606,8 @@ github.com/AdamSLevy/jsonrpc2/v14 v14.1.0/go.mod h1:ZakZtbCXxCz82NJvq7MoREtiQesn
|
||||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 h1:j8BorDEigD8UFOSZQiSqAMOOleyQOOQPnUAwV+Ls1gA=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
|
||||||
|
@ -702,8 +702,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjK
|
||||||
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||||
github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
|
github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
|
||||||
github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
||||||
github.com/baidubce/bce-sdk-go v0.9.226 h1:VKEKcJC9P33yIfYJZr12Q/4Bvj18RFbgO8w8XOfU8AI=
|
github.com/baidubce/bce-sdk-go v0.9.225 h1:4zz/cGgrEpAIOM6pkEU3UnlNgEcpO4SV2oVpa0gAZKI=
|
||||||
github.com/baidubce/bce-sdk-go v0.9.226/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
github.com/baidubce/bce-sdk-go v0.9.225/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
||||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
|
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
|
||||||
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
|
@ -739,8 +739,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||||
github.com/civo/civogo v0.5.0 h1:YDG38z+hmgaAhpDad1n/9sZrBtwRTeKVvMgdrS8Gwy4=
|
github.com/civo/civogo v0.4.1 h1:C+lwZ7hBqKy6eKy6qgviuselF0V5Z/um0x7X/eLEQ64=
|
||||||
github.com/civo/civogo v0.5.0/go.mod h1:LaEbkszc+9nXSh4YNG0sYXFGYqdQFmXXzQg0gESs2hc=
|
github.com/civo/civogo v0.4.1/go.mod h1:LaEbkszc+9nXSh4YNG0sYXFGYqdQFmXXzQg0gESs2hc=
|
||||||
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
|
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cloudflare/cloudflare-go v0.115.0 h1:84/dxeeXweCc0PN5Cto44iTA8AkG1fyT11yPO5ZB7sM=
|
github.com/cloudflare/cloudflare-go v0.115.0 h1:84/dxeeXweCc0PN5Cto44iTA8AkG1fyT11yPO5ZB7sM=
|
||||||
|
@ -1022,8 +1022,8 @@ github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMd
|
||||||
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
|
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
|
||||||
github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
||||||
github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
||||||
github.com/googleapis/gax-go/v2 v2.14.2 h1:eBLnkZ9635krYIPD+ag1USrOAI0Nr0QYF3+/3GqO0k0=
|
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
|
||||||
github.com/googleapis/gax-go/v2 v2.14.2/go.mod h1:ON64QhlJkhVtSqp4v1uaK92VyZ2gmvDQsweuyLV+8+w=
|
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
|
||||||
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
||||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||||
github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
|
github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
|
||||||
|
@ -1100,8 +1100,8 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J
|
||||||
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
||||||
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.149 h1:gDzo/eYE8/mwF5fi7v10pdBW2027PUvaHvRPA5aOPoM=
|
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148 h1:PdWSbniKnPhKe1B19KUHW/9ahYbFH2EY6Iq6sxOnomo=
|
||||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.149/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
|
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
|
||||||
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
|
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
|
||||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
@ -1322,8 +1322,8 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr
|
||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
|
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
|
||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
|
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
|
||||||
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
|
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
|
||||||
github.com/oracle/oci-go-sdk/v65 v65.91.0 h1:maO6AxKxVfszH0X4tbbtN21jOk03lCRR3IqiA8/FzZc=
|
github.com/oracle/oci-go-sdk/v65 v65.90.0 h1:XGoPkq0oThnIzmreyWOG3PkP3r1I1JrEWxOlGocJXt0=
|
||||||
github.com/oracle/oci-go-sdk/v65 v65.91.0/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
|
github.com/oracle/oci-go-sdk/v65 v65.90.0/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
|
||||||
github.com/ovh/go-ovh v1.7.0 h1:V14nF7FwDjQrZt9g7jzcvAAQ3HN6DNShRFRMC3jLoPw=
|
github.com/ovh/go-ovh v1.7.0 h1:V14nF7FwDjQrZt9g7jzcvAAQ3HN6DNShRFRMC3jLoPw=
|
||||||
github.com/ovh/go-ovh v1.7.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
|
github.com/ovh/go-ovh v1.7.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
|
@ -1393,12 +1393,12 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
|
||||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/puzpuzpuz/xsync/v4 v4.1.0 h1:x9eHRl4QhZFIPJ17yl4KKW9xLyVWbb3/Yq4SXpjF71U=
|
github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
|
||||||
github.com/puzpuzpuz/xsync/v4 v4.1.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo=
|
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI=
|
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
|
||||||
github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
|
||||||
github.com/regfish/regfish-dnsapi-go v0.1.1 h1:TJFtbePHkd47q5GZwYl1h3DIYXmoxdLjW/SBsPtB5IE=
|
github.com/regfish/regfish-dnsapi-go v0.1.1 h1:TJFtbePHkd47q5GZwYl1h3DIYXmoxdLjW/SBsPtB5IE=
|
||||||
github.com/regfish/regfish-dnsapi-go v0.1.1/go.mod h1:ubIgXSfqarSnl3XHSn8hIFwFF3h0yrq0ZiWD93Y2VjY=
|
github.com/regfish/regfish-dnsapi-go v0.1.1/go.mod h1:ubIgXSfqarSnl3XHSn8hIFwFF3h0yrq0ZiWD93Y2VjY=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
@ -1519,8 +1519,8 @@ github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNG
|
||||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1164 h1:qEzZCZf1sgvvrZ8ngws0gZlyW+sOdY0K9VXGm4AcvTE=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1161 h1:S4dJSWhOtaPjp0/GO/yhzUC6DfZvpWhrnsEKaLxr73c=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1164/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1161/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 h1:kMIdSU5IvpOROh27ToVQ3hlm6ym3lCRs9tnGCOBoZqk=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 h1:kMIdSU5IvpOROh27ToVQ3hlm6ym3lCRs9tnGCOBoZqk=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136/go.mod h1:FpyIz3mymKaExVs6Fz27kxDBS42jqZn7vbACtxdeEH4=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136/go.mod h1:FpyIz3mymKaExVs6Fz27kxDBS42jqZn7vbACtxdeEH4=
|
||||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||||
|
@ -2155,8 +2155,8 @@ google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60c
|
||||||
google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0=
|
google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0=
|
||||||
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
|
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
|
||||||
google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms=
|
google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms=
|
||||||
google.golang.org/api v0.233.0 h1:iGZfjXAJiUFSSaekVB7LzXl6tRfEKhUN7FkZN++07tI=
|
google.golang.org/api v0.232.0 h1:qGnmaIMf7KcuwHOlF3mERVzChloDYwRfOJOrHt8YC3I=
|
||||||
google.golang.org/api v0.233.0/go.mod h1:TCIVLLlcwunlMpZIhIp7Ltk77W+vUSdUKAAIlbxY44c=
|
google.golang.org/api v0.232.0/go.mod h1:p9QCfBWZk1IJETUdbTKloR5ToFdKbYh2fkjsUL6vNoY=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
@ -2297,12 +2297,11 @@ google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOl
|
||||||
google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||||
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||||
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 h1:1tXaIXCracvtsRxSBsYDiSBN0cuJvM7QYW+MrpIRY78=
|
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU=
|
||||||
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:49MsLSx0oWMOZqcpB3uL8ZOkAh1+TndpJ8ONoCBWiZk=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f h1:tjZsroqekhC63+WMqzmWyW5Twj/ZfR5HAlpd5YQ1Vs0=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 h1:vPV0tzlsK6EzEDHNNH5sa7Hs9bd7iXR7B1tSiPepkV0=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:Cd8IzgPo5Akum2c9R6FsXNaZbH3Jpa2gpHlW89FqlyQ=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:pKLAc5OolXC3ViWGI62vvC0n10CpwAtRcTNCFwTKBEw=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 h1:IqsN8hx+lWLqlN+Sc3DoMy/watjofWiU8sRFgQ8fhKM=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 h1:IkAfh6J/yllPtpYFU0zZN1hUPYdT0ogkBT/9hMxHjvg=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
@ -2345,8 +2344,8 @@ google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5v
|
||||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
||||||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
||||||
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
||||||
google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
|
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
||||||
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
|
|
@ -54,7 +54,7 @@ func TestContainerHostNetworkMode(t *testing.T) {
|
||||||
Names: []string{"test"},
|
Names: []string{"test"},
|
||||||
State: "test",
|
State: "test",
|
||||||
HostConfig: struct {
|
HostConfig: struct {
|
||||||
NetworkMode string `json:",omitempty"`
|
NetworkMode string "json:\",omitempty\""
|
||||||
}{
|
}{
|
||||||
NetworkMode: "host",
|
NetworkMode: "host",
|
||||||
},
|
},
|
||||||
|
|
|
@ -36,11 +36,8 @@ func (err *baseError) Subjectf(format string, args ...any) Error {
|
||||||
return err.Subject(format)
|
return err.Subject(format)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err *baseError) With(extra error) Error {
|
func (err baseError) With(extra error) Error {
|
||||||
if extra == nil {
|
return &nestedError{&err, []error{extra}}
|
||||||
return err
|
|
||||||
}
|
|
||||||
return &nestedError{&baseError{err.Err}, []error{extra}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err baseError) Withf(format string, args ...any) Error {
|
func (err baseError) Withf(format string, args ...any) Error {
|
||||||
|
|
|
@ -59,9 +59,6 @@ func (b *Builder) Error() Error {
|
||||||
if len(b.errs) == 0 {
|
if len(b.errs) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if len(b.errs) == 1 && b.about == "" {
|
|
||||||
return wrap(b.errs[0])
|
|
||||||
}
|
|
||||||
return &nestedError{Err: New(b.about), Extras: b.errs}
|
return &nestedError{Err: New(b.about), Extras: b.errs}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ func (h *Hint) String() string {
|
||||||
return h.Error()
|
return h.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func DoYouMean(s string) error {
|
func DoYouMean(s string) *Hint {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,9 @@ type nestedError struct {
|
||||||
Extras []error `json:"extras"`
|
Extras []error `json:"extras"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var emptyError = errStr("")
|
|
||||||
|
|
||||||
func (err nestedError) Subject(subject string) Error {
|
func (err nestedError) Subject(subject string) Error {
|
||||||
if err.Err == nil {
|
if err.Err == nil {
|
||||||
err.Err = PrependSubject(subject, emptyError)
|
err.Err = PrependSubject(subject, errStr(""))
|
||||||
} else {
|
} else {
|
||||||
err.Err = PrependSubject(subject, err.Err)
|
err.Err = PrependSubject(subject, err.Err)
|
||||||
}
|
}
|
||||||
|
@ -80,10 +78,8 @@ func (err *nestedError) fmtError(appendLine appendLineFunc) []byte {
|
||||||
}
|
}
|
||||||
if err.Err != nil {
|
if err.Err != nil {
|
||||||
buf := appendLine(nil, err.Err, 0)
|
buf := appendLine(nil, err.Err, 0)
|
||||||
if len(err.Extras) > 0 {
|
buf = append(buf, '\n')
|
||||||
buf = append(buf, '\n')
|
buf = appendLines(buf, err.Extras, 1, appendLine)
|
||||||
buf = appendLines(buf, err.Extras, 1, appendLine)
|
|
||||||
}
|
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
return appendLines(nil, err.Extras, 0, appendLine)
|
return appendLines(nil, err.Extras, 0, appendLine)
|
||||||
|
|
|
@ -45,11 +45,6 @@ func PrependSubject(subject string, err error) error {
|
||||||
switch err := err.(type) {
|
switch err := err.(type) {
|
||||||
case *withSubject:
|
case *withSubject:
|
||||||
return err.Prepend(subject)
|
return err.Prepend(subject)
|
||||||
case *wrappedError:
|
|
||||||
return &wrappedError{
|
|
||||||
Err: PrependSubject(subject, err.Err),
|
|
||||||
Message: err.Message,
|
|
||||||
}
|
|
||||||
case Error:
|
case Error:
|
||||||
return err.Subject(subject)
|
return err.Subject(subject)
|
||||||
}
|
}
|
||||||
|
@ -100,24 +95,20 @@ func (err *withSubject) Markdown() []byte {
|
||||||
|
|
||||||
func (err *withSubject) fmtError(highlight highlightFunc) []byte {
|
func (err *withSubject) fmtError(highlight highlightFunc) []byte {
|
||||||
// subject is in reversed order
|
// subject is in reversed order
|
||||||
|
n := len(err.Subjects)
|
||||||
size := 0
|
size := 0
|
||||||
errStr := err.Err.Error()
|
errStr := err.Err.Error()
|
||||||
subjects := err.Subjects
|
|
||||||
if err.pendingSubject != "" {
|
|
||||||
subjects = append(subjects, err.pendingSubject)
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
for _, s := range subjects {
|
for _, s := range err.Subjects {
|
||||||
size += len(s)
|
size += len(s)
|
||||||
}
|
}
|
||||||
n := len(subjects)
|
|
||||||
buf.Grow(size + 2 + n*len(subjectSep) + len(errStr) + len(highlight("")))
|
buf.Grow(size + 2 + n*len(subjectSep) + len(errStr) + len(highlight("")))
|
||||||
|
|
||||||
for i := n - 1; i > 0; i-- {
|
for i := n - 1; i > 0; i-- {
|
||||||
buf.WriteString(subjects[i])
|
buf.WriteString(err.Subjects[i])
|
||||||
buf.WriteString(subjectSep)
|
buf.WriteString(subjectSep)
|
||||||
}
|
}
|
||||||
buf.WriteString(highlight(subjects[0]))
|
buf.WriteString(highlight(err.Subjects[0]))
|
||||||
if errStr != "" {
|
if errStr != "" {
|
||||||
buf.WriteString(": ")
|
buf.WriteString(": ")
|
||||||
buf.WriteString(errStr)
|
buf.WriteString(errStr)
|
||||||
|
@ -136,9 +127,6 @@ func (err *withSubject) MarshalJSON() ([]byte, error) {
|
||||||
Subjects: subjects,
|
Subjects: subjects,
|
||||||
Err: err.Err,
|
Err: err.Err,
|
||||||
}
|
}
|
||||||
if err.pendingSubject != "" {
|
|
||||||
reversed.Subjects = append(reversed.Subjects, err.pendingSubject)
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.Marshal(reversed)
|
return json.Marshal(reversed)
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,9 +87,6 @@ func Join(errors ...error) Error {
|
||||||
func JoinLines(main error, errors ...string) Error {
|
func JoinLines(main error, errors ...string) Error {
|
||||||
errs := make([]error, len(errors))
|
errs := make([]error, len(errors))
|
||||||
for i, err := range errors {
|
for i, err := range errors {
|
||||||
if err == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
errs[i] = newError(err)
|
errs[i] = newError(err)
|
||||||
}
|
}
|
||||||
return &nestedError{Err: main, Extras: errs}
|
return &nestedError{Err: main, Extras: errs}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
"maps"
|
"maps"
|
||||||
|
|
||||||
"github.com/puzpuzpuz/xsync/v4"
|
"github.com/puzpuzpuz/xsync/v3"
|
||||||
"github.com/yusing/go-proxy/internal/common"
|
"github.com/yusing/go-proxy/internal/common"
|
||||||
"github.com/yusing/go-proxy/internal/gperr"
|
"github.com/yusing/go-proxy/internal/gperr"
|
||||||
"github.com/yusing/go-proxy/internal/logging"
|
"github.com/yusing/go-proxy/internal/logging"
|
||||||
|
@ -19,7 +19,7 @@ import (
|
||||||
type namespace string
|
type namespace string
|
||||||
|
|
||||||
type MapStore[VT any] struct {
|
type MapStore[VT any] struct {
|
||||||
*xsync.Map[string, VT]
|
*xsync.MapOf[string, VT]
|
||||||
}
|
}
|
||||||
|
|
||||||
type ObjectStore[Pointer Initializer] struct {
|
type ObjectStore[Pointer Initializer] struct {
|
||||||
|
@ -103,7 +103,7 @@ func Object[Ptr Initializer](namespace namespace) Ptr {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MapStore[VT]) Initialize() {
|
func (s *MapStore[VT]) Initialize() {
|
||||||
s.Map = xsync.NewMap[string, VT]()
|
s.MapOf = xsync.NewMapOf[string, VT]()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s MapStore[VT]) MarshalJSON() ([]byte, error) {
|
func (s MapStore[VT]) MarshalJSON() ([]byte, error) {
|
||||||
|
@ -115,9 +115,9 @@ func (s *MapStore[VT]) UnmarshalJSON(data []byte) error {
|
||||||
if err := json.Unmarshal(data, &tmp); err != nil {
|
if err := json.Unmarshal(data, &tmp); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.Map = xsync.NewMap[string, VT](xsync.WithPresize(len(tmp)))
|
s.MapOf = xsync.NewMapOf[string, VT](xsync.WithPresize(len(tmp)))
|
||||||
for k, v := range tmp {
|
for k, v := range tmp {
|
||||||
s.Map.Store(k, v)
|
s.MapOf.Store(k, v)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ func TestSaveLoadStore(t *testing.T) {
|
||||||
if v != "1" {
|
if v != "1" {
|
||||||
t.Fatalf("expected 1, got %q", v)
|
t.Fatalf("expected 1, got %q", v)
|
||||||
}
|
}
|
||||||
if loaded.Map == store.Map {
|
if loaded.MapOf == store.MapOf {
|
||||||
t.Fatal("expected different objects")
|
t.Fatal("expected different objects")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package accesslog
|
package accesslog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -12,7 +13,6 @@ import (
|
||||||
"github.com/yusing/go-proxy/internal/logging"
|
"github.com/yusing/go-proxy/internal/logging"
|
||||||
maxmind "github.com/yusing/go-proxy/internal/maxmind/types"
|
maxmind "github.com/yusing/go-proxy/internal/maxmind/types"
|
||||||
"github.com/yusing/go-proxy/internal/task"
|
"github.com/yusing/go-proxy/internal/task"
|
||||||
"github.com/yusing/go-proxy/internal/utils"
|
|
||||||
"github.com/yusing/go-proxy/internal/utils/strutils"
|
"github.com/yusing/go-proxy/internal/utils/strutils"
|
||||||
"github.com/yusing/go-proxy/internal/utils/synk"
|
"github.com/yusing/go-proxy/internal/utils/synk"
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
|
@ -26,7 +26,7 @@ type (
|
||||||
rawWriter io.Writer
|
rawWriter io.Writer
|
||||||
closer []io.Closer
|
closer []io.Closer
|
||||||
supportRotate []supportRotate
|
supportRotate []supportRotate
|
||||||
writer *utils.BufferedWriter
|
writer *bufio.Writer
|
||||||
writeLock sync.Mutex
|
writeLock sync.Mutex
|
||||||
closed bool
|
closed bool
|
||||||
|
|
||||||
|
@ -116,9 +116,9 @@ func NewAccessLoggerWithIO(parent task.Parent, writer WriterWithName, anyCfg Any
|
||||||
task: parent.Subtask("accesslog."+writer.Name(), true),
|
task: parent.Subtask("accesslog."+writer.Name(), true),
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
rawWriter: writer,
|
rawWriter: writer,
|
||||||
writer: utils.NewBufferedWriter(writer, MinBufferSize),
|
writer: bufio.NewWriterSize(writer, MinBufferSize),
|
||||||
bufSize: MinBufferSize,
|
bufSize: MinBufferSize,
|
||||||
lineBufPool: synk.NewBytesPool(),
|
lineBufPool: synk.NewBytesPool(256, 768), // for common/combined usually < 256B; for json < 512B
|
||||||
errRateLimiter: rate.NewLimiter(rate.Every(errRateLimit), errBurst),
|
errRateLimiter: rate.NewLimiter(rate.Every(errRateLimit), errBurst),
|
||||||
logger: logging.With().Str("file", writer.Name()).Logger(),
|
logger: logging.With().Str("file", writer.Name()).Logger(),
|
||||||
}
|
}
|
||||||
|
@ -269,7 +269,6 @@ func (l *AccessLogger) Close() error {
|
||||||
c.Close()
|
c.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l.writer.Release()
|
|
||||||
l.closed = true
|
l.closed = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -340,10 +339,6 @@ func (l *AccessLogger) adjustBuffer() {
|
||||||
Str("new", strutils.FormatByteSize(newBufSize)).
|
Str("new", strutils.FormatByteSize(newBufSize)).
|
||||||
Msg("adjusted buffer size")
|
Msg("adjusted buffer size")
|
||||||
|
|
||||||
err := l.writer.Resize(newBufSize)
|
l.writer = bufio.NewWriterSize(l.rawWriter, newBufSize)
|
||||||
if err != nil {
|
|
||||||
l.handleErr(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
l.bufSize = newBufSize
|
l.bufSize = newBufSize
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,8 @@ type lineInfo struct {
|
||||||
Size int64 // Size of this line
|
Size int64 // Size of this line
|
||||||
}
|
}
|
||||||
|
|
||||||
var rotateBytePool = synk.NewBytesPool()
|
// do not allocate initial size
|
||||||
|
var rotateBytePool = synk.NewBytesPool(0, 16*1024*1024)
|
||||||
|
|
||||||
// rotateLogFile rotates the log file based on the retention policy.
|
// rotateLogFile rotates the log file based on the retention policy.
|
||||||
// It returns the result of the rotation and an error if any.
|
// It returns the result of the rotation and an error if any.
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/coder/websocket"
|
"github.com/coder/websocket"
|
||||||
"github.com/puzpuzpuz/xsync/v4"
|
"github.com/puzpuzpuz/xsync/v3"
|
||||||
"github.com/yusing/go-proxy/internal/net/gphttp/gpwebsocket"
|
"github.com/yusing/go-proxy/internal/net/gphttp/gpwebsocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ type memLogger struct {
|
||||||
*bytes.Buffer
|
*bytes.Buffer
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
notifyLock sync.RWMutex
|
notifyLock sync.RWMutex
|
||||||
connChans *xsync.Map[chan *logEntryRange, struct{}]
|
connChans *xsync.MapOf[chan *logEntryRange, struct{}]
|
||||||
listeners *xsync.Map[chan []byte, struct{}]
|
listeners *xsync.MapOf[chan []byte, struct{}]
|
||||||
}
|
}
|
||||||
|
|
||||||
type MemLogger io.Writer
|
type MemLogger io.Writer
|
||||||
|
@ -35,8 +35,8 @@ const (
|
||||||
|
|
||||||
var memLoggerInstance = &memLogger{
|
var memLoggerInstance = &memLogger{
|
||||||
Buffer: bytes.NewBuffer(make([]byte, maxMemLogSize)),
|
Buffer: bytes.NewBuffer(make([]byte, maxMemLogSize)),
|
||||||
connChans: xsync.NewMap[chan *logEntryRange, struct{}](),
|
connChans: xsync.NewMapOf[chan *logEntryRange, struct{}](),
|
||||||
listeners: xsync.NewMap[chan []byte, struct{}](),
|
listeners: xsync.NewMapOf[chan []byte, struct{}](),
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMemLogger() MemLogger {
|
func GetMemLogger() MemLogger {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package maxmind
|
package maxmind
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/puzpuzpuz/xsync/v4"
|
"github.com/puzpuzpuz/xsync/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cityCache = xsync.NewMap[string, *City]()
|
var cityCache = xsync.NewMapOf[string, *City]()
|
||||||
|
|
||||||
func (cfg *MaxMind) lookupCity(ip *IPInfo) (*City, bool) {
|
func (cfg *MaxMind) lookupCity(ip *IPInfo) (*City, bool) {
|
||||||
if ip.City != nil {
|
if ip.City != nil {
|
||||||
|
|
|
@ -1,29 +1,12 @@
|
||||||
package maxmind
|
package maxmind
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
"github.com/yusing/go-proxy/internal/gperr"
|
"github.com/yusing/go-proxy/internal/gperr"
|
||||||
"github.com/yusing/go-proxy/internal/notif"
|
|
||||||
"github.com/yusing/go-proxy/internal/task"
|
"github.com/yusing/go-proxy/internal/task"
|
||||||
)
|
)
|
||||||
|
|
||||||
var instance *MaxMind
|
var instance *MaxMind
|
||||||
|
|
||||||
var warnOnce sync.Once
|
|
||||||
|
|
||||||
func warnNotConfigured() {
|
|
||||||
log.Warn().Msg("MaxMind not configured, geo lookup will fail")
|
|
||||||
notif.Notify(¬if.LogMessage{
|
|
||||||
Level: zerolog.WarnLevel,
|
|
||||||
Title: "MaxMind not configured",
|
|
||||||
Body: notif.MessageBody("MaxMind is not configured, geo lookup will fail"),
|
|
||||||
Color: notif.ColorError,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetInstance(parent task.Parent, cfg *Config) gperr.Error {
|
func SetInstance(parent task.Parent, cfg *Config) gperr.Error {
|
||||||
newInstance := &MaxMind{Config: cfg}
|
newInstance := &MaxMind{Config: cfg}
|
||||||
if err := newInstance.LoadMaxMindDB(parent); err != nil {
|
if err := newInstance.LoadMaxMindDB(parent); err != nil {
|
||||||
|
@ -39,7 +22,6 @@ func HasInstance() bool {
|
||||||
|
|
||||||
func LookupCity(ip *IPInfo) (*City, bool) {
|
func LookupCity(ip *IPInfo) (*City, bool) {
|
||||||
if instance == nil {
|
if instance == nil {
|
||||||
warnOnce.Do(warnNotConfigured)
|
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
return instance.lookupCity(ip)
|
return instance.lookupCity(ip)
|
||||||
|
|
|
@ -1,201 +0,0 @@
|
||||||
package systeminfo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/v4/sensors"
|
|
||||||
"github.com/yusing/go-proxy/internal/utils/synk"
|
|
||||||
)
|
|
||||||
|
|
||||||
var bufPool = synk.NewBytesPool()
|
|
||||||
|
|
||||||
// explicitly implement MarshalJSON to avoid reflection.
|
|
||||||
func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
|
||||||
b := bufPool.Get()
|
|
||||||
defer bufPool.Put(b)
|
|
||||||
|
|
||||||
b = append(b, '{')
|
|
||||||
|
|
||||||
// timestamp
|
|
||||||
b = append(b, `"timestamp":`...)
|
|
||||||
b = strconv.AppendInt(b, s.Timestamp, 10)
|
|
||||||
|
|
||||||
// cpu_average
|
|
||||||
b = append(b, `,"cpu_average":`...)
|
|
||||||
if s.CPUAverage != nil {
|
|
||||||
b = strconv.AppendFloat(b, *s.CPUAverage, 'f', 2, 64)
|
|
||||||
} else {
|
|
||||||
b = append(b, "null"...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// memory
|
|
||||||
b = append(b, `,"memory":`...)
|
|
||||||
if s.Memory != nil {
|
|
||||||
b = fmt.Appendf(b,
|
|
||||||
`{"total":%d,"available":%d,"used":%d,"used_percent":%.2f}`,
|
|
||||||
s.Memory.Total,
|
|
||||||
s.Memory.Available,
|
|
||||||
s.Memory.Used,
|
|
||||||
s.Memory.UsedPercent,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
b = append(b, "null"...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// disk
|
|
||||||
b = append(b, `,"disks":`...)
|
|
||||||
if len(s.Disks) > 0 {
|
|
||||||
b = append(b, '{')
|
|
||||||
first := true
|
|
||||||
for device, disk := range s.Disks {
|
|
||||||
if !first {
|
|
||||||
b = append(b, ',')
|
|
||||||
}
|
|
||||||
b = fmt.Appendf(b,
|
|
||||||
`"%s":{"device":"%s","path":"%s","fstype":"%s","total":%d,"free":%d,"used":%d,"used_percent":%.2f}`,
|
|
||||||
device,
|
|
||||||
device,
|
|
||||||
disk.Path,
|
|
||||||
disk.Fstype,
|
|
||||||
disk.Total,
|
|
||||||
disk.Free,
|
|
||||||
disk.Used,
|
|
||||||
disk.UsedPercent,
|
|
||||||
)
|
|
||||||
first = false
|
|
||||||
}
|
|
||||||
b = append(b, '}')
|
|
||||||
} else {
|
|
||||||
b = append(b, "null"...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// disks_io
|
|
||||||
b = append(b, `,"disks_io":`...)
|
|
||||||
if len(s.DisksIO) > 0 {
|
|
||||||
b = append(b, '{')
|
|
||||||
first := true
|
|
||||||
for name, usage := range s.DisksIO {
|
|
||||||
if !first {
|
|
||||||
b = append(b, ',')
|
|
||||||
}
|
|
||||||
b = fmt.Appendf(b,
|
|
||||||
`"%s":{"name":"%s","read_bytes":%d,"write_bytes":%d,"read_speed":%.2f,"write_speed":%.2f,"iops":%d}`,
|
|
||||||
name,
|
|
||||||
name,
|
|
||||||
usage.ReadBytes,
|
|
||||||
usage.WriteBytes,
|
|
||||||
usage.ReadSpeed,
|
|
||||||
usage.WriteSpeed,
|
|
||||||
usage.Iops,
|
|
||||||
)
|
|
||||||
first = false
|
|
||||||
}
|
|
||||||
b = append(b, '}')
|
|
||||||
} else {
|
|
||||||
b = append(b, "null"...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// network
|
|
||||||
b = append(b, `,"network":`...)
|
|
||||||
if s.Network != nil {
|
|
||||||
b = fmt.Appendf(b,
|
|
||||||
`{"bytes_sent":%d,"bytes_recv":%d,"upload_speed":%.2f,"download_speed":%.2f}`,
|
|
||||||
s.Network.BytesSent,
|
|
||||||
s.Network.BytesRecv,
|
|
||||||
s.Network.UploadSpeed,
|
|
||||||
s.Network.DownloadSpeed,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
b = append(b, "null"...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sensors
|
|
||||||
b = append(b, `,"sensors":`...)
|
|
||||||
if len(s.Sensors) > 0 {
|
|
||||||
b = append(b, '{')
|
|
||||||
first := true
|
|
||||||
for _, sensor := range s.Sensors {
|
|
||||||
if !first {
|
|
||||||
b = append(b, ',')
|
|
||||||
}
|
|
||||||
b = fmt.Appendf(b,
|
|
||||||
`"%s":{"name":"%s","temperature":%.2f,"high":%.2f,"critical":%.2f}`,
|
|
||||||
sensor.SensorKey,
|
|
||||||
sensor.SensorKey,
|
|
||||||
sensor.Temperature,
|
|
||||||
sensor.High,
|
|
||||||
sensor.Critical,
|
|
||||||
)
|
|
||||||
first = false
|
|
||||||
}
|
|
||||||
b = append(b, '}')
|
|
||||||
} else {
|
|
||||||
b = append(b, "null"...)
|
|
||||||
}
|
|
||||||
|
|
||||||
b = append(b, '}')
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sensors) UnmarshalJSON(data []byte) error {
|
|
||||||
var v map[string]map[string]any
|
|
||||||
if err := json.Unmarshal(data, &v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(v) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
*s = make(Sensors, 0, len(v))
|
|
||||||
for k, v := range v {
|
|
||||||
*s = append(*s, sensors.TemperatureStat{
|
|
||||||
SensorKey: k,
|
|
||||||
Temperature: v["temperature"].(float64),
|
|
||||||
High: v["high"].(float64),
|
|
||||||
Critical: v["critical"].(float64),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (result Aggregated) MarshalJSON() ([]byte, error) {
|
|
||||||
buf := bufPool.Get()
|
|
||||||
defer bufPool.Put(buf)
|
|
||||||
|
|
||||||
buf = append(buf, '[')
|
|
||||||
i := 0
|
|
||||||
n := len(result)
|
|
||||||
for _, entry := range result {
|
|
||||||
buf = append(buf, '{')
|
|
||||||
j := 0
|
|
||||||
m := len(entry)
|
|
||||||
for k, v := range entry {
|
|
||||||
buf = append(buf, '"')
|
|
||||||
buf = append(buf, k...)
|
|
||||||
buf = append(buf, '"')
|
|
||||||
buf = append(buf, ':')
|
|
||||||
switch v := v.(type) {
|
|
||||||
case float64:
|
|
||||||
buf = strconv.AppendFloat(buf, v, 'f', 2, 64)
|
|
||||||
case uint64:
|
|
||||||
buf = strconv.AppendUint(buf, v, 10)
|
|
||||||
case int64:
|
|
||||||
buf = strconv.AppendInt(buf, v, 10)
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("unexpected type: %T", v))
|
|
||||||
}
|
|
||||||
if j != m-1 {
|
|
||||||
buf = append(buf, ',')
|
|
||||||
}
|
|
||||||
j++
|
|
||||||
}
|
|
||||||
buf = append(buf, '}')
|
|
||||||
if i != n-1 {
|
|
||||||
buf = append(buf, ',')
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
buf = append(buf, ']')
|
|
||||||
return buf, nil
|
|
||||||
}
|
|
|
@ -2,9 +2,11 @@ package systeminfo // import github.com/yusing/go-proxy/internal/metrics/systemi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sync"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -18,6 +20,7 @@ import (
|
||||||
"github.com/yusing/go-proxy/internal/gperr"
|
"github.com/yusing/go-proxy/internal/gperr"
|
||||||
"github.com/yusing/go-proxy/internal/logging"
|
"github.com/yusing/go-proxy/internal/logging"
|
||||||
"github.com/yusing/go-proxy/internal/metrics/period"
|
"github.com/yusing/go-proxy/internal/metrics/period"
|
||||||
|
"github.com/yusing/go-proxy/internal/utils/synk"
|
||||||
)
|
)
|
||||||
|
|
||||||
// json tags are left for tests
|
// json tags are left for tests
|
||||||
|
@ -65,53 +68,34 @@ var allQueries = []string{
|
||||||
|
|
||||||
var Poller = period.NewPoller("system_info", getSystemInfo, aggregate)
|
var Poller = period.NewPoller("system_info", getSystemInfo, aggregate)
|
||||||
|
|
||||||
|
func _() { // check if this behavior is not changed
|
||||||
|
var _ sensors.Warnings = disk.Warnings{}
|
||||||
|
}
|
||||||
|
|
||||||
func isNoDataAvailable(err error) bool {
|
func isNoDataAvailable(err error) bool {
|
||||||
return errors.Is(err, syscall.ENODATA)
|
return errors.Is(err, syscall.ENODATA)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSystemInfo(ctx context.Context, lastResult *SystemInfo) (*SystemInfo, error) {
|
func getSystemInfo(ctx context.Context, lastResult *SystemInfo) (*SystemInfo, error) {
|
||||||
errs := gperr.NewBuilderWithConcurrency("failed to get system info")
|
errs := gperr.NewBuilder("failed to get system info")
|
||||||
var s SystemInfo
|
var s SystemInfo
|
||||||
s.Timestamp = time.Now().Unix()
|
s.Timestamp = time.Now().Unix()
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
|
|
||||||
if !common.MetricsDisableCPU {
|
if !common.MetricsDisableCPU {
|
||||||
wg.Add(1)
|
errs.Add(s.collectCPUInfo(ctx))
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
errs.Add(s.collectCPUInfo(ctx))
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
if !common.MetricsDisableMemory {
|
if !common.MetricsDisableMemory {
|
||||||
wg.Add(1)
|
errs.Add(s.collectMemoryInfo(ctx))
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
errs.Add(s.collectMemoryInfo(ctx))
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
if !common.MetricsDisableDisk {
|
if !common.MetricsDisableDisk {
|
||||||
wg.Add(1)
|
errs.Add(s.collectDisksInfo(ctx, lastResult))
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
errs.Add(s.collectDisksInfo(ctx, lastResult))
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
if !common.MetricsDisableNetwork {
|
if !common.MetricsDisableNetwork {
|
||||||
wg.Add(1)
|
errs.Add(s.collectNetworkInfo(ctx, lastResult))
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
errs.Add(s.collectNetworkInfo(ctx, lastResult))
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
if !common.MetricsDisableSensors {
|
if !common.MetricsDisableSensors {
|
||||||
wg.Add(1)
|
errs.Add(s.collectSensorsInfo(ctx))
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
errs.Add(s.collectSensorsInfo(ctx))
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
if errs.HasError() {
|
if errs.HasError() {
|
||||||
allWarnings := gperr.NewBuilder("")
|
allWarnings := gperr.NewBuilder("")
|
||||||
|
@ -223,7 +207,157 @@ func (s *SystemInfo) collectSensorsInfo(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// recharts friendly.
|
var bufPool = synk.NewBytesPool(1024, 16384)
|
||||||
|
|
||||||
|
// explicitly implement MarshalJSON to avoid reflection
|
||||||
|
func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
||||||
|
b := bufPool.Get()
|
||||||
|
defer bufPool.Put(b)
|
||||||
|
|
||||||
|
b = append(b, '{')
|
||||||
|
|
||||||
|
// timestamp
|
||||||
|
b = append(b, `"timestamp":`...)
|
||||||
|
b = strconv.AppendInt(b, s.Timestamp, 10)
|
||||||
|
|
||||||
|
// cpu_average
|
||||||
|
b = append(b, `,"cpu_average":`...)
|
||||||
|
if s.CPUAverage != nil {
|
||||||
|
b = strconv.AppendFloat(b, *s.CPUAverage, 'f', 2, 64)
|
||||||
|
} else {
|
||||||
|
b = append(b, "null"...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// memory
|
||||||
|
b = append(b, `,"memory":`...)
|
||||||
|
if s.Memory != nil {
|
||||||
|
b = fmt.Appendf(b,
|
||||||
|
`{"total":%d,"available":%d,"used":%d,"used_percent":%.2f}`,
|
||||||
|
s.Memory.Total,
|
||||||
|
s.Memory.Available,
|
||||||
|
s.Memory.Used,
|
||||||
|
s.Memory.UsedPercent,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
b = append(b, "null"...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// disk
|
||||||
|
b = append(b, `,"disks":`...)
|
||||||
|
if len(s.Disks) > 0 {
|
||||||
|
b = append(b, '{')
|
||||||
|
first := true
|
||||||
|
for device, disk := range s.Disks {
|
||||||
|
if !first {
|
||||||
|
b = append(b, ',')
|
||||||
|
}
|
||||||
|
b = fmt.Appendf(b,
|
||||||
|
`"%s":{"device":"%s","path":"%s","fstype":"%s","total":%d,"free":%d,"used":%d,"used_percent":%.2f}`,
|
||||||
|
device,
|
||||||
|
device,
|
||||||
|
disk.Path,
|
||||||
|
disk.Fstype,
|
||||||
|
disk.Total,
|
||||||
|
disk.Free,
|
||||||
|
disk.Used,
|
||||||
|
disk.UsedPercent,
|
||||||
|
)
|
||||||
|
first = false
|
||||||
|
}
|
||||||
|
b = append(b, '}')
|
||||||
|
} else {
|
||||||
|
b = append(b, "null"...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// disks_io
|
||||||
|
b = append(b, `,"disks_io":`...)
|
||||||
|
if len(s.DisksIO) > 0 {
|
||||||
|
b = append(b, '{')
|
||||||
|
first := true
|
||||||
|
for name, usage := range s.DisksIO {
|
||||||
|
if !first {
|
||||||
|
b = append(b, ',')
|
||||||
|
}
|
||||||
|
b = fmt.Appendf(b,
|
||||||
|
`"%s":{"name":"%s","read_bytes":%d,"write_bytes":%d,"read_speed":%.2f,"write_speed":%.2f,"iops":%d}`,
|
||||||
|
name,
|
||||||
|
name,
|
||||||
|
usage.ReadBytes,
|
||||||
|
usage.WriteBytes,
|
||||||
|
usage.ReadSpeed,
|
||||||
|
usage.WriteSpeed,
|
||||||
|
usage.Iops,
|
||||||
|
)
|
||||||
|
first = false
|
||||||
|
}
|
||||||
|
b = append(b, '}')
|
||||||
|
} else {
|
||||||
|
b = append(b, "null"...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// network
|
||||||
|
b = append(b, `,"network":`...)
|
||||||
|
if s.Network != nil {
|
||||||
|
b = fmt.Appendf(b,
|
||||||
|
`{"bytes_sent":%d,"bytes_recv":%d,"upload_speed":%.2f,"download_speed":%.2f}`,
|
||||||
|
s.Network.BytesSent,
|
||||||
|
s.Network.BytesRecv,
|
||||||
|
s.Network.UploadSpeed,
|
||||||
|
s.Network.DownloadSpeed,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
b = append(b, "null"...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sensors
|
||||||
|
b = append(b, `,"sensors":`...)
|
||||||
|
if len(s.Sensors) > 0 {
|
||||||
|
b = append(b, '{')
|
||||||
|
first := true
|
||||||
|
for _, sensor := range s.Sensors {
|
||||||
|
if !first {
|
||||||
|
b = append(b, ',')
|
||||||
|
}
|
||||||
|
b = fmt.Appendf(b,
|
||||||
|
`"%s":{"name":"%s","temperature":%.2f,"high":%.2f,"critical":%.2f}`,
|
||||||
|
sensor.SensorKey,
|
||||||
|
sensor.SensorKey,
|
||||||
|
sensor.Temperature,
|
||||||
|
sensor.High,
|
||||||
|
sensor.Critical,
|
||||||
|
)
|
||||||
|
first = false
|
||||||
|
}
|
||||||
|
b = append(b, '}')
|
||||||
|
} else {
|
||||||
|
b = append(b, "null"...)
|
||||||
|
}
|
||||||
|
|
||||||
|
b = append(b, '}')
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Sensors) UnmarshalJSON(data []byte) error {
|
||||||
|
var v map[string]map[string]any
|
||||||
|
if err := json.Unmarshal(data, &v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(v) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
*s = make(Sensors, 0, len(v))
|
||||||
|
for k, v := range v {
|
||||||
|
*s = append(*s, sensors.TemperatureStat{
|
||||||
|
SensorKey: k,
|
||||||
|
Temperature: v["temperature"].(float64),
|
||||||
|
High: v["high"].(float64),
|
||||||
|
Critical: v["critical"].(float64),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// recharts friendly
|
||||||
func aggregate(entries []*SystemInfo, query url.Values) (total int, result Aggregated) {
|
func aggregate(entries []*SystemInfo, query url.Values) (total int, result Aggregated) {
|
||||||
n := len(entries)
|
n := len(entries)
|
||||||
aggregated := make(Aggregated, 0, n)
|
aggregated := make(Aggregated, 0, n)
|
||||||
|
@ -342,3 +476,44 @@ func aggregate(entries []*SystemInfo, query url.Values) (total int, result Aggre
|
||||||
}
|
}
|
||||||
return len(aggregated), aggregated
|
return len(aggregated), aggregated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (result Aggregated) MarshalJSON() ([]byte, error) {
|
||||||
|
buf := bufPool.Get()
|
||||||
|
defer bufPool.Put(buf)
|
||||||
|
|
||||||
|
buf = append(buf, '[')
|
||||||
|
i := 0
|
||||||
|
n := len(result)
|
||||||
|
for _, entry := range result {
|
||||||
|
buf = append(buf, '{')
|
||||||
|
j := 0
|
||||||
|
m := len(entry)
|
||||||
|
for k, v := range entry {
|
||||||
|
buf = append(buf, '"')
|
||||||
|
buf = append(buf, k...)
|
||||||
|
buf = append(buf, '"')
|
||||||
|
buf = append(buf, ':')
|
||||||
|
switch v := v.(type) {
|
||||||
|
case float64:
|
||||||
|
buf = strconv.AppendFloat(buf, v, 'f', 2, 64)
|
||||||
|
case uint64:
|
||||||
|
buf = strconv.AppendUint(buf, v, 10)
|
||||||
|
case int64:
|
||||||
|
buf = strconv.AppendInt(buf, v, 10)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unexpected type: %T", v))
|
||||||
|
}
|
||||||
|
if j != m-1 {
|
||||||
|
buf = append(buf, ',')
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
buf = append(buf, '}')
|
||||||
|
if i != n-1 {
|
||||||
|
buf = append(buf, ',')
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
buf = append(buf, ']')
|
||||||
|
return buf, nil
|
||||||
|
}
|
||||||
|
|
|
@ -301,14 +301,14 @@ func (p *ReverseProxy) handler(rw http.ResponseWriter, req *http.Request) {
|
||||||
prior, ok := outreq.Header[httpheaders.HeaderXForwardedFor]
|
prior, ok := outreq.Header[httpheaders.HeaderXForwardedFor]
|
||||||
omit := ok && prior == nil // Issue 38079: nil now means don't populate the header
|
omit := ok && prior == nil // Issue 38079: nil now means don't populate the header
|
||||||
|
|
||||||
|
xff, _, err := net.SplitHostPort(req.RemoteAddr)
|
||||||
|
if err != nil {
|
||||||
|
xff = req.RemoteAddr
|
||||||
|
}
|
||||||
|
if len(prior) > 0 {
|
||||||
|
xff = strings.Join(prior, ", ") + ", " + xff
|
||||||
|
}
|
||||||
if !omit {
|
if !omit {
|
||||||
xff, _, err := net.SplitHostPort(req.RemoteAddr)
|
|
||||||
if err != nil {
|
|
||||||
xff = req.RemoteAddr
|
|
||||||
}
|
|
||||||
if len(prior) > 0 {
|
|
||||||
xff = strings.Join(prior, ", ") + ", " + xff
|
|
||||||
}
|
|
||||||
outreq.Header.Set(httpheaders.HeaderXForwardedFor, xff)
|
outreq.Header.Set(httpheaders.HeaderXForwardedFor, xff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,6 @@ func NewServer(opt Options) (s *Server) {
|
||||||
Handler: opt.Handler,
|
Handler: opt.Handler,
|
||||||
TLSConfig: &tls.Config{
|
TLSConfig: &tls.Config{
|
||||||
GetCertificate: opt.CertProvider.GetCert,
|
GetCertificate: opt.CertProvider.GetCert,
|
||||||
MinVersion: tls.VersionTLS12,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +169,7 @@ func stop[Server httpServer](srv Server, logger *zerolog.Logger) {
|
||||||
|
|
||||||
proto := proto(srv)
|
proto := proto(srv)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(task.RootContext(), 1*time.Second)
|
ctx, cancel := context.WithTimeout(task.RootContext(), 3*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if err := srv.Shutdown(ctx); err != nil {
|
if err := srv.Shutdown(ctx); err != nil {
|
||||||
|
|
|
@ -1,210 +0,0 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Modified from bufio.Writer by yusing <yusing@6uo.me>.
|
|
||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
// buffered output
|
|
||||||
|
|
||||||
// BufferedWriter implements buffering for an [io.BufferedWriter] object.
|
|
||||||
// If an error occurs writing to a [BufferedWriter], no more data will be
|
|
||||||
// accepted and all subsequent writes, and [BufferedWriter.Flush], will return the error.
|
|
||||||
// After all data has been written, the client should call the
|
|
||||||
// [BufferedWriter.Flush] method to guarantee all data has been forwarded to
|
|
||||||
// the underlying [io.BufferedWriter].
|
|
||||||
type BufferedWriter struct {
|
|
||||||
err error
|
|
||||||
buf []byte
|
|
||||||
n int
|
|
||||||
wr io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBufferedWriter returns a new [BufferedWriter] whose buffer has at least the specified
|
|
||||||
// size. If the argument io.Writer is already a [BufferedWriter] with large enough
|
|
||||||
// size, it returns the underlying [BufferedWriter].
|
|
||||||
func NewBufferedWriter(w io.Writer, size int) *BufferedWriter {
|
|
||||||
// Is it already a Writer?
|
|
||||||
b, ok := w.(*BufferedWriter)
|
|
||||||
if ok && len(b.buf) >= size {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
return &BufferedWriter{
|
|
||||||
buf: bytesPool.GetSized(size),
|
|
||||||
wr: w,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns the size of the underlying buffer in bytes.
|
|
||||||
func (b *BufferedWriter) Size() int { return len(b.buf) }
|
|
||||||
|
|
||||||
func (b *BufferedWriter) Resize(size int) error {
|
|
||||||
err := b.Flush()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if cap(b.buf) >= size {
|
|
||||||
b.buf = b.buf[:size]
|
|
||||||
} else {
|
|
||||||
b.Release()
|
|
||||||
b.buf = bytesPool.GetSized(size)
|
|
||||||
}
|
|
||||||
b.err = nil
|
|
||||||
b.n = 0
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BufferedWriter) Release() {
|
|
||||||
bytesPool.Put(b.buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush writes any buffered data to the underlying [io.Writer].
|
|
||||||
func (b *BufferedWriter) Flush() error {
|
|
||||||
if b.err != nil {
|
|
||||||
return b.err
|
|
||||||
}
|
|
||||||
if b.n == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
n, err := b.wr.Write(b.buf[0:b.n])
|
|
||||||
if n < b.n && err == nil {
|
|
||||||
err = io.ErrShortWrite
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
if n > 0 && n < b.n {
|
|
||||||
copy(b.buf[0:b.n-n], b.buf[n:b.n])
|
|
||||||
}
|
|
||||||
b.n -= n
|
|
||||||
b.err = err
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b.n = 0
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Available returns how many bytes are unused in the buffer.
|
|
||||||
func (b *BufferedWriter) Available() int { return len(b.buf) - b.n }
|
|
||||||
|
|
||||||
// AvailableBuffer returns an empty buffer with b.Available() capacity.
|
|
||||||
// This buffer is intended to be appended to and
|
|
||||||
// passed to an immediately succeeding [BufferedWriter.Write] call.
|
|
||||||
// The buffer is only valid until the next write operation on b.
|
|
||||||
func (b *BufferedWriter) AvailableBuffer() []byte {
|
|
||||||
return b.buf[b.n:][:0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buffered returns the number of bytes that have been written into the current buffer.
|
|
||||||
func (b *BufferedWriter) Buffered() int { return b.n }
|
|
||||||
|
|
||||||
// Write writes the contents of p into the buffer.
|
|
||||||
// It returns the number of bytes written.
|
|
||||||
// If nn < len(p), it also returns an error explaining
|
|
||||||
// why the write is short.
|
|
||||||
func (b *BufferedWriter) Write(p []byte) (nn int, err error) {
|
|
||||||
for len(p) > b.Available() && b.err == nil {
|
|
||||||
var n int
|
|
||||||
if b.Buffered() == 0 {
|
|
||||||
// Large write, empty buffer.
|
|
||||||
// Write directly from p to avoid copy.
|
|
||||||
n, b.err = b.wr.Write(p)
|
|
||||||
} else {
|
|
||||||
n = copy(b.buf[b.n:], p)
|
|
||||||
b.n += n
|
|
||||||
b.Flush()
|
|
||||||
}
|
|
||||||
nn += n
|
|
||||||
p = p[n:]
|
|
||||||
}
|
|
||||||
if b.err != nil {
|
|
||||||
return nn, b.err
|
|
||||||
}
|
|
||||||
n := copy(b.buf[b.n:], p)
|
|
||||||
b.n += n
|
|
||||||
nn += n
|
|
||||||
return nn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteByte writes a single byte.
|
|
||||||
func (b *BufferedWriter) WriteByte(c byte) error {
|
|
||||||
if b.err != nil {
|
|
||||||
return b.err
|
|
||||||
}
|
|
||||||
if b.Available() <= 0 && b.Flush() != nil {
|
|
||||||
return b.err
|
|
||||||
}
|
|
||||||
b.buf[b.n] = c
|
|
||||||
b.n++
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteRune writes a single Unicode code point, returning
|
|
||||||
// the number of bytes written and any error.
|
|
||||||
func (b *BufferedWriter) WriteRune(r rune) (size int, err error) {
|
|
||||||
// Compare as uint32 to correctly handle negative runes.
|
|
||||||
if uint32(r) < utf8.RuneSelf {
|
|
||||||
err = b.WriteByte(byte(r))
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return 1, nil
|
|
||||||
}
|
|
||||||
if b.err != nil {
|
|
||||||
return 0, b.err
|
|
||||||
}
|
|
||||||
n := b.Available()
|
|
||||||
if n < utf8.UTFMax {
|
|
||||||
if b.Flush(); b.err != nil {
|
|
||||||
return 0, b.err
|
|
||||||
}
|
|
||||||
n = b.Available()
|
|
||||||
if n < utf8.UTFMax {
|
|
||||||
// Can only happen if buffer is silly small.
|
|
||||||
return b.WriteString(string(r))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size = utf8.EncodeRune(b.buf[b.n:], r)
|
|
||||||
b.n += size
|
|
||||||
return size, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteString writes a string.
|
|
||||||
// It returns the number of bytes written.
|
|
||||||
// If the count is less than len(s), it also returns an error explaining
|
|
||||||
// why the write is short.
|
|
||||||
func (b *BufferedWriter) WriteString(s string) (int, error) {
|
|
||||||
var sw io.StringWriter
|
|
||||||
tryStringWriter := true
|
|
||||||
|
|
||||||
nn := 0
|
|
||||||
for len(s) > b.Available() && b.err == nil {
|
|
||||||
var n int
|
|
||||||
if b.Buffered() == 0 && sw == nil && tryStringWriter {
|
|
||||||
// Check at most once whether b.wr is a StringWriter.
|
|
||||||
sw, tryStringWriter = b.wr.(io.StringWriter)
|
|
||||||
}
|
|
||||||
if b.Buffered() == 0 && tryStringWriter {
|
|
||||||
// Large write, empty buffer, and the underlying writer supports
|
|
||||||
// WriteString: forward the write to the underlying StringWriter.
|
|
||||||
// This avoids an extra copy.
|
|
||||||
n, b.err = sw.WriteString(s)
|
|
||||||
} else {
|
|
||||||
n = copy(b.buf[b.n:], s)
|
|
||||||
b.n += n
|
|
||||||
b.Flush()
|
|
||||||
}
|
|
||||||
nn += n
|
|
||||||
s = s[n:]
|
|
||||||
}
|
|
||||||
if b.err != nil {
|
|
||||||
return nn, b.err
|
|
||||||
}
|
|
||||||
n := copy(b.buf[b.n:], s)
|
|
||||||
b.n += n
|
|
||||||
nn += n
|
|
||||||
return nn, nil
|
|
||||||
}
|
|
|
@ -4,17 +4,17 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/puzpuzpuz/xsync/v4"
|
"github.com/puzpuzpuz/xsync/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Map[KT comparable, VT any] struct {
|
type Map[KT comparable, VT any] struct {
|
||||||
*xsync.Map[KT, VT]
|
*xsync.MapOf[KT, VT]
|
||||||
}
|
}
|
||||||
|
|
||||||
const minParallelSize = 4
|
const minParallelSize = 4
|
||||||
|
|
||||||
func NewMapOf[KT comparable, VT any](options ...func(*xsync.MapConfig)) Map[KT, VT] {
|
func NewMapOf[KT comparable, VT any](options ...func(*xsync.MapConfig)) Map[KT, VT] {
|
||||||
return Map[KT, VT]{xsync.NewMap[KT, VT](options...)}
|
return Map[KT, VT]{xsync.NewMapOf[KT, VT](options...)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMapFrom[KT comparable, VT any](m map[KT]VT) (res Map[KT, VT]) {
|
func NewMapFrom[KT comparable, VT any](m map[KT]VT) (res Map[KT, VT]) {
|
||||||
|
|
|
@ -3,15 +3,15 @@ package functional
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/puzpuzpuz/xsync/v4"
|
"github.com/puzpuzpuz/xsync/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Set[T comparable] struct {
|
type Set[T comparable] struct {
|
||||||
m *xsync.Map[T, struct{}]
|
m *xsync.MapOf[T, struct{}]
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSet[T comparable]() Set[T] {
|
func NewSet[T comparable]() Set[T] {
|
||||||
return Set[T]{m: xsync.NewMap[T, struct{}]()}
|
return Set[T]{m: xsync.NewMapOf[T, struct{}]()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (set Set[T]) Add(v T) {
|
func (set Set[T]) Add(v T) {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/yusing/go-proxy/internal/gperr"
|
"github.com/yusing/go-proxy/internal/gperr"
|
||||||
"github.com/yusing/go-proxy/internal/utils/synk"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: move to "utils/io".
|
// TODO: move to "utils/io".
|
||||||
|
@ -111,24 +110,31 @@ type httpFlusher interface {
|
||||||
Flush() error
|
Flush() error
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHTTPFlusher(dst io.Writer) httpFlusher {
|
func getHttpFlusher(dst io.Writer) httpFlusher {
|
||||||
if rw, ok := dst.(http.ResponseWriter); ok {
|
if rw, ok := dst.(http.ResponseWriter); ok {
|
||||||
return http.NewResponseController(rw)
|
return http.NewResponseController(rw)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const copyBufSize = 32 * 1024
|
const (
|
||||||
|
copyBufSize = 32 * 1024
|
||||||
|
)
|
||||||
|
|
||||||
var bytesPool = synk.NewBytesPool()
|
var copyBufPool = sync.Pool{
|
||||||
|
New: func() any {
|
||||||
|
return make([]byte, copyBufSize)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// This is a copy of io.Copy with context and HTTP flusher handling
|
// This is a copy of io.Copy with context and HTTP flusher handling
|
||||||
// Author: yusing <yusing@6uo.me>.
|
// Author: yusing <yusing@6uo.me>.
|
||||||
func CopyClose(dst *ContextWriter, src *ContextReader) (err error) {
|
func CopyClose(dst *ContextWriter, src *ContextReader) (err error) {
|
||||||
size := copyBufSize
|
var buf []byte
|
||||||
if l, ok := src.Reader.(*io.LimitedReader); ok {
|
if l, ok := src.Reader.(*io.LimitedReader); ok {
|
||||||
|
size := copyBufSize
|
||||||
if int64(size) > l.N {
|
if int64(size) > l.N {
|
||||||
if l.N < 1 {
|
if l.N < 1 {
|
||||||
size = 1
|
size = 1
|
||||||
|
@ -136,9 +142,11 @@ func CopyClose(dst *ContextWriter, src *ContextReader) (err error) {
|
||||||
size = int(l.N)
|
size = int(l.N)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
buf = make([]byte, 0, size)
|
||||||
|
} else {
|
||||||
|
buf = copyBufPool.Get().([]byte)
|
||||||
|
defer copyBufPool.Put(buf)
|
||||||
}
|
}
|
||||||
buf := bytesPool.GetSized(size)
|
|
||||||
defer bytesPool.Put(buf)
|
|
||||||
// close both as soon as one of them is done
|
// close both as soon as one of them is done
|
||||||
wCloser, wCanClose := dst.Writer.(io.Closer)
|
wCloser, wCanClose := dst.Writer.(io.Closer)
|
||||||
rCloser, rCanClose := src.Reader.(io.Closer)
|
rCloser, rCanClose := src.Reader.(io.Closer)
|
||||||
|
@ -168,10 +176,10 @@ func CopyClose(dst *ContextWriter, src *ContextReader) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flusher := getHTTPFlusher(dst.Writer)
|
flusher := getHttpFlusher(dst.Writer)
|
||||||
canFlush := flusher != nil
|
canFlush := flusher != nil
|
||||||
for {
|
for {
|
||||||
nr, er := src.Reader.Read(buf)
|
nr, er := src.Reader.Read(buf[:copyBufSize])
|
||||||
if nr > 0 {
|
if nr > 0 {
|
||||||
nw, ew := dst.Writer.Write(buf[0:nr])
|
nw, ew := dst.Writer.Write(buf[0:nr])
|
||||||
if nw < 0 || nr < nw {
|
if nw < 0 || nr < nw {
|
||||||
|
|
|
@ -3,13 +3,13 @@ package pool
|
||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/puzpuzpuz/xsync/v4"
|
"github.com/puzpuzpuz/xsync/v3"
|
||||||
"github.com/yusing/go-proxy/internal/logging"
|
"github.com/yusing/go-proxy/internal/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Pool[T Object] struct {
|
Pool[T Object] struct {
|
||||||
m *xsync.Map[string, T]
|
m *xsync.MapOf[string, T]
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
Object interface {
|
Object interface {
|
||||||
|
@ -19,7 +19,7 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
func New[T Object](name string) Pool[T] {
|
func New[T Object](name string) Pool[T] {
|
||||||
return Pool[T]{xsync.NewMap[string, T](), name}
|
return Pool[T]{xsync.NewMapOf[string, T](), name}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Pool[T]) Name() string {
|
func (p Pool[T]) Name() string {
|
||||||
|
|
|
@ -256,7 +256,7 @@ func mapUnmarshalValidate(src SerializedObject, dst any, checkValidateTag bool)
|
||||||
if field, ok := mapping[strutils.ToLowerNoSnake(k)]; ok {
|
if field, ok := mapping[strutils.ToLowerNoSnake(k)]; ok {
|
||||||
err := Convert(reflect.ValueOf(v), field, !hasValidateTag)
|
err := Convert(reflect.ValueOf(v), field, !hasValidateTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs.Add(err.Subject(k))
|
errs.Add(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errs.Add(ErrUnknownField.Subject(k).With(gperr.DoYouMean(NearestField(k, mapping))))
|
errs.Add(ErrUnknownField.Subject(k).With(gperr.DoYouMean(NearestField(k, mapping))))
|
||||||
|
@ -314,26 +314,12 @@ func Convert(src reflect.Value, dst reflect.Value, checkValidateTag bool) gperr.
|
||||||
return gperr.Errorf("convert: dst is %w", ErrNilValue)
|
return gperr.Errorf("convert: dst is %w", ErrNilValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src.Kind() == reflect.Pointer && src.IsNil()) || !src.IsValid() {
|
if !src.IsValid() || src.IsZero() {
|
||||||
if !dst.CanSet() {
|
if dst.CanSet() {
|
||||||
return gperr.Errorf("convert: src is %w", ErrNilValue)
|
|
||||||
}
|
|
||||||
// manually set nil
|
|
||||||
dst.Set(reflect.Zero(dst.Type()))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if src.IsZero() {
|
|
||||||
if !dst.CanSet() {
|
|
||||||
return gperr.Errorf("convert: src is %w", ErrNilValue)
|
|
||||||
}
|
|
||||||
switch dst.Kind() {
|
|
||||||
case reflect.Pointer, reflect.Interface:
|
|
||||||
dst.Set(reflect.New(dst.Type().Elem()))
|
|
||||||
default:
|
|
||||||
dst.Set(reflect.Zero(dst.Type()))
|
dst.Set(reflect.Zero(dst.Type()))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return nil
|
return gperr.Errorf("convert: src is %w", ErrNilValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
srcT := src.Type()
|
srcT := src.Type()
|
||||||
|
@ -344,6 +330,10 @@ func Convert(src reflect.Value, dst reflect.Value, checkValidateTag bool) gperr.
|
||||||
srcT = src.Type()
|
srcT = src.Type()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !dst.CanSet() {
|
||||||
|
return ErrUnsettable.Subject(dstT.String())
|
||||||
|
}
|
||||||
|
|
||||||
if dst.Kind() == reflect.Pointer {
|
if dst.Kind() == reflect.Pointer {
|
||||||
if dst.IsNil() {
|
if dst.IsNil() {
|
||||||
dst.Set(New(dstT.Elem()))
|
dst.Set(New(dstT.Elem()))
|
||||||
|
@ -356,25 +346,16 @@ func Convert(src reflect.Value, dst reflect.Value, checkValidateTag bool) gperr.
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case srcT.AssignableTo(dstT):
|
case srcT.AssignableTo(dstT):
|
||||||
if !dst.CanSet() {
|
|
||||||
return ErrUnsettable.Subject(dstT.String())
|
|
||||||
}
|
|
||||||
dst.Set(src)
|
dst.Set(src)
|
||||||
return nil
|
return nil
|
||||||
// case srcT.ConvertibleTo(dstT):
|
// case srcT.ConvertibleTo(dstT):
|
||||||
// dst.Set(src.Convert(dstT))
|
// dst.Set(src.Convert(dstT))
|
||||||
// return nil
|
// return nil
|
||||||
case srcKind == reflect.String:
|
case srcKind == reflect.String:
|
||||||
if !dst.CanSet() {
|
|
||||||
return ErrUnsettable.Subject(dstT.String())
|
|
||||||
}
|
|
||||||
if convertible, err := ConvertString(src.String(), dst); convertible {
|
if convertible, err := ConvertString(src.String(), dst); convertible {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case isIntFloat(srcKind):
|
case isIntFloat(srcKind):
|
||||||
if !dst.CanSet() {
|
|
||||||
return ErrUnsettable.Subject(dstT.String())
|
|
||||||
}
|
|
||||||
var strV string
|
var strV string
|
||||||
switch {
|
switch {
|
||||||
case src.CanInt():
|
case src.CanInt():
|
||||||
|
@ -405,7 +386,7 @@ func Convert(src reflect.Value, dst reflect.Value, checkValidateTag bool) gperr.
|
||||||
if dstT.Kind() != reflect.Slice {
|
if dstT.Kind() != reflect.Slice {
|
||||||
return ErrUnsupportedConversion.Subject(dstT.String() + " to " + srcT.String())
|
return ErrUnsupportedConversion.Subject(dstT.String() + " to " + srcT.String())
|
||||||
}
|
}
|
||||||
sliceErrs := gperr.NewBuilder()
|
sliceErrs := gperr.NewBuilder("slice conversion errors")
|
||||||
newSlice := reflect.MakeSlice(dstT, src.Len(), src.Len())
|
newSlice := reflect.MakeSlice(dstT, src.Len(), src.Len())
|
||||||
i := 0
|
i := 0
|
||||||
for j, v := range src.Seq2() {
|
for j, v := range src.Seq2() {
|
||||||
|
@ -488,7 +469,7 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe
|
||||||
if !isMultiline && src[0] != '-' {
|
if !isMultiline && src[0] != '-' {
|
||||||
values := strutils.CommaSeperatedList(src)
|
values := strutils.CommaSeperatedList(src)
|
||||||
dst.Set(reflect.MakeSlice(dst.Type(), len(values), len(values)))
|
dst.Set(reflect.MakeSlice(dst.Type(), len(values), len(values)))
|
||||||
errs := gperr.NewBuilder()
|
errs := gperr.NewBuilder("invalid slice values")
|
||||||
for i, v := range values {
|
for i, v := range values {
|
||||||
err := Convert(reflect.ValueOf(v), dst.Index(i), true)
|
err := Convert(reflect.ValueOf(v), dst.Index(i), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -73,61 +73,6 @@ func TestDeserializeAnonymousField(t *testing.T) {
|
||||||
ExpectEqual(t, s2.C, 3)
|
ExpectEqual(t, s2.C, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPointerPrimitives(t *testing.T) {
|
|
||||||
type testType struct {
|
|
||||||
B *bool `json:"b"`
|
|
||||||
I8 *int8 `json:"i8"`
|
|
||||||
I16 *int16 `json:"i16"`
|
|
||||||
I32 *int32 `json:"i32"`
|
|
||||||
I64 *int64 `json:"i64"`
|
|
||||||
U8 *uint8 `json:"u8"`
|
|
||||||
U16 *uint16 `json:"u16"`
|
|
||||||
U32 *uint32 `json:"u32"`
|
|
||||||
U64 *uint64 `json:"u64"`
|
|
||||||
}
|
|
||||||
var test testType
|
|
||||||
|
|
||||||
err := MapUnmarshalValidate(map[string]any{"b": true, "i8": int8(127), "i16": int16(127), "i32": int32(127), "i64": int64(127), "u8": uint8(127), "u16": uint16(127), "u32": uint32(127), "u64": uint64(127)}, &test)
|
|
||||||
ExpectNoError(t, err)
|
|
||||||
ExpectEqual(t, *test.B, true)
|
|
||||||
ExpectEqual(t, *test.I8, int8(127))
|
|
||||||
ExpectEqual(t, *test.I16, int16(127))
|
|
||||||
ExpectEqual(t, *test.I32, int32(127))
|
|
||||||
ExpectEqual(t, *test.I64, int64(127))
|
|
||||||
ExpectEqual(t, *test.U8, uint8(127))
|
|
||||||
ExpectEqual(t, *test.U16, uint16(127))
|
|
||||||
ExpectEqual(t, *test.U32, uint32(127))
|
|
||||||
ExpectEqual(t, *test.U64, uint64(127))
|
|
||||||
|
|
||||||
// zero values
|
|
||||||
err = MapUnmarshalValidate(map[string]any{"b": false, "i8": int8(0), "i16": int16(0), "i32": int32(0), "i64": int64(0), "u8": uint8(0), "u16": uint16(0), "u32": uint32(0), "u64": uint64(0)}, &test)
|
|
||||||
ExpectNoError(t, err)
|
|
||||||
ExpectEqual(t, *test.B, false)
|
|
||||||
ExpectEqual(t, *test.I8, int8(0))
|
|
||||||
ExpectEqual(t, *test.I16, int16(0))
|
|
||||||
ExpectEqual(t, *test.I32, int32(0))
|
|
||||||
ExpectEqual(t, *test.I64, int64(0))
|
|
||||||
ExpectEqual(t, *test.U8, uint8(0))
|
|
||||||
ExpectEqual(t, *test.U16, uint16(0))
|
|
||||||
ExpectEqual(t, *test.U32, uint32(0))
|
|
||||||
ExpectEqual(t, *test.U64, uint64(0))
|
|
||||||
|
|
||||||
// nil values
|
|
||||||
err = MapUnmarshalValidate(map[string]any{"b": true, "i8": int8(127), "i16": int16(127), "i32": int32(127), "i64": int64(127), "u8": uint8(127), "u16": uint16(127), "u32": uint32(127), "u64": uint64(127)}, &test)
|
|
||||||
ExpectNoError(t, err)
|
|
||||||
err = MapUnmarshalValidate(map[string]any{"b": nil, "i8": nil, "i16": nil, "i32": nil, "i64": nil, "u8": nil, "u16": nil, "u32": nil, "u64": nil}, &test)
|
|
||||||
ExpectNoError(t, err)
|
|
||||||
ExpectEqual(t, test.B, nil)
|
|
||||||
ExpectEqual(t, test.I8, nil)
|
|
||||||
ExpectEqual(t, test.I16, nil)
|
|
||||||
ExpectEqual(t, test.I32, nil)
|
|
||||||
ExpectEqual(t, test.I64, nil)
|
|
||||||
ExpectEqual(t, test.U8, nil)
|
|
||||||
ExpectEqual(t, test.U16, nil)
|
|
||||||
ExpectEqual(t, test.U32, nil)
|
|
||||||
ExpectEqual(t, test.U64, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStringIntConvert(t *testing.T) {
|
func TestStringIntConvert(t *testing.T) {
|
||||||
s := "127"
|
s := "127"
|
||||||
|
|
||||||
|
|
|
@ -1,48 +1,42 @@
|
||||||
package synk
|
package synk
|
||||||
|
|
||||||
import (
|
import "sync"
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// Pool is a wrapper of sync.Pool that limits the size of the object.
|
// Pool is a wrapper of sync.Pool that limits the size of the object.
|
||||||
Pool[T any] struct {
|
Pool[T any] struct {
|
||||||
pool *sync.Pool
|
pool sync.Pool
|
||||||
|
maxSize int
|
||||||
}
|
}
|
||||||
BytesPool = Pool[byte]
|
BytesPool = Pool[byte]
|
||||||
)
|
)
|
||||||
|
|
||||||
const DefaultInitBytes = 32 * 1024
|
const (
|
||||||
|
DefaultInitBytes = 1024
|
||||||
|
DefaultMaxBytes = 1024 * 1024
|
||||||
|
)
|
||||||
|
|
||||||
func NewPool[T any](initSize int) *Pool[T] {
|
func NewPool[T any](initSize int, maxSize int) *Pool[T] {
|
||||||
return &Pool[T]{
|
return &Pool[T]{
|
||||||
pool: &sync.Pool{
|
pool: sync.Pool{
|
||||||
New: func() any {
|
New: func() any {
|
||||||
return make([]T, 0, initSize)
|
return make([]T, 0, initSize)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
maxSize: maxSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var bytesPool = NewPool[byte](DefaultInitBytes)
|
func NewBytesPool(initSize int, maxSize int) *BytesPool {
|
||||||
|
return NewPool[byte](initSize, maxSize)
|
||||||
func NewBytesPool() *BytesPool {
|
|
||||||
return bytesPool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pool[T]) Get() []T {
|
func (p *Pool[T]) Get() []T {
|
||||||
return p.pool.Get().([]T)
|
return p.pool.Get().([]T)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pool[T]) GetSized(size int) []T {
|
|
||||||
b := p.Get()
|
|
||||||
if cap(b) < size {
|
|
||||||
p.Put(b)
|
|
||||||
return make([]T, size)
|
|
||||||
}
|
|
||||||
return b[:size]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pool[T]) Put(b []T) {
|
func (p *Pool[T]) Put(b []T) {
|
||||||
p.pool.Put(b[:0]) //nolint:staticcheck
|
if cap(b) <= p.maxSize {
|
||||||
|
p.pool.Put(b[:0]) //nolint:staticcheck
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package trie
|
package trie
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/puzpuzpuz/xsync/v4"
|
"github.com/puzpuzpuz/xsync/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
key string
|
key string
|
||||||
children *xsync.Map[string, *Node] // lock-free map which allows concurrent access
|
children *xsync.MapOf[string, *Node] // lock-free map which allows concurrent access
|
||||||
value AnyValue // only end nodes have values
|
value AnyValue // only end nodes have values
|
||||||
}
|
}
|
||||||
|
|
||||||
func mayPrefix(key, part string) string {
|
func mayPrefix(key, part string) string {
|
||||||
|
@ -20,7 +20,7 @@ func mayPrefix(key, part string) string {
|
||||||
func (node *Node) newChild(part string) *Node {
|
func (node *Node) newChild(part string) *Node {
|
||||||
return &Node{
|
return &Node{
|
||||||
key: mayPrefix(node.key, part),
|
key: mayPrefix(node.key, part),
|
||||||
children: xsync.NewMap[string, *Node](),
|
children: xsync.NewMapOf[string, *Node](),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,16 +39,16 @@ func (node *Node) Get(key *Key) (any, bool) {
|
||||||
return v, true
|
return v, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *Node) loadOrStore(key *Key, newFunc func() any) (*Node, bool) {
|
func (node *Node) loadOrStore(key *Key, newFunc func() any) *Node {
|
||||||
for i, seg := range key.segments {
|
for i, seg := range key.segments {
|
||||||
child, _ := node.children.LoadOrCompute(seg, func() (*Node, bool) {
|
child, _ := node.children.LoadOrCompute(seg, func() *Node {
|
||||||
newNode := node.newChild(seg)
|
newNode := node.newChild(seg)
|
||||||
if i == len(key.segments)-1 {
|
if i == len(key.segments)-1 {
|
||||||
newNode.value.Store(newFunc())
|
newNode.value.Store(newFunc())
|
||||||
}
|
}
|
||||||
return newNode, false
|
return newNode
|
||||||
})
|
})
|
||||||
node = child
|
node = child
|
||||||
}
|
}
|
||||||
return node, false
|
return node
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
package trie
|
package trie
|
||||||
|
|
||||||
import "github.com/puzpuzpuz/xsync/v4"
|
import "github.com/puzpuzpuz/xsync/v3"
|
||||||
|
|
||||||
type Root struct {
|
type Root struct {
|
||||||
*Node
|
*Node
|
||||||
cached *xsync.Map[string, *Node]
|
cached *xsync.MapOf[string, *Node]
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTrie() *Root {
|
func NewTrie() *Root {
|
||||||
return &Root{
|
return &Root{
|
||||||
Node: &Node{
|
Node: &Node{
|
||||||
children: xsync.NewMap[string, *Node](),
|
children: xsync.NewMapOf[string, *Node](),
|
||||||
},
|
},
|
||||||
cached: xsync.NewMap[string, *Node](),
|
cached: xsync.NewMapOf[string, *Node](),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ func (r *Root) getNode(key *Key, newFunc func() any) *Node {
|
||||||
if key.hasWildcard {
|
if key.hasWildcard {
|
||||||
panic("should not call Load or Store on a key with any wildcard: " + key.full)
|
panic("should not call Load or Store on a key with any wildcard: " + key.full)
|
||||||
}
|
}
|
||||||
node, _ := r.cached.LoadOrCompute(key.full, func() (*Node, bool) {
|
node, _ := r.cached.LoadOrCompute(key.full, func() *Node {
|
||||||
return r.Node.loadOrStore(key, newFunc)
|
return r.Node.loadOrStore(key, newFunc)
|
||||||
})
|
})
|
||||||
return node
|
return node
|
||||||
|
|
|
@ -35,7 +35,7 @@ type (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNegativeInterval = gperr.New("negative interval")
|
var ErrNegativeInterval = errors.New("negative interval")
|
||||||
|
|
||||||
func NewMonitor(r routes.Route) health.HealthMonCheck {
|
func NewMonitor(r routes.Route) health.HealthMonCheck {
|
||||||
var mon health.HealthMonCheck
|
var mon health.HealthMonCheck
|
||||||
|
@ -84,7 +84,7 @@ func (mon *monitor) ContextWithTimeout(cause string) (ctx context.Context, cance
|
||||||
// Start implements task.TaskStarter.
|
// Start implements task.TaskStarter.
|
||||||
func (mon *monitor) Start(parent task.Parent) gperr.Error {
|
func (mon *monitor) Start(parent task.Parent) gperr.Error {
|
||||||
if mon.config.Interval <= 0 {
|
if mon.config.Interval <= 0 {
|
||||||
return ErrNegativeInterval
|
return gperr.Wrap(ErrNegativeInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
mon.service = parent.Name()
|
mon.service = parent.Name()
|
||||||
|
@ -100,11 +100,9 @@ func (mon *monitor) Start(parent task.Parent) gperr.Error {
|
||||||
mon.task.Finish(nil)
|
mon.task.Finish(nil)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
failures := 0
|
|
||||||
|
|
||||||
if err := mon.checkUpdateHealth(); err != nil {
|
if err := mon.checkUpdateHealth(); err != nil {
|
||||||
logger.Err(err).Msg("healthchecker error")
|
logger.Err(err).Msg("healthchecker failure")
|
||||||
failures++
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ticker := time.NewTicker(mon.config.Interval)
|
ticker := time.NewTicker(mon.config.Interval)
|
||||||
|
@ -117,15 +115,7 @@ func (mon *monitor) Start(parent task.Parent) gperr.Error {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
err := mon.checkUpdateHealth()
|
err := mon.checkUpdateHealth()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Err(err).Msg("healthchecker error")
|
logger.Err(err).Msg("healthchecker failure")
|
||||||
failures++
|
|
||||||
} else {
|
|
||||||
failures = 0
|
|
||||||
}
|
|
||||||
if failures >= 5 {
|
|
||||||
mon.status.Store(health.StatusError)
|
|
||||||
mon.task.Finish(err)
|
|
||||||
logger.Error().Msg("healthchecker stopped after 5 trials")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
COMMAND="$1"
|
|
||||||
|
|
||||||
check_pkg() {
|
check_pkg() {
|
||||||
if ! command -v "$1" &>/dev/null; then
|
if ! command -v "$1" &>/dev/null; then
|
||||||
echo "$1 could not be found, please install it first"
|
echo "$1 could not be found, please install it first"
|
||||||
|
@ -14,7 +12,7 @@ check_pkg() {
|
||||||
start-service() {
|
start-service() {
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
# if command is empty
|
# if command is empty
|
||||||
if [ -z "$COMMAND" ]; then
|
if [ -z "$1" ]; then
|
||||||
echo "Enabling and starting the agent service"
|
echo "Enabling and starting the agent service"
|
||||||
else
|
else
|
||||||
echo "Reloading the agent service"
|
echo "Reloading the agent service"
|
||||||
|
@ -31,7 +29,7 @@ start-service() {
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
# if command is empty
|
# if command is empty
|
||||||
if [ -z "$COMMAND" ]; then
|
if [ -z "$1" ]; then
|
||||||
echo "Agent installed successfully"
|
echo "Agent installed successfully"
|
||||||
else
|
else
|
||||||
echo "Agent updated successfully"
|
echo "Agent updated successfully"
|
||||||
|
@ -57,7 +55,7 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# check variables if command is empty
|
# check variables if command is empty
|
||||||
if [ -z "$COMMAND" ]; then
|
if [ -z "$1" ]; then
|
||||||
if [ -z "$AGENT_NAME" ]; then
|
if [ -z "$AGENT_NAME" ]; then
|
||||||
echo "AGENT_NAME is not set"
|
echo "AGENT_NAME is not set"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -115,7 +113,7 @@ if [ ! -w "$(dirname "$env_file")" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# check if command is uninstall
|
# check if command is uninstall
|
||||||
if [ "$COMMAND" = "uninstall" ]; then
|
if [ "$1" = "uninstall" ]; then
|
||||||
echo "Uninstalling the agent"
|
echo "Uninstalling the agent"
|
||||||
systemctl disable --now $name || true
|
systemctl disable --now $name || true
|
||||||
rm -f $bin_path
|
rm -f $bin_path
|
||||||
|
@ -141,17 +139,13 @@ bin_last_updated=$(date -d "$(echo "$asset" | jq -r '.updated_at')" +%s)
|
||||||
if [ -f "$bin_path" ]; then
|
if [ -f "$bin_path" ]; then
|
||||||
bin_mod_time=$(stat -c %Y "$bin_path")
|
bin_mod_time=$(stat -c %Y "$bin_path")
|
||||||
if [ "$bin_last_updated" -eq "$bin_mod_time" ]; then
|
if [ "$bin_last_updated" -eq "$bin_mod_time" ]; then
|
||||||
echo "Binary is already up to date, continue? (y/n)"
|
echo "Binary is up to date"
|
||||||
read -n 1 -r
|
exit 0
|
||||||
if [ "$REPLY" != "y" ] && [ "$REPLY" != "Y" ]; then
|
|
||||||
echo "Aborting"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# check if command is update
|
# check if command is update
|
||||||
if [ "$COMMAND" = "update" ]; then
|
if [ "$1" = "update" ]; then
|
||||||
echo "Stopping the agent"
|
echo "Stopping the agent"
|
||||||
systemctl stop $name || true
|
systemctl stop $name || true
|
||||||
fi
|
fi
|
||||||
|
@ -162,19 +156,6 @@ if [ -z "$bin_url" ] || [ "$bin_url" = "null" ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# check if agent is already running
|
|
||||||
if systemctl is-active $name &>/dev/null; then
|
|
||||||
echo "Agent is already running, stopping it"
|
|
||||||
systemctl stop $name || true
|
|
||||||
sleep 1
|
|
||||||
if systemctl is-active $name &>/dev/null; then
|
|
||||||
echo "Agent is still running, please stop it manually"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "Agent stopped successfully"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Downloading the agent binary from $bin_url"
|
echo "Downloading the agent binary from $bin_url"
|
||||||
if ! curl -L -f "$bin_url" -o $bin_path; then
|
if ! curl -L -f "$bin_url" -o $bin_path; then
|
||||||
echo "Failed to download binary"
|
echo "Failed to download binary"
|
||||||
|
@ -188,7 +169,7 @@ echo "Making the agent binary executable"
|
||||||
chmod +x $bin_path
|
chmod +x $bin_path
|
||||||
|
|
||||||
# check if command is update
|
# check if command is update
|
||||||
if [ "$COMMAND" = "update" ]; then
|
if [ "$1" = "update" ]; then
|
||||||
echo "Starting the agent"
|
echo "Starting the agent"
|
||||||
start-service
|
start-service
|
||||||
exit 0
|
exit 0
|
||||||
|
|
Loading…
Add table
Reference in a new issue