Compare commits

..

57 Commits

Author SHA1 Message Date
fatedier
d689f0fc53 Merge pull request #3968 from fatedier/dev
bump version
2024-02-01 14:29:17 +08:00
fatedier
d505ecb473 Merge pull request #3880 from fatedier/dev
fix login retry interval (#3879)
2023-12-21 21:42:47 +08:00
fatedier
2b83436a97 Merge pull request #3878 from fatedier/dev
bump version
2023-12-21 21:25:01 +08:00
fatedier
051299ec25 Merge pull request #3845 from fatedier/dev
bump version to v0.53.0
2023-12-14 20:58:11 +08:00
fatedier
44985f574d Merge pull request #3722 from fatedier/dev
bump version
2023-10-24 10:47:16 +08:00
fatedier
c9ca9353cf Merge pull request #3714 from fatedier/dev
bump version
2023-10-23 10:51:50 +08:00
fatedier
31fa3f021a Merge pull request #3668 from fatedier/dev
bump version to v0.52.1
2023-10-11 17:16:07 +08:00
fatedier
2d3af8a108 Merge pull request #3651 from fatedier/dev
bump version to v0.52.0
2023-10-10 17:24:07 +08:00
fatedier
466d69eae0 Merge pull request #3574 from fatedier/dev
release v0.51.3
2023-08-14 11:59:09 +08:00
fatedier
7c8cbeb250 Merge pull request #3550 from fatedier/dev
release v0.51.2
2023-07-25 21:35:08 +08:00
fatedier
4fd6301577 Merge pull request #3537 from fatedier/dev
release v0.51.1
2023-07-20 22:38:48 +08:00
fatedier
53626b370c Merge pull request #3517 from fatedier/dev
bump version to v0.51.0
2023-07-05 20:39:25 +08:00
fatedier
4fd800bc48 Merge pull request #3499 from fatedier/dev
release v0.50.0
2023-06-26 17:03:56 +08:00
fatedier
0d6d968fe8 Merge pull request #3454 from fatedier/dev
release v0.49.0
2023-05-29 01:12:26 +08:00
fatedier
8fb99ef7a9 Merge pull request #3348 from fatedier/dev
bump version
2023-03-08 11:40:31 +08:00
fatedier
88e74ff24d Merge pull request #3300 from fatedier/dev
sync
2023-02-10 01:12:00 +08:00
fatedier
534dc99d55 Merge pull request #3299 from fatedier/dev
sync
2023-02-09 23:06:14 +08:00
fatedier
595aba5a9b Merge pull request #3248 from fatedier/dev
bump version
2023-01-10 10:26:56 +08:00
fatedier
a4189ba474 Merge branch 'dev' 2022-12-18 19:27:22 +08:00
fatedier
9ec84f8143 Merge pull request #3218 from fatedier/dev
release v0.46.0
2022-12-18 18:46:52 +08:00
fatedier
8ab474cc97 remove unsupported platform (#3148) 2022-10-27 10:22:47 +08:00
fatedier
a301046f3d Merge pull request #3147 from fatedier/dev
bump version
2022-10-26 23:18:40 +08:00
fatedier
8888610d83 Merge pull request #3010 from fatedier/dev
release v0.44.0
2022-07-11 00:10:43 +08:00
fatedier
fe5fb0326b Merge pull request #2955 from fatedier/dev
bump version to v0.43.0
2022-05-27 16:27:19 +08:00
fatedier
eb1e19a821 Merge pull request #2906 from fatedier/dev
bump version
2022-04-22 11:32:27 +08:00
fatedier
10f2620131 Merge pull request #2869 from fatedier/dev
bump version to v0.41.0
2022-03-23 21:19:59 +08:00
fatedier
ce677820c6 Merge pull request #2834 from fatedier/dev
bump version
2022-03-11 19:51:32 +08:00
fatedier
88fcc079e8 Merge pull request #2792 from fatedier/dev
bump version
2022-02-09 16:11:20 +08:00
fatedier
2dab5d0bca Merge pull request #2782 from fatedier/dev
bump version
2022-01-26 20:17:54 +08:00
fatedier
143750901e Merge pull request #2638 from fatedier/dev
bump version to v0.38.0
2021-10-25 20:31:13 +08:00
fatedier
997d406ec2 Merge pull request #2508 from fatedier/dev
bump version
2021-08-03 23:13:31 +08:00
fatedier
cfd1a3128a Merge pull request #2426 from fatedier/dev
update workflow file
2021-06-03 00:59:21 +08:00
fatedier
57577ea044 Merge pull request #2425 from fatedier/dev
bump version
2021-06-03 00:14:32 +08:00
fatedier
c5c79e4148 Merge pull request #2324 from fatedier/dev
bump version v0.36.2
2021-03-22 14:56:48 +08:00
fatedier
55da58eca4 Merge pull request #2310 from fatedier/dev
bump version
2021-03-18 11:14:56 +08:00
fatedier
76a1efccd9 update 2021-03-17 11:43:23 +08:00
fatedier
980f084ad1 Merge pull request #2302 from fatedier/dev
bump version
2021-03-15 21:54:52 +08:00
fatedier
3bf1eb8565 Merge pull request #2216 from fatedier/dev
bump version
2021-01-25 16:15:52 +08:00
fatedier
b2ae433e18 Merge pull request #2206 from fatedier/dev
bump version
2021-01-19 20:56:06 +08:00
fatedier
aa0a41ee4e Merge pull request #2088 from fatedier/dev
bump version to v0.34.3
2020-11-20 17:04:55 +08:00
fatedier
1ea1530b36 Merge pull request #2058 from fatedier/dev
bump version to v0.34.2
2020-11-06 14:50:50 +08:00
fatedier
e0c45a1aca Merge pull request #2018 from fatedier/dev
bump version to v0.34.1
2020-09-30 15:13:08 +08:00
fatedier
813c45f5c2 Merge pull request #1993 from fatedier/dev
bump version to v0.34.0
2020-09-20 00:30:51 +08:00
fatedier
aa74dc4646 Merge pull request #1990 from fatedier/dev
bump version to v0.34.0
2020-09-20 00:10:32 +08:00
fatedier
2406ecdfea Merge pull request #1780 from fatedier/dev
bump version
2020-04-27 16:50:34 +08:00
fatedier
8668fef136 Merge pull request #1728 from fatedier/dev
bump version to v0.32.1
2020-04-03 01:14:58 +08:00
fatedier
ea62bc5a34 remove vendor (#1697) 2020-03-11 14:39:43 +08:00
fatedier
23bb76397a Merge pull request #1696 from fatedier/dev
bump version to v0.32.0
2020-03-11 14:30:47 +08:00
fatedier
487c8d7c29 Merge pull request #1637 from fatedier/dev
bump version to v0.31.2
2020-02-04 21:54:28 +08:00
fatedier
f480160e2d Merge pull request #1596 from fatedier/dev
v0.31.1, fix bugs
2020-01-06 15:55:44 +08:00
fatedier
30c246c488 Merge pull request #1588 from fatedier/dev
bump version to v0.31.0
2020-01-03 11:45:22 +08:00
fatedier
75f3bce04d Merge pull request #1542 from fatedier/dev
bump version to v0.30.0
2019-11-28 14:21:27 +08:00
fatedier
adc3adc13b Merge pull request #1494 from fatedier/dev
bump version to v0.29.1
2019-11-02 21:14:50 +08:00
fatedier
e62d9a5242 Merge pull request #1415 from fatedier/dev
bump version to v0.29.0
2019-08-29 21:22:30 +08:00
fatedier
134a46c00b Merge pull request #1369 from fatedier/dev
bump version to v0.28.2
2019-08-09 12:59:13 +08:00
fatedier
ae08811636 Merge pull request #1364 from fatedier/dev
bump version to v0.28.1 and remove support for go1.11
2019-08-08 17:32:57 +08:00
fatedier
6451583e60 Merge pull request #1349 from fatedier/dev
bump version to v0.28.0
2019-08-01 14:04:55 +08:00
62 changed files with 527 additions and 489 deletions

View File

@@ -2,7 +2,15 @@ version: 2
jobs:
go-version-latest:
docker:
- image: cimg/go:1.22-node
- image: cimg/go:1.21-node
resource_class: large
steps:
- checkout
- run: make
- run: make alltest
go-version-last:
docker:
- image: cimg/go:1.20-node
resource_class: large
steps:
- checkout
@@ -14,3 +22,4 @@ workflows:
build_and_test:
jobs:
- go-version-latest
- go-version-last

View File

@@ -19,15 +19,15 @@ jobs:
steps:
# environment
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: '0'
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v2
# get image tag name
- name: Get Image Tag Name
@@ -38,13 +38,13 @@ jobs:
echo "TAG_NAME=${{ github.event.inputs.tag }}" >> $GITHUB_ENV
fi
- name: Login to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Login to the GPR
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -72,7 +72,7 @@ jobs:
${{ env.TAG_FRPC_GPR }}
- name: Build and push frps
uses: docker/build-push-action@v5
uses: docker/build-push-action@v4
with:
context: .
file: ./dockerfiles/Dockerfile-for-frps

View File

@@ -14,16 +14,15 @@ jobs:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: actions/setup-go@v4
with:
go-version: '1.22'
cache: false
go-version: '1.21'
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v4
uses: golangci/golangci-lint-action@v3
with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
version: v1.56
version: v1.55
# Optional: golangci-lint command line arguments.
# args: --issues-exit-code=0

View File

@@ -8,21 +8,21 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
uses: actions/setup-go@v4
with:
go-version: '1.22'
go-version: '1.21'
- name: Make All
run: |
./package.sh
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
uses: goreleaser/goreleaser-action@v4
with:
version: latest
args: release --clean --release-notes=./Release.md

View File

@@ -1,5 +1,5 @@
service:
golangci-lint-version: 1.56.x # use the fixed version to not introduce new linters unexpectedly
golangci-lint-version: 1.55.x # use the fixed version to not introduce new linters unexpectedly
run:
concurrency: 4

View File

@@ -1,14 +1,11 @@
export PATH := $(PATH):`go env GOPATH`/bin
export PATH := $(GOPATH)/bin:$(PATH)
export GO111MODULE=on
LDFLAGS := -s -w
all: env fmt build
all: fmt build
build: frps frpc
env:
@go version
# compile assets into binary file
file:
rm -rf ./assets/frps/static/*

View File

@@ -2,8 +2,6 @@
[![Build Status](https://circleci.com/gh/fatedier/frp.svg?style=shield)](https://circleci.com/gh/fatedier/frp)
[![GitHub release](https://img.shields.io/github/tag/fatedier/frp.svg?label=release)](https://github.com/fatedier/frp/releases)
[![Go Report Card](https://goreportcard.com/badge/github.com/fatedier/frp)](https://goreportcard.com/report/github.com/fatedier/frp)
[![GitHub Releases Stats](https://img.shields.io/github/downloads/fatedier/frp/total.svg?logo=github)](https://somsubhra.github.io/github-release-stats/?username=fatedier&repository=frp)
[README](README.md) | [中文文档](README_zh.md)
@@ -13,6 +11,10 @@
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
<img width="350px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
</a>
<a>&nbsp</a>
<a href="https://www.nango.dev?utm_source=github&utm_medium=oss-banner&utm_campaign=fatedier-frp" target="_blank">
<img width="400px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_nango.png">
</a>
</p>
<!--gold sponsors end-->
@@ -199,11 +201,11 @@ This example implements multiple SSH services exposed through the same port usin
4. To access internal machine A using SSH ProxyCommand, assuming the username is "test":
`ssh -o 'proxycommand socat - PROXY:x.x.x.x:%h:%p,proxyport=5002' test@machine-a.example.com`
`ssh -o 'proxycommand socat - PROXY:x.x.x.x:machine-a.example.com:22,proxyport=5002' test@machine-a`
5. To access internal machine B, the only difference is the domain name, assuming the username is "test":
`ssh -o 'proxycommand socat - PROXY:x.x.x.x:%h:%p,proxyport=5002' test@machine-b.example.com`
`ssh -o 'proxycommand socat - PROXY:x.x.x.x:machine-b.example.com:22,proxyport=5002' test@machine-b`
### Accessing Internal Web Services with Custom Domains in LAN
@@ -524,8 +526,6 @@ Check frp's status and proxies' statistics information by Dashboard.
Configure a port for dashboard to enable this feature:
```toml
# The default value is 127.0.0.1. Change it to 0.0.0.0 when you want to access it from a public network.
webServer.addr = "0.0.0.0"
webServer.port = 7500
# dashboard's username and password are both optional
webServer.user = "admin"

View File

@@ -2,8 +2,6 @@
[![Build Status](https://circleci.com/gh/fatedier/frp.svg?style=shield)](https://circleci.com/gh/fatedier/frp)
[![GitHub release](https://img.shields.io/github/tag/fatedier/frp.svg?label=release)](https://github.com/fatedier/frp/releases)
[![Go Report Card](https://goreportcard.com/badge/github.com/fatedier/frp)](https://goreportcard.com/report/github.com/fatedier/frp)
[![GitHub Releases Stats](https://img.shields.io/github/downloads/fatedier/frp/total.svg?logo=github)](https://somsubhra.github.io/github-release-stats/?username=fatedier&repository=frp)
[README](README.md) | [中文文档](README_zh.md)
@@ -15,6 +13,10 @@ frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
<img width="350px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
</a>
<a>&nbsp</a>
<a href="https://www.nango.dev?utm_source=github&utm_medium=oss-banner&utm_campaign=fatedier-frp" target="_blank">
<img width="400px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_nango.png">
</a>
</p>
<!--gold sponsors end-->

View File

@@ -1,3 +1,11 @@
### Deprecation Notices
* Using an underscore in a flag name is deprecated and has been replaced by a hyphen. The underscore format will remain compatible for some time, until it is completely removed in a future version. For example, `--remote_port` is replaced with `--remote-port`.
### Features
* Proxy supports configuring annotations, which will be displayed in the frps dashboard.
* The `Refresh` and `ClearOfflineProxies` buttons have been added to the Dashboard of frps.
### Fixes
* The host/domain matching in the routing rules has been changed to be case-insensitive.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,8 +4,8 @@
<head>
<meta charset="utf-8">
<title>frps dashboard</title>
<script type="module" crossorigin src="./index-Q42Pu2_S.js"></script>
<link rel="stylesheet" crossorigin href="./index-rzPDshRD.css">
<script type="module" crossorigin src="./index-1gecbKzv.js"></script>
<link rel="stylesheet" crossorigin href="./index-Lf6B06jY.css">
</head>
<body>

View File

@@ -15,17 +15,19 @@
package client
import (
"cmp"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"os"
"slices"
"sort"
"strconv"
"strings"
"time"
"github.com/samber/lo"
"github.com/fatedier/frp/client/proxy"
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/config/v1/validation"
@@ -151,7 +153,7 @@ func NewProxyStatusResp(status *proxy.WorkingStatus, serverAddr string) ProxySta
if status.Err == "" {
psr.RemoteAddr = status.RemoteAddr
if slices.Contains([]string{"tcp", "udp"}, status.Type) {
if lo.Contains([]string{"tcp", "udp"}, status.Type) {
psr.RemoteAddr = serverAddr + psr.RemoteAddr
}
}
@@ -188,8 +190,8 @@ func (svr *Service) apiStatus(w http.ResponseWriter, _ *http.Request) {
if len(arrs) <= 1 {
continue
}
slices.SortFunc(arrs, func(a, b ProxyStatusResp) int {
return cmp.Compare(a.Name, b.Name)
sort.Slice(arrs, func(i, j int) bool {
return strings.Compare(arrs[i].Name, arrs[j].Name) < 0
})
}
}

View File

@@ -17,8 +17,8 @@ package sub
import (
"fmt"
"os"
"slices"
"github.com/samber/lo"
"github.com/spf13/cobra"
"github.com/fatedier/frp/pkg/config"
@@ -55,7 +55,7 @@ func init() {
config.RegisterProxyFlags(cmd, c)
// add sub command for visitor
if slices.Contains(visitorTypes, v1.VisitorType(typ)) {
if lo.Contains(visitorTypes, v1.VisitorType(typ)) {
vc := v1.NewVisitorConfigurerByType(v1.VisitorType(typ))
if vc == nil {
panic("visitor type: " + typ + " not support")

View File

@@ -164,16 +164,11 @@ healthCheck.type = "tcp"
healthCheck.timeoutSeconds = 3
# If continuous failed in 3 times, the proxy will be removed from frps
healthCheck.maxFailed = 3
# Every 10 seconds will do a health check
# every 10 seconds will do a health check
healthCheck.intervalSeconds = 10
# Additional meta info for each proxy. It will be passed to the server-side plugin for use.
# additional meta info for each proxy
metadatas.var1 = "abc"
metadatas.var2 = "123"
# You can add some extra information to the proxy through annotations.
# These annotations will be displayed on the frps dashboard.
[proxies.annotations]
key1 = "value1"
"prefix/key2" = "value2"
[[proxies]]
name = "ssh_random"

View File

@@ -1,4 +1,4 @@
FROM golang:1.22 AS building
FROM golang:1.21 AS building
COPY . /building
WORKDIR /building

View File

@@ -1,4 +1,4 @@
FROM golang:1.22 AS building
FROM golang:1.21 AS building
COPY . /building
WORKDIR /building

31
go.mod
View File

@@ -1,12 +1,13 @@
module github.com/fatedier/frp
go 1.22
go 1.20
require (
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
github.com/coreos/go-oidc/v3 v3.6.0
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb
github.com/fatedier/golib v0.3.0
github.com/fatedier/golib v0.1.1-0.20230725122706-dcbaee8eef40
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
@@ -14,19 +15,17 @@ require (
github.com/onsi/ginkgo/v2 v2.11.0
github.com/onsi/gomega v1.27.8
github.com/pelletier/go-toml/v2 v2.1.0
github.com/pion/stun/v2 v2.0.0
github.com/pion/stun v0.6.1
github.com/pires/go-proxyproto v0.7.0
github.com/prometheus/client_golang v1.16.0
github.com/quic-go/quic-go v0.41.0
github.com/quic-go/quic-go v0.37.7
github.com/rodaine/table v1.1.0
github.com/samber/lo v1.39.0
github.com/samber/lo v1.38.1
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4
github.com/tidwall/gjson v1.17.1
github.com/xtaci/kcp-go/v5 v5.6.7
golang.org/x/crypto v0.17.0
golang.org/x/net v0.19.0
golang.org/x/net v0.17.0
golang.org/x/oauth2 v0.10.0
golang.org/x/sync v0.3.0
golang.org/x/time v0.3.0
@@ -43,33 +42,31 @@ require (
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/klauspost/reedsolomon v1.12.0 // indirect
github.com/klauspost/cpuid/v2 v2.0.6 // indirect
github.com/klauspost/reedsolomon v1.9.15 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/pion/dtls/v2 v2.2.7 // indirect
github.com/pion/logging v0.2.2 // indirect
github.com/pion/transport/v2 v2.2.1 // indirect
github.com/pion/transport/v3 v3.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/quic-go/qtls-go1-20 v0.3.1 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/templexxx/cpu v0.1.0 // indirect
github.com/templexxx/xorsimd v0.4.2 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
go.uber.org/mock v0.3.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.9.3 // indirect

80
go.sum
View File

@@ -26,8 +26,10 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb h1:wCrNShQidLmvVWn/0PikGmpdP0vtQmnvyRg3ZBEhczw=
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb/go.mod h1:wx3gB6dbIfBRcucp94PI9Bt3I0F2c/MyNEWuhzpWiwk=
github.com/fatedier/golib v0.3.0 h1:xX0QQoYD1ns3IHVDTSysg6gL8buZvGaLyQFvBnWIRF4=
github.com/fatedier/golib v0.3.0/go.mod h1:pmX4FYyp6N4awxDB6jAgIDVOUWuH+QkVP4v30O+iJDM=
github.com/fatedier/golib v0.1.1-0.20230725122706-dcbaee8eef40 h1:BVdpWT6viE/mpuRa6txNyRNjtHa1Efrii9Du6/gHfJ0=
github.com/fatedier/golib v0.1.1-0.20230725122706-dcbaee8eef40/go.mod h1:Lmi9U4VfvdRvonSMh1FgXVy1hCXycVyJk4E9ktokknE=
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible h1:ssXat9YXFvigNge/IkkZvFMn8yeYKFX+uI6wn2mLJ74=
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible/go.mod h1:YpCOaxj7vvMThhIQ9AfTOPW2sfztQR5WDfs7AflSy4s=
github.com/fatedier/yamux v0.0.0-20230628132301-7aca4898904d h1:ynk1ra0RUqDWQfvFi5KtMiSobkVQ3cNc0ODb8CfIETo=
github.com/fatedier/yamux v0.0.0-20230628132301-7aca4898904d/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
@@ -38,6 +40,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -73,12 +77,11 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/reedsolomon v1.12.0 h1:I5FEp3xSwVCcEh3F5A7dofEfhXdF/bWhQWPH+XwBFno=
github.com/klauspost/reedsolomon v1.12.0/go.mod h1:EPLZJeh4l27pUGC3aXOjheaoh1I9yut7xTURiW3LQ9Y=
github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/reedsolomon v1.9.15 h1:g2erWKD2M6rgnPf89fCji6jNlhMKMdXcuNHMW1SYCIo=
github.com/klauspost/reedsolomon v1.9.15/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
@@ -95,12 +98,10 @@ github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8=
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0=
github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ=
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c=
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM=
github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0=
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -116,15 +117,17 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
github.com/quic-go/qtls-go1-20 v0.3.1 h1:O4BLOM3hwfVF3AcktIylQXyl7Yi2iBNVy5QsV+ySxbg=
github.com/quic-go/qtls-go1-20 v0.3.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/quic-go/quic-go v0.37.7 h1:AgKsQLZ1+YCwZd2GYhBUsJDYZwEkA5gENtAjb+MxONU=
github.com/quic-go/quic-go v0.37.7/go.mod h1:YsbH1r4mSHPJcLF4k4zruUkLBqctEMBDR6VPvcYjIsU=
github.com/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4=
github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -138,32 +141,22 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/templexxx/cpu v0.1.0 h1:wVM+WIJP2nYaxVxqgHPD4wGA2aJ9rvrQRV8CvFzNb40=
github.com/templexxx/cpu v0.1.0/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
github.com/templexxx/xorsimd v0.4.2 h1:ocZZ+Nvu65LGHmCLZ7OoCtg8Fx8jnHKK37SjvngUoVI=
github.com/templexxx/xorsimd v0.4.2/go.mod h1:HgwaPoDREdi6OnULpSfxhzaiiSUY4Fi3JPn1wpt28NI=
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU=
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI=
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
github.com/xtaci/kcp-go/v5 v5.6.7 h1:7+rnxNFIsjEwTXQk4cSZpXM4pO0hqtpwE1UFFoJBffA=
github.com/xtaci/kcp-go/v5 v5.6.7/go.mod h1:oE9j2NVqAkuKO5o8ByKGch3vgVX3BNf8zqP8JiGq0bM=
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -172,10 +165,11 @@ golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZ
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -185,13 +179,12 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
@@ -199,6 +192,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
@@ -209,30 +203,26 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
@@ -243,12 +233,15 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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=
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.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
@@ -271,7 +264,6 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

View File

@@ -17,9 +17,9 @@ package auth
import (
"context"
"fmt"
"slices"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/samber/lo"
"golang.org/x/oauth2/clientcredentials"
v1 "github.com/fatedier/frp/pkg/config/v1"
@@ -70,7 +70,7 @@ func (auth *OidcAuthProvider) SetLogin(loginMsg *msg.Login) (err error) {
}
func (auth *OidcAuthProvider) SetPing(pingMsg *msg.Ping) (err error) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
return nil
}
@@ -79,7 +79,7 @@ func (auth *OidcAuthProvider) SetPing(pingMsg *msg.Ping) (err error) {
}
func (auth *OidcAuthProvider) SetNewWorkConn(newWorkConnMsg *msg.NewWorkConn) (err error) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
return nil
}
@@ -135,7 +135,7 @@ func (auth *OidcAuthConsumer) verifyPostLoginToken(privilegeKey string) (err err
}
func (auth *OidcAuthConsumer) VerifyPing(pingMsg *msg.Ping) (err error) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
return nil
}
@@ -143,7 +143,7 @@ func (auth *OidcAuthConsumer) VerifyPing(pingMsg *msg.Ping) (err error) {
}
func (auth *OidcAuthConsumer) VerifyNewWorkConn(newWorkConnMsg *msg.NewWorkConn) (err error) {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
return nil
}

View File

@@ -16,9 +16,10 @@ package auth
import (
"fmt"
"slices"
"time"
"github.com/samber/lo"
v1 "github.com/fatedier/frp/pkg/config/v1"
"github.com/fatedier/frp/pkg/msg"
"github.com/fatedier/frp/pkg/util/util"
@@ -42,7 +43,7 @@ func (auth *TokenAuthSetterVerifier) SetLogin(loginMsg *msg.Login) error {
}
func (auth *TokenAuthSetterVerifier) SetPing(pingMsg *msg.Ping) error {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
return nil
}
@@ -52,7 +53,7 @@ func (auth *TokenAuthSetterVerifier) SetPing(pingMsg *msg.Ping) error {
}
func (auth *TokenAuthSetterVerifier) SetNewWorkConn(newWorkConnMsg *msg.NewWorkConn) error {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
return nil
}
@@ -69,7 +70,7 @@ func (auth *TokenAuthSetterVerifier) VerifyLogin(m *msg.Login) error {
}
func (auth *TokenAuthSetterVerifier) VerifyPing(m *msg.Ping) error {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {
return nil
}
@@ -80,7 +81,7 @@ func (auth *TokenAuthSetterVerifier) VerifyPing(m *msg.Ping) error {
}
func (auth *TokenAuthSetterVerifier) VerifyNewWorkConn(m *msg.NewWorkConn) error {
if !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
if !lo.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {
return nil
}

View File

@@ -18,9 +18,9 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"github.com/samber/lo"
"gopkg.in/ini.v1"
legacyauth "github.com/fatedier/frp/pkg/auth/legacy"
@@ -399,7 +399,7 @@ func (cfg *ClientCommonConf) Validate() error {
}
}
if !slices.Contains([]string{"tcp", "kcp", "quic", "websocket", "wss"}, cfg.Protocol) {
if !lo.Contains([]string{"tcp", "kcp", "quic", "websocket", "wss"}, cfg.Protocol) {
return fmt.Errorf("invalid protocol")
}

View File

@@ -175,9 +175,6 @@ func transformHeadersFromPluginParams(params map[string]string) v1.HeaderOperati
continue
}
if k = strings.TrimPrefix(k, "plugin_header_"); k != "" {
if out.Set == nil {
out.Set = make(map[string]string)
}
out.Set[k] = v
}
}

View File

@@ -45,6 +45,15 @@ func NewBandwidthQuantity(s string) (BandwidthQuantity, error) {
return q, nil
}
func MustBandwidthQuantity(s string) BandwidthQuantity {
q := BandwidthQuantity{}
err := q.UnmarshalString(s)
if err != nil {
panic(err)
}
return q
}
func (q *BandwidthQuantity) Equal(u *BandwidthQuantity) bool {
if q == nil && u == nil {
return true

View File

@@ -107,7 +107,6 @@ type DomainConfig struct {
type ProxyBaseConfig struct {
Name string `json:"name"`
Type string `json:"type"`
Annotations map[string]string `json:"annotations,omitempty"`
Transport ProxyTransport `json:"transport,omitempty"`
// metadata info for each proxy
Metadatas map[string]string `json:"metadatas,omitempty"`
@@ -139,7 +138,6 @@ func (c *ProxyBaseConfig) MarshalToMsg(m *msg.NewProxy) {
m.Group = c.LoadBalancer.Group
m.GroupKey = c.LoadBalancer.GroupKey
m.Metas = c.Metadatas
m.Annotations = c.Annotations
}
func (c *ProxyBaseConfig) UnmarshalFromMsg(m *msg.NewProxy) {
@@ -156,7 +154,6 @@ func (c *ProxyBaseConfig) UnmarshalFromMsg(m *msg.NewProxy) {
c.LoadBalancer.Group = m.Group
c.LoadBalancer.GroupKey = m.GroupKey
c.Metadatas = m.Metas
c.Annotations = m.Annotations
}
type TypedProxyConfig struct {

View File

@@ -18,7 +18,6 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"github.com/samber/lo"
@@ -30,7 +29,7 @@ func ValidateClientCommonConfig(c *v1.ClientCommonConfig) (Warning, error) {
warnings Warning
errs error
)
if !slices.Contains(SupportedAuthMethods, c.Auth.Method) {
if !lo.Contains(SupportedAuthMethods, c.Auth.Method) {
errs = AppendError(errs, fmt.Errorf("invalid auth method, optional values are %v", SupportedAuthMethods))
}
if !lo.Every(SupportedAuthAdditionalScopes, c.Auth.AdditionalScopes) {
@@ -64,7 +63,7 @@ func ValidateClientCommonConfig(c *v1.ClientCommonConfig) (Warning, error) {
warnings = AppendError(warnings, checkTLSConfig("transport.tls.trustedCaFile", c.Transport.TLS.TrustedCaFile))
}
if !slices.Contains(SupportedTransportProtocols, c.Transport.Protocol) {
if !lo.Contains(SupportedTransportProtocols, c.Transport.Protocol) {
errs = AppendError(errs, fmt.Errorf("invalid transport.protocol, optional values are %v", SupportedTransportProtocols))
}

View File

@@ -16,7 +16,8 @@ package validation
import (
"fmt"
"slices"
"github.com/samber/lo"
v1 "github.com/fatedier/frp/pkg/config/v1"
)
@@ -43,7 +44,7 @@ func ValidatePort(port int, fieldPath string) error {
}
func validateLogConfig(c *v1.LogConfig) error {
if !slices.Contains(SupportedLogLevels, c.Level) {
if !lo.Contains(SupportedLogLevels, c.Level) {
return fmt.Errorf("invalid log level, optional values are %v", SupportedLogLevels)
}
return nil

View File

@@ -17,10 +17,9 @@ package validation
import (
"errors"
"fmt"
"slices"
"strings"
"k8s.io/apimachinery/pkg/util/validation"
"github.com/samber/lo"
v1 "github.com/fatedier/frp/pkg/config/v1"
)
@@ -30,13 +29,11 @@ func validateProxyBaseConfigForClient(c *v1.ProxyBaseConfig) error {
return errors.New("name should not be empty")
}
if err := ValidateAnnotations(c.Annotations); err != nil {
return err
}
if !slices.Contains([]string{"", "v1", "v2"}, c.Transport.ProxyProtocolVersion) {
if !lo.Contains([]string{"", "v1", "v2"}, c.Transport.ProxyProtocolVersion) {
return fmt.Errorf("not support proxy protocol version: %s", c.Transport.ProxyProtocolVersion)
}
if !slices.Contains([]string{"client", "server"}, c.Transport.BandwidthLimitMode) {
if !lo.Contains([]string{"client", "server"}, c.Transport.BandwidthLimitMode) {
return fmt.Errorf("bandwidth limit mode should be client or server")
}
@@ -46,7 +43,7 @@ func validateProxyBaseConfigForClient(c *v1.ProxyBaseConfig) error {
}
}
if !slices.Contains([]string{"", "tcp", "http"}, c.HealthCheck.Type) {
if !lo.Contains([]string{"", "tcp", "http"}, c.HealthCheck.Type) {
return fmt.Errorf("not support health check type: %s", c.HealthCheck.Type)
}
if c.HealthCheck.Type != "" {
@@ -64,10 +61,7 @@ func validateProxyBaseConfigForClient(c *v1.ProxyBaseConfig) error {
return nil
}
func validateProxyBaseConfigForServer(c *v1.ProxyBaseConfig) error {
if err := ValidateAnnotations(c.Annotations); err != nil {
return err
}
func validateProxyBaseConfigForServer(c *v1.ProxyBaseConfig, s *v1.ServerConfig) error {
return nil
}
@@ -139,7 +133,7 @@ func validateTCPMuxProxyConfigForClient(c *v1.TCPMuxProxyConfig) error {
return err
}
if !slices.Contains([]string{string(v1.TCPMultiplexerHTTPConnect)}, c.Multiplexer) {
if !lo.Contains([]string{string(v1.TCPMultiplexerHTTPConnect)}, c.Multiplexer) {
return fmt.Errorf("not support multiplexer: %s", c.Multiplexer)
}
return nil
@@ -167,7 +161,7 @@ func validateSUDPProxyConfigForClient(c *v1.SUDPProxyConfig) error {
func ValidateProxyConfigurerForServer(c v1.ProxyConfigurer, s *v1.ServerConfig) error {
base := c.GetBaseConfig()
if err := validateProxyBaseConfigForServer(base); err != nil {
if err := validateProxyBaseConfigForServer(base, s); err != nil {
return err
}
@@ -237,34 +231,3 @@ func validateXTCPProxyConfigForServer(c *v1.XTCPProxyConfig, s *v1.ServerConfig)
func validateSUDPProxyConfigForServer(c *v1.SUDPProxyConfig, s *v1.ServerConfig) error {
return nil
}
// ValidateAnnotations validates that a set of annotations are correctly defined.
func ValidateAnnotations(annotations map[string]string) error {
if len(annotations) == 0 {
return nil
}
var errs error
for k := range annotations {
for _, msg := range validation.IsQualifiedName(strings.ToLower(k)) {
errs = AppendError(errs, fmt.Errorf("annotation key %s is invalid: %s", k, msg))
}
}
if err := ValidateAnnotationsSize(annotations); err != nil {
errs = AppendError(errs, err)
}
return errs
}
const TotalAnnotationSizeLimitB int = 256 * (1 << 10) // 256 kB
func ValidateAnnotationsSize(annotations map[string]string) error {
var totalSize int64
for k, v := range annotations {
totalSize += (int64)(len(k)) + (int64)(len(v))
}
if totalSize > (int64)(TotalAnnotationSizeLimitB) {
return fmt.Errorf("annotations size %d is larger than limit %d", totalSize, TotalAnnotationSizeLimitB)
}
return nil
}

View File

@@ -16,7 +16,6 @@ package validation
import (
"fmt"
"slices"
"github.com/samber/lo"
@@ -28,7 +27,7 @@ func ValidateServerConfig(c *v1.ServerConfig) (Warning, error) {
warnings Warning
errs error
)
if !slices.Contains(SupportedAuthMethods, c.Auth.Method) {
if !lo.Contains(SupportedAuthMethods, c.Auth.Method) {
errs = AppendError(errs, fmt.Errorf("invalid auth method, optional values are %v", SupportedAuthMethods))
}
if !lo.Every(SupportedAuthAdditionalScopes, c.Auth.AdditionalScopes) {

View File

@@ -17,7 +17,8 @@ package validation
import (
"errors"
"fmt"
"slices"
"github.com/samber/lo"
v1 "github.com/fatedier/frp/pkg/config/v1"
)
@@ -55,7 +56,7 @@ func validateVisitorBaseConfig(c *v1.VisitorBaseConfig) error {
}
func validateXTCPVisitorConfig(c *v1.XTCPVisitorConfig) error {
if !slices.Contains([]string{"kcp", "quic"}, c.Protocol) {
if !lo.Contains([]string{"kcp", "quic"}, c.Protocol) {
return fmt.Errorf("protocol should be kcp or quic")
}
return nil

View File

@@ -42,3 +42,7 @@ func ReadMsgInto(c io.Reader, msg Message) (err error) {
func WriteMsg(c io.Writer, msg interface{}) (err error) {
return msgCtl.WriteMsg(c, msg)
}
func Pack(msg interface{}) (data []byte, err error) {
return msgCtl.Pack(msg)
}

View File

@@ -108,7 +108,6 @@ type NewProxy struct {
Group string `json:"group,omitempty"`
GroupKey string `json:"group_key,omitempty"`
Metas map[string]string `json:"metas,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
// tcp and udp only
RemotePort int `json:"remote_port,omitempty"`

View File

@@ -15,8 +15,6 @@
package nathole
import (
"cmp"
"slices"
"sync"
"time"
@@ -226,7 +224,7 @@ func (mhr *MakeHoleRecords) ReportSuccess(mode int, index int) {
}
score.Score += 2
score.Score = min(score.Score, 10)
score.Score = lo.Min([]int{score.Score, 10})
return
}
}
@@ -235,12 +233,12 @@ func (mhr *MakeHoleRecords) Recommand() (mode, index int) {
mhr.mu.Lock()
defer mhr.mu.Unlock()
if len(mhr.scores) == 0 {
maxScore := lo.MaxBy(mhr.scores, func(item, max *BehaviorScore) bool {
return item.Score > max.Score
})
if maxScore == nil {
return 0, 0
}
maxScore := slices.MaxFunc(mhr.scores, func(a, b *BehaviorScore) int {
return cmp.Compare(a.Score, b.Score)
})
maxScore.Score--
mhr.LastUpdateTime = time.Now()
return maxScore.Mode, maxScore.Index

View File

@@ -17,8 +17,9 @@ package nathole
import (
"fmt"
"net"
"slices"
"strconv"
"github.com/samber/lo"
)
const (
@@ -58,7 +59,7 @@ func ClassifyNATFeature(addresses []string, localIPs []string) (*NatFeature, err
if err != nil {
return nil, err
}
if slices.Contains(localIPs, ip) {
if lo.Contains(localIPs, ip) {
natFeature.PublicNetwork = true
}

View File

@@ -20,7 +20,6 @@ import (
"encoding/hex"
"fmt"
"net"
"slices"
"strconv"
"sync"
"time"
@@ -73,7 +72,7 @@ type Session struct {
func (s *Session) genAnalysisKey() {
hash := md5.New()
vIPs := slices.Compact(parseIPs(s.visitorMsg.MappedAddrs))
vIPs := lo.Uniq(parseIPs(s.visitorMsg.MappedAddrs))
if len(vIPs) > 0 {
hash.Write([]byte(vIPs[0]))
}
@@ -81,7 +80,7 @@ func (s *Session) genAnalysisKey() {
hash.Write([]byte(s.vNatFeature.Behavior))
hash.Write([]byte(strconv.FormatBool(s.vNatFeature.RegularPortsChange)))
cIPs := slices.Compact(parseIPs(s.clientMsg.MappedAddrs))
cIPs := lo.Uniq(parseIPs(s.clientMsg.MappedAddrs))
if len(cIPs) > 0 {
hash.Write([]byte(cIPs[0]))
}
@@ -157,7 +156,7 @@ func (c *Controller) HandleVisitor(m *msg.NatHoleVisitor, transporter transport.
_ = transporter.Send(c.GenNatHoleResponse(m.TransactionID, nil, fmt.Sprintf("xtcp server for [%s] doesn't exist", m.ProxyName)))
return
}
if !slices.Contains(cfg.allowUsers, visitorUser) && !slices.Contains(cfg.allowUsers, "*") {
if !lo.Contains(cfg.allowUsers, visitorUser) && !lo.Contains(cfg.allowUsers, "*") {
_ = transporter.Send(c.GenNatHoleResponse(m.TransactionID, nil, fmt.Sprintf("xtcp visitor user [%s] not allowed for [%s]", visitorUser, m.ProxyName)))
return
}
@@ -318,7 +317,7 @@ func (c *Controller) analysis(session *Session) (*msg.NatHoleResp, *msg.NatHoleR
session.cBehavior = cBehavior
session.vBehavior = vBehavior
timeoutMs := max(cBehavior.SendDelayMs, vBehavior.SendDelayMs) + 5000
timeoutMs := lo.Max([]int{cBehavior.SendDelayMs, vBehavior.SendDelayMs}) + 5000
if cBehavior.ListenRandomPorts > 0 || vBehavior.ListenRandomPorts > 0 {
timeoutMs += 30000
}
@@ -328,8 +327,8 @@ func (c *Controller) analysis(session *Session) (*msg.NatHoleResp, *msg.NatHoleR
TransactionID: vm.TransactionID,
Sid: session.sid,
Protocol: protocol,
CandidateAddrs: slices.Compact(cm.MappedAddrs),
AssistedAddrs: slices.Compact(cm.AssistedAddrs),
CandidateAddrs: lo.Uniq(cm.MappedAddrs),
AssistedAddrs: lo.Uniq(cm.AssistedAddrs),
DetectBehavior: msg.NatHoleDetectBehavior{
Mode: mode,
Role: vBehavior.Role,
@@ -345,8 +344,8 @@ func (c *Controller) analysis(session *Session) (*msg.NatHoleResp, *msg.NatHoleR
TransactionID: cm.TransactionID,
Sid: session.sid,
Protocol: protocol,
CandidateAddrs: slices.Compact(vm.MappedAddrs),
AssistedAddrs: slices.Compact(vm.AssistedAddrs),
CandidateAddrs: lo.Uniq(vm.MappedAddrs),
AssistedAddrs: lo.Uniq(vm.AssistedAddrs),
DetectBehavior: msg.NatHoleDetectBehavior{
Mode: mode,
Role: cBehavior.Role,
@@ -385,8 +384,8 @@ func getRangePorts(addrs []string, difference, maxNumber int) []msg.PortsRange {
return nil
}
ports = append(ports, msg.PortsRange{
From: max(port-difference-5, port-maxNumber, 1),
To: min(port+difference+5, port+maxNumber, 65535),
From: lo.Max([]int{port - difference - 5, port - maxNumber, 1}),
To: lo.Min([]int{port + difference + 5, port + maxNumber, 65535}),
})
return ports
}

View File

@@ -19,7 +19,7 @@ import (
"net"
"time"
"github.com/pion/stun/v2"
"github.com/pion/stun"
)
var responseTimeout = 3 * time.Second

View File

@@ -19,12 +19,12 @@ import (
"fmt"
"math/rand"
"net"
"slices"
"strconv"
"strings"
"time"
"github.com/fatedier/golib/pool"
"github.com/samber/lo"
"golang.org/x/net/ipv4"
"k8s.io/apimachinery/pkg/util/sets"
@@ -212,7 +212,7 @@ func MakeHole(ctx context.Context, listenConn *net.UDPConn, m *msg.NatHoleResp,
}
}
detectAddrs = slices.Compact(detectAddrs)
detectAddrs = lo.Uniq(detectAddrs)
for _, detectAddr := range detectAddrs {
for _, conn := range listenConns {
if err := sendSidMessage(ctx, conn, m.Sid, transactionID, detectAddr, key, m.DetectBehavior.TTL); err != nil {
@@ -377,7 +377,7 @@ func sendSidMessageToRangePorts(
sendFunc func(*net.UDPConn, string) error,
) {
xl := xlog.FromContextSafe(ctx)
for _, ip := range slices.Compact(parseIPs(addrs)) {
for _, ip := range lo.Uniq(parseIPs(addrs)) {
for _, portsRange := range ports {
for i := portsRange.From; i <= portsRange.To; i++ {
detectAddr := net.JoinHostPort(ip, strconv.Itoa(i))
@@ -419,7 +419,7 @@ func sendSidMessageToRandomPorts(
continue
}
for _, ip := range slices.Compact(parseIPs(addrs)) {
for _, ip := range lo.Uniq(parseIPs(addrs)) {
detectAddr := net.JoinHostPort(ip, strconv.Itoa(port))
if err := sendFunc(conn, detectAddr); err != nil {
xl.Trace("send sid message from %s to %s error: %v", conn.LocalAddr(), detectAddr, err)

View File

@@ -21,7 +21,7 @@ import (
"strconv"
"github.com/fatedier/golib/crypto"
"github.com/pion/stun/v2"
"github.com/pion/stun"
"github.com/fatedier/frp/pkg/msg"
)

View File

@@ -53,8 +53,7 @@ func NewHTTP2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) {
}
rp := &httputil.ReverseProxy{
Rewrite: func(r *httputil.ProxyRequest) {
req := r.Out
Director: func(req *http.Request) {
req.URL.Scheme = "https"
req.URL.Host = p.opts.LocalAddr
if p.opts.HostHeaderRewrite != "" {

View File

@@ -50,8 +50,7 @@ func NewHTTPS2HTTPPlugin(options v1.ClientPluginOptions) (Plugin, error) {
}
rp := &httputil.ReverseProxy{
Rewrite: func(r *httputil.ProxyRequest) {
req := r.Out
Director: func(req *http.Request) {
req.URL.Scheme = "http"
req.URL.Host = p.opts.LocalAddr
if p.opts.HostHeaderRewrite != "" {

View File

@@ -55,8 +55,7 @@ func NewHTTPS2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) {
}
rp := &httputil.ReverseProxy{
Rewrite: func(r *httputil.ProxyRequest) {
req := r.Out
Director: func(req *http.Request) {
req.URL.Scheme = "https"
req.URL.Host = p.opts.LocalAddr
if p.opts.HostHeaderRewrite != "" {

View File

@@ -20,12 +20,12 @@ import (
"errors"
"fmt"
"net"
"slices"
"strings"
"sync"
"time"
libio "github.com/fatedier/golib/io"
"github.com/samber/lo"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"golang.org/x/crypto/ssh"
@@ -262,7 +262,7 @@ func (s *TunnelServer) parseClientAndProxyConfigurer(_ *tcpipForward, extraPaylo
}
proxyType := strings.TrimSpace(args[0])
supportTypes := []string{"tcp", "http", "https", "tcpmux", "stcp"}
if !slices.Contains(supportTypes, proxyType) {
if !lo.Contains(supportTypes, proxyType) {
return nil, nil, helpMessage, fmt.Errorf("invalid proxy type: %s, support types: %v", proxyType, supportTypes)
}
pc := v1.NewProxyConfigurerByType(v1.ProxyType(proxyType))

View File

@@ -24,6 +24,30 @@ import (
"github.com/fatedier/frp/pkg/util/util"
)
type HTTPAuthWrapper struct {
h http.Handler
user string
passwd string
}
func NewHTTPBasicAuthWrapper(h http.Handler, user, passwd string) http.Handler {
return &HTTPAuthWrapper{
h: h,
user: user,
passwd: passwd,
}
}
func (aw *HTTPAuthWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
user, passwd, hasAuth := r.BasicAuth()
if (aw.user == "" && aw.passwd == "") || (hasAuth && user == aw.user && passwd == aw.passwd) {
aw.h.ServeHTTP(w, r)
} else {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
}
type HTTPAuthMiddleware struct {
user string
passwd string

View File

@@ -18,7 +18,7 @@ import (
"fmt"
"net"
kcp "github.com/xtaci/kcp-go/v5"
kcp "github.com/fatedier/kcp-go"
)
type KCPListener struct {
@@ -85,15 +85,7 @@ func (l *KCPListener) Addr() net.Addr {
}
func NewKCPConnFromUDP(conn *net.UDPConn, connected bool, raddr string) (net.Conn, error) {
udpAddr, err := net.ResolveUDPAddr("udp", raddr)
if err != nil {
return nil, err
}
var pConn net.PacketConn = conn
if connected {
pConn = &ConnectedUDPConn{conn}
}
kcpConn, err := kcp.NewConn3(1, udpAddr, nil, 10, 3, pConn)
kcpConn, err := kcp.NewConnEx(1, connected, raddr, nil, 10, 3, conn)
if err != nil {
return nil, err
}

View File

@@ -4,6 +4,7 @@ import (
"errors"
"net"
"net/http"
"strconv"
"golang.org/x/net/websocket"
)
@@ -49,6 +50,15 @@ func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) {
return
}
func ListenWebsocket(bindAddr string, bindPort int) (*WebsocketListener, error) {
tcpLn, err := net.Listen("tcp", net.JoinHostPort(bindAddr, strconv.Itoa(bindPort)))
if err != nil {
return nil, err
}
l := NewWebsocketListener(tcpLn)
return l, nil
}
func (p *WebsocketListener) Accept() (net.Conn, error) {
c, ok := <-p.acceptCh
if !ok {

View File

@@ -47,6 +47,16 @@ func RandIDWithLen(idLen int) (id string, err error) {
return id[:idLen], nil
}
// RandIDWithRandLen return a rand string with length between [start, end).
func RandIDWithRandLen(start, end int) (id string, err error) {
if start >= end {
err = fmt.Errorf("start should be less than end")
return
}
idLen := mathrand.Intn(end-start) + start
return RandIDWithLen(idLen)
}
func GetAuthKey(token string, timestamp int64) (key string) {
md5Ctx := md5.New()
md5Ctx.Write([]byte(token))

View File

@@ -14,6 +14,48 @@ func TestRandId(t *testing.T) {
assert.Equal(16, len(id))
}
func TestRandIDWithRandLen(t *testing.T) {
tests := []struct {
name string
start int
end int
expectErr bool
}{
{
name: "start and end are equal",
start: 5,
end: 5,
expectErr: true,
},
{
name: "start is less than end",
start: 5,
end: 10,
expectErr: false,
},
{
name: "start is greater than end",
start: 10,
end: 5,
expectErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert := assert.New(t)
id, err := RandIDWithRandLen(tt.start, tt.end)
if tt.expectErr {
assert.Error(err)
} else {
assert.NoError(err)
assert.GreaterOrEqual(len(id), tt.start)
assert.Less(len(id), tt.end)
}
})
}
}
func TestGetAuthKey(t *testing.T) {
assert := assert.New(t)
key := GetAuthKey("1234", 1488720000)

View File

@@ -14,8 +14,34 @@
package version
import (
"strconv"
"strings"
)
var version = "0.54.0"
func Full() string {
return version
}
func getSubVersion(v string, position int) int64 {
arr := strings.Split(v, ".")
if len(arr) < 3 {
return 0
}
res, _ := strconv.ParseInt(arr[position], 10, 64)
return res
}
func Proto(v string) int64 {
return getSubVersion(v, 0)
}
func Major(v string) int64 {
return getSubVersion(v, 1)
}
func Minor(v string) int64 {
return getSubVersion(v, 2)
}

View File

@@ -0,0 +1,53 @@
// Copyright 2016 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package version
import (
"fmt"
"strconv"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestFull(t *testing.T) {
assert := assert.New(t)
version := Full()
arr := strings.Split(version, ".")
assert.Equal(3, len(arr))
proto, err := strconv.ParseInt(arr[0], 10, 64)
assert.NoError(err)
assert.True(proto >= 0)
major, err := strconv.ParseInt(arr[1], 10, 64)
assert.NoError(err)
assert.True(major >= 0)
minor, err := strconv.ParseInt(arr[2], 10, 64)
assert.NoError(err)
assert.True(minor >= 0)
}
func TestVersion(t *testing.T) {
assert := assert.New(t)
proto := Proto(Full())
major := Major(Full())
minor := Minor(Full())
parseVersion := fmt.Sprintf("%d.%d.%d", proto, major, minor)
version := Full()
assert.Equal(parseVersion, version)
}

View File

@@ -58,9 +58,7 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
}
proxy := &httputil.ReverseProxy{
// Modify incoming requests by route policies.
Rewrite: func(r *httputil.ProxyRequest) {
r.SetXForwarded()
req := r.Out
Director: func(req *http.Request) {
req.URL.Scheme = "http"
reqRouteInfo := req.Context().Value(RouteInfoKey).(*RequestRouteInfo)
oldHost, _ := httppkg.CanonicalHost(reqRouteInfo.Host)

View File

@@ -1,9 +1,8 @@
package vhost
import (
"cmp"
"errors"
"slices"
"sort"
"strings"
"sync"
)
@@ -59,10 +58,7 @@ func (r *Routers) Add(domain, location, httpUser string, payload interface{}) er
payload: payload,
}
vrs = append(vrs, vr)
slices.SortFunc(vrs, func(a, b *Router) int {
return -cmp.Compare(a.location, b.location)
})
sort.Sort(sort.Reverse(ByLocation(vrs)))
routersByHTTPUser[httpUser] = vrs
r.indexByDomain[domain] = routersByHTTPUser
@@ -134,3 +130,18 @@ func (r *Routers) exist(host, path, httpUser string) (route *Router, exist bool)
}
return
}
// sort by location
type ByLocation []*Router
func (a ByLocation) Len() int {
return len(a)
}
func (a ByLocation) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func (a ByLocation) Less(i, j int) bool {
return strings.Compare(a[i].location, a[j].location) < 0
}

View File

@@ -16,6 +16,7 @@ package wait
import (
"math/rand"
"sync"
"time"
"github.com/fatedier/frp/pkg/util/util"
@@ -173,3 +174,21 @@ func Until(f func(), period time.Duration, stopCh <-chan struct{}) {
return period
}), true, stopCh)
}
func MergeAndCloseOnAnyStopChannel[T any](upstreams ...<-chan T) <-chan T {
out := make(chan T)
closeOnce := sync.Once{}
for _, upstream := range upstreams {
ch := upstream
go func() {
select {
case <-ch:
closeOnce.Do(func() {
close(out)
})
case <-out:
}
}()
}
return out
}

View File

@@ -15,8 +15,7 @@
package xlog
import (
"cmp"
"slices"
"sort"
"github.com/fatedier/frp/pkg/util/log"
)
@@ -78,8 +77,8 @@ func (l *Logger) AddPrefix(prefix LogPrefix) *Logger {
}
func (l *Logger) renderPrefixString() {
slices.SortStableFunc(l.prefixes, func(a, b LogPrefix) int {
return cmp.Compare(a.Priority, b.Priority)
sort.SliceStable(l.prefixes, func(i, j int) bool {
return l.prefixes[i].Priority < l.prefixes[j].Priority
})
l.prefixString = ""
for _, v := range l.prefixes {

View File

@@ -15,10 +15,9 @@
package server
import (
"cmp"
"encoding/json"
"net/http"
"slices"
"sort"
"github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus/promhttp"
@@ -229,8 +228,8 @@ func (svr *Service) apiProxyByType(w http.ResponseWriter, r *http.Request) {
proxyInfoResp := GetProxyInfoResp{}
proxyInfoResp.Proxies = svr.getProxyStatsByType(proxyType)
slices.SortFunc(proxyInfoResp.Proxies, func(a, b *ProxyStatsInfo) int {
return cmp.Compare(a.Name, b.Name)
sort.Slice(proxyInfoResp.Proxies, func(i, j int) bool {
return proxyInfoResp.Proxies[i].Name < proxyInfoResp.Proxies[j].Name
})
buf, _ := json.Marshal(&proxyInfoResp)

View File

@@ -18,10 +18,10 @@ import (
"fmt"
"io"
"net"
"slices"
"sync"
libio "github.com/fatedier/golib/io"
"github.com/samber/lo"
netpkg "github.com/fatedier/frp/pkg/util/net"
"github.com/fatedier/frp/pkg/util/util"
@@ -75,7 +75,7 @@ func (vm *Manager) NewConn(name string, conn net.Conn, timestamp int64, signKey
return
}
if !slices.Contains(l.allowUsers, visitorUser) && !slices.Contains(l.allowUsers, "*") {
if !lo.Contains(l.allowUsers, visitorUser) && !lo.Contains(l.allowUsers, "*") {
err = fmt.Errorf("visitor connection of [%s] user [%s] not allowed", name, visitorUser)
return
}

View File

@@ -1,54 +0,0 @@
package basic
import (
"fmt"
"io"
"net/http"
"github.com/onsi/ginkgo/v2"
"github.com/tidwall/gjson"
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
)
var _ = ginkgo.Describe("[Feature: Annotations]", func() {
f := framework.NewDefaultFramework()
ginkgo.It("Set Proxy Annotations", func() {
webPort := f.AllocPort()
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
webServer.port = %d
`, webPort)
p1Port := f.AllocPort()
clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
[[proxies]]
name = "p1"
type = "tcp"
localPort = {{ .%s }}
remotePort = %d
[proxies.annotations]
"frp.e2e.test/foo" = "value1"
"frp.e2e.test/bar" = "value2"
`, framework.TCPEchoServerPort, p1Port)
f.RunProcesses([]string{serverConf}, []string{clientConf})
framework.NewRequestExpect(f).Port(p1Port).Ensure()
// check annotations in frps
resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/api/proxy/tcp/%s", webPort, "p1"))
framework.ExpectNoError(err)
framework.ExpectEqual(resp.StatusCode, 200)
defer resp.Body.Close()
content, err := io.ReadAll(resp.Body)
framework.ExpectNoError(err)
annotations := gjson.Get(string(content), "conf.annotations").Map()
framework.ExpectEqual("value1", annotations["frp.e2e.test/foo"].String())
framework.ExpectEqual("value2", annotations["frp.e2e.test/bar"].String())
})
})

View File

@@ -9,21 +9,19 @@ declare module 'vue' {
export interface GlobalComponents {
ElButton: typeof import('element-plus/es')['ElButton']
ElCol: typeof import('element-plus/es')['ElCol']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDivider: typeof import('element-plus/es')['ElDivider']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElRow: typeof import('element-plus/es')['ElRow']
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTag: typeof import('element-plus/es')['ElTag']
ElText: typeof import('element-plus/es')['ElText']
ElTooltip: typeof import('element-plus/es')['ElTooltip']
LongSpan: typeof import('./src/components/LongSpan.vue')['default']
ProxiesHTTP: typeof import('./src/components/ProxiesHTTP.vue')['default']

View File

@@ -30,6 +30,27 @@
>
<el-table-column type="expand">
<template #default="props">
<el-popover
placement="right"
width="600"
style="margin-left: 0px"
trigger="click"
>
<template #default>
<Traffic :proxyName="props.row.name" />
</template>
<template #reference>
<el-button
type="primary"
size="large"
:name="props.row.name"
style="margin-bottom: 10px"
>Traffic Statistics
</el-button>
</template>
</el-popover>
<ProxyViewExpand :row="props.row" :proxyType="proxyType" />
</template>
</el-table-column>
@@ -61,27 +82,8 @@
<el-tag v-else type="danger">{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
<el-table-column label="Operations">
<template #default="scope">
<el-button
type="primary"
:name="scope.row.name"
style="margin-bottom: 10px"
@click="dialogVisibleName = scope.row.name; dialogVisible = true"
>Traffic
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog
v-model="dialogVisible"
destroy-on-close="true"
:title="dialogVisibleName"
width="700px">
<Traffic :proxyName="dialogVisibleName" />
</el-dialog>
</template>
<script setup lang="ts">
@@ -90,7 +92,6 @@ import type { TableColumnCtx } from 'element-plus'
import type { BaseProxy } from '../utils/proxy.js'
import { ElMessage } from 'element-plus'
import ProxyViewExpand from './ProxyViewExpand.vue'
import { ref } from 'vue'
defineProps<{
proxies: BaseProxy[]
@@ -99,9 +100,6 @@ defineProps<{
const emit = defineEmits(['refresh'])
const dialogVisible = ref(false)
const dialogVisibleName = ref("")
const formatTrafficIn = (row: BaseProxy, _: TableColumnCtx<BaseProxy>) => {
return Humanize.fileSize(row.trafficIn)
}
@@ -111,7 +109,7 @@ const formatTrafficOut = (row: BaseProxy, _: TableColumnCtx<BaseProxy>) => {
}
const clearOfflineProxies = () => {
fetch('../api/proxies?status=offline', {
fetch('/api/proxies?status=offline', {
method: 'DELETE',
credentials: 'include',
})

View File

@@ -60,56 +60,11 @@
<span>{{ row.lastCloseTime }}</span>
</el-form-item>
</el-form>
<div v-if="row.annotations && row.annotations.size > 0">
<el-divider />
<el-text class="title-text" size="large">Annotations</el-text>
<ul>
<li v-for="item in annotationsArray()">
<span class="annotation-key">{{ item.key }}</span>
<span>{{ item.value }}</span>
</li>
</ul>
</div>
</template>
<script setup lang="ts">
const props = defineProps<{
defineProps<{
row: any
proxyType: string
}>()
// annotationsArray returns an array of key-value pairs from the annotations map.
const annotationsArray = (): Array<{ key: string; value: string }> => {
const array: Array<{ key: string; value: any }> = [];
if (props.row.annotations) {
props.row.annotations.forEach((value: any, key: string) => {
array.push({ key, value });
});
}
return array;
}
</script>
<style>
ul {
list-style-type: none;
padding: 5px;
}
ul li {
justify-content: space-between;
padding: 5px;
}
ul .annotation-key {
width: 300px;
display: inline-block;
vertical-align: middle;
}
.title-text {
color: #99a9bf;
}
</style>

View File

@@ -1,7 +1,6 @@
class BaseProxy {
name: string
type: string
annotations: Map<string, string>
encryption: boolean
compression: boolean
conns: number
@@ -22,13 +21,6 @@ class BaseProxy {
constructor(proxyStats: any) {
this.name = proxyStats.name
this.type = ''
this.annotations = new Map<string, string>()
if (proxyStats.conf?.annotations) {
for (const key in proxyStats.conf.annotations) {
this.annotations.set(key, proxyStats.conf.annotations[key])
}
}
this.encryption = false
this.compression = false
this.encryption =