diff --git a/.circleci/config.yml b/.circleci/config.yml
index f8623698ae3..7499579a8d9 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -2,14 +2,16 @@ version: 2
jobs:
go-version-latest:
docker:
- - image: cimg/go:1.18-node
+ - image: cimg/go:1.19-node
+ resource_class: large
steps:
- checkout
- run: make
- run: make alltest
go-version-last:
docker:
- - image: cimg/go:1.17-node
+ - image: cimg/go:1.18-node
+ resource_class: large
steps:
- checkout
- run: make
diff --git a/.github/workflows/build-and-push-image.yml b/.github/workflows/build-and-push-image.yml
index b7f7318b62f..99a9fa9a066 100644
--- a/.github/workflows/build-and-push-image.yml
+++ b/.github/workflows/build-and-push-image.yml
@@ -9,6 +9,9 @@ on:
description: 'Image tag'
required: true
default: 'test'
+permissions:
+ contents: read
+
jobs:
image:
name: Build Image from Dockerfile and binaries
@@ -16,15 +19,15 @@ jobs:
steps:
# environment
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: '0'
- name: Set up QEMU
- uses: docker/setup-qemu-action@v1
+ uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v1
+ uses: docker/setup-buildx-action@v2
# get image tag name
- name: Get Image Tag Name
@@ -35,13 +38,13 @@ jobs:
echo "TAG_NAME=${{ github.event.inputs.tag }}" >> $GITHUB_ENV
fi
- name: Login to DockerHub
- uses: docker/login-action@v1
+ uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Login to the GPR
- uses: docker/login-action@v1
+ uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -58,7 +61,7 @@ jobs:
echo "TAG_FRPS_GPR=ghcr.io/fatedier/frps:${{ env.TAG_NAME }}" >> $GITHUB_ENV
- name: Build and push frpc
- uses: docker/build-push-action@v2
+ uses: docker/build-push-action@v3
with:
context: .
file: ./dockerfiles/Dockerfile-for-frpc
@@ -69,7 +72,7 @@ jobs:
${{ env.TAG_FRPC_GPR }}
- name: Build and push frps
- uses: docker/build-push-action@v2
+ uses: docker/build-push-action@v3
with:
context: .
file: ./dockerfiles/Dockerfile-for-frps
diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
new file mode 100644
index 00000000000..c9051f38ac6
--- /dev/null
+++ b/.github/workflows/golangci-lint.yml
@@ -0,0 +1,41 @@
+name: golangci-lint
+on:
+ push:
+ branches:
+ - master
+ - dev
+ pull_request:
+permissions:
+ contents: read
+ # Optional: allow read access to pull request. Use with `only-new-issues` option.
+ pull-requests: read
+jobs:
+ golangci:
+ name: lint
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/setup-go@v3
+ with:
+ go-version: 1.19
+ - uses: actions/checkout@v3
+ - name: golangci-lint
+ 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.49.0
+
+ # Optional: golangci-lint command line arguments.
+ # args: --issues-exit-code=0
+
+ # Optional: show only new issues if it's a pull request. The default value is `false`.
+ # only-new-issues: true
+
+ # Optional: if set to true then the all caching functionality will be complete disabled,
+ # takes precedence over all other caching options.
+ # skip-cache: true
+
+ # Optional: if set to true then the action don't cache or restore ~/go/pkg.
+ # skip-pkg-cache: true
+
+ # Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
+ # skip-build-cache: true
diff --git a/.github/workflows/goreleaser.yml b/.github/workflows/goreleaser.yml
index d78d2929714..d483e844267 100644
--- a/.github/workflows/goreleaser.yml
+++ b/.github/workflows/goreleaser.yml
@@ -10,26 +10,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
- uses: actions/setup-go@v2
+ uses: actions/setup-go@v3
with:
- go-version: 1.18
+ go-version: 1.19
- - run: |
- # https://github.com/actions/setup-go/issues/107
- cp -f `which go` /usr/bin/go
-
- name: Make All
run: |
sed -i 's/Token: ""/Token: "${{ secrets.FRP_TOKEN }}"/' ./pkg/auth/token.go
./package.sh
- name: Run GoReleaser
- uses: goreleaser/goreleaser-action@v2
+ uses: goreleaser/goreleaser-action@v3
with:
version: latest
args: release --rm-dist --release-notes=./Release.md
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index 1a44ddf67c4..c3642d914ac 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -8,11 +8,17 @@ on:
description: 'In debug mod'
required: false
default: 'false'
+permissions:
+ contents: read
+
jobs:
stale:
+ permissions:
+ issues: write # for actions/stale to close stale issues
+ pull-requests: write # for actions/stale to close stale PRs
runs-on: ubuntu-latest
steps:
- - uses: actions/stale@v5
+ - uses: actions/stale@v6
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'Issues go stale after 30d of inactivity. Stale issues rot after an additional 7d of inactivity and eventually close.'
diff --git a/.gitignore b/.gitignore
index eeccf24af01..0d8ca50d8d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,7 @@ test/bin/
vendor/
dist/
.idea/
+.vscode/
# Cache
*.swp
diff --git a/.golangci.yml b/.golangci.yml
new file mode 100644
index 00000000000..39c8e3f7ece
--- /dev/null
+++ b/.golangci.yml
@@ -0,0 +1,140 @@
+service:
+ # When updating this, also update the version stored in docker/build-tools/Dockerfile in the istio/tools repo.
+ golangci-lint-version: 1.49.x # use the fixed version to not introduce new linters unexpectedly
+
+run:
+ concurrency: 4
+ # timeout for analysis, e.g. 30s, 5m, default is 1m
+ deadline: 20m
+ build-tags:
+ - integ
+ - integfuzz
+ # which dirs to skip: they won't be analyzed;
+ # can use regexp here: generated.*, regexp is applied on full path;
+ # default value is empty list, but next dirs are always skipped independently
+ # from this option's value:
+ # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
+ skip-dirs:
+ - genfiles$
+ - vendor$
+ - bin$
+
+ # which files to skip: they will be analyzed, but issues from them
+ # won't be reported. Default value is empty list, but there is
+ # no need to include all autogenerated files, we confidently recognize
+ # autogenerated files. If it's not please let us know.
+ skip-files:
+ - ".*\\.pb\\.go"
+ - ".*\\.gen\\.go"
+
+linters:
+ disable-all: true
+ enable:
+ - unused
+ - errcheck
+ - exportloopref
+ - gocritic
+ - gofumpt
+ - goimports
+ - revive
+ - gosimple
+ - govet
+ - ineffassign
+ - lll
+ - misspell
+ - staticcheck
+ - stylecheck
+ - typecheck
+ - unconvert
+ - unparam
+ - gci
+ - gosec
+ - asciicheck
+ - prealloc
+ - predeclared
+ - makezero
+ fast: false
+
+linters-settings:
+ errcheck:
+ # report about not checking of errors in type assetions: `a := b.(MyStruct)`;
+ # default is false: such cases aren't reported by default.
+ check-type-assertions: false
+
+ # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
+ # default is false: such cases aren't reported by default.
+ check-blank: false
+ govet:
+ # report about shadowed variables
+ check-shadowing: false
+ maligned:
+ # print struct with more effective memory layout or not, false by default
+ suggest-new: true
+ misspell:
+ # Correct spellings using locale preferences for US or UK.
+ # Default is to use a neutral variety of English.
+ # Setting locale to US will correct the British spelling of 'colour' to 'color'.
+ locale: US
+ ignore-words:
+ - cancelled
+ - marshalled
+ lll:
+ # max line length, lines longer will be reported. Default is 120.
+ # '\t' is counted as 1 character by default, and can be changed with the tab-width option
+ line-length: 160
+ # tab width in spaces. Default to 1.
+ tab-width: 1
+ gocritic:
+ disabled-checks:
+ - exitAfterDefer
+ unused:
+ check-exported: false
+ unparam:
+ # Inspect exported functions, default is false. Set to true if no external program/library imports your code.
+ # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
+ # if it's called for subdir of a project it can't find external interfaces. All text editor integrations
+ # with golangci-lint call it on a directory with the changed file.
+ check-exported: false
+ gci:
+ sections:
+ - standard
+ - default
+ - prefix(github.com/fatedier/frp/)
+ gosec:
+ severity: "low"
+ confidence: "low"
+ excludes:
+ - G102
+ - G112
+ - G306
+ - G401
+ - G402
+ - G404
+ - G501
+
+issues:
+ # List of regexps of issue texts to exclude, empty list by default.
+ # But independently from this option we use default exclude patterns,
+ # it can be disabled by `exclude-use-default: false`. To list all
+ # excluded by default patterns execute `golangci-lint run --help`
+ # exclude:
+ # - composite literal uses unkeyed fields
+
+ exclude-rules:
+ # Exclude some linters from running on test files.
+ - path: _test\.go$|^tests/|^samples/
+ linters:
+ - errcheck
+ - maligned
+
+ # Independently from option `exclude` we use default exclude patterns,
+ # it can be disabled by this option. To list all
+ # excluded by default patterns execute `golangci-lint run --help`.
+ # Default value for this option is true.
+ exclude-use-default: true
+
+ # Maximum issues count per one linter. Set to 0 to disable. Default is 50.
+ max-per-linter: 0
+
+ # Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
+ max-same-issues: 0
diff --git a/Makefile.cross-compiles b/Makefile.cross-compiles
index 9351924a922..06e10d7959a 100644
--- a/Makefile.cross-compiles
+++ b/Makefile.cross-compiles
@@ -2,7 +2,7 @@ export PATH := $(GOPATH)/bin:$(PATH)
export GO111MODULE=on
LDFLAGS := -s -w
-os-archs=darwin:amd64 darwin:arm64 freebsd:386 freebsd:amd64 linux:386 linux:amd64 linux:arm linux:arm64 windows:386 windows:amd64 linux:mips64 linux:mips64le linux:mips:softfloat linux:mipsle:softfloat
+os-archs=darwin:amd64 darwin:arm64 freebsd:386 freebsd:amd64 linux:386 linux:amd64 linux:arm linux:arm64 windows:386 windows:amd64 linux:mips64 linux:mips64le linux:mips:softfloat linux:mipsle:softfloat linux:riscv64
all: build
diff --git a/README.md b/README.md
index 92c14933c24..57a68949b24 100644
--- a/README.md
+++ b/README.md
@@ -6,17 +6,6 @@
[README](README.md) | [中文文档](README_zh.md)
-
Platinum Sponsors
-
-
-
-
-
-
-
-
-
-
Gold Sponsors
@@ -74,6 +63,7 @@ frp also has a P2P connect mode.
* [For Each Proxy](#for-each-proxy)
* [TCP Stream Multiplexing](#tcp-stream-multiplexing)
* [Support KCP Protocol](#support-kcp-protocol)
+ * [Support QUIC Protocol](#support-quic-protocol)
* [Connection Pooling](#connection-pooling)
* [Load balancing](#load-balancing)
* [Service Health Check](#service-health-check)
@@ -656,7 +646,7 @@ openssl req -new -sha256 -key server.key \
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com")) \
-out server.csr
-openssl x509 -req -days 365 \
+openssl x509 -req -days 365 -sha256 \
-in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com") \
-out server.crt
@@ -671,7 +661,7 @@ openssl req -new -sha256 -key client.key \
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:client.com,DNS:example.client.com")) \
-out client.csr
-openssl x509 -req -days 365 \
+openssl x509 -req -days 365 -sha256 \
-in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-extfile <(printf "subjectAltName=DNS:client.com,DNS:example.client.com") \
-out client.crt
@@ -772,6 +762,35 @@ KCP mode uses UDP as the underlying transport. Using KCP in frp:
protocol = kcp
```
+### Support QUIC Protocol
+
+QUIC is a new multiplexed transport built on top of UDP.
+
+Using QUIC in frp:
+
+1. Enable QUIC in frps:
+
+ ```ini
+ # frps.ini
+ [common]
+ bind_port = 7000
+ # Specify a UDP port for QUIC.
+ quic_bind_port = 7000
+ ```
+
+ The `quic_bind_port` number can be the same number as `bind_port`, since `bind_port` field specifies a TCP port.
+
+2. Configure `frpc.ini` to use QUIC to connect to frps:
+
+ ```ini
+ # frpc.ini
+ [common]
+ server_addr = x.x.x.x
+ # Same as the 'quic_bind_port' in frps.ini
+ server_port = 7000
+ protocol = quic
+ ```
+
### Connection Pooling
By default, frps creates a new frpc connection to the backend service upon a user request. With connection pooling, frps keeps a certain number of pre-established connections, reducing the time needed to establish a connection.
@@ -883,7 +902,7 @@ custom_domains = test.example.com
host_header_rewrite = dev.example.com
```
-The HTTP request will have the the `Host` header rewritten to `Host: dev.example.com` when it reaches the actual web server, although the request from the browser probably has `Host: test.example.com`.
+The HTTP request will have the `Host` header rewritten to `Host: dev.example.com` when it reaches the actual web server, although the request from the browser probably has `Host: test.example.com`.
### Setting other HTTP Headers
diff --git a/README_zh.md b/README_zh.md
index 854ae966a46..e0612bbfbe2 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -7,17 +7,6 @@
frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。
-Platinum Sponsors
-
-
-
-
-
-
-
-
-
-
Gold Sponsors
diff --git a/Release.md b/Release.md
index 35c8b12ea31..bbcb8c5c96f 100644
--- a/Release.md
+++ b/Release.md
@@ -1,8 +1,9 @@
### New
-* Use auto generated certificates if `plugin_key_path` and `plugin_crt_path` are empty for plugin `https2https` and `https2http`.
-* Server dashboard supports TLS configs.
+* Add `oidc_scope` parameter to frpc when `authentication_method = oidc`.
+* Support quic protocol between frpc and frps.
-### Fix
-* xtcp error with IPv6 address.
+### Improve
+
+* Upgrade oidc and oauth2 package which is forward compatible.
diff --git a/client/admin.go b/client/admin.go
index 6a6ceecb7c4..f96e1bc1e5a 100644
--- a/client/admin.go
+++ b/client/admin.go
@@ -20,10 +20,10 @@ import (
"net/http/pprof"
"time"
+ "github.com/gorilla/mux"
+
"github.com/fatedier/frp/assets"
frpNet "github.com/fatedier/frp/pkg/util/net"
-
- "github.com/gorilla/mux"
)
var (
@@ -77,6 +77,8 @@ func (svr *Service) RunAdminServer(address string) (err error) {
return err
}
- go server.Serve(ln)
+ go func() {
+ _ = server.Serve(ln)
+ }()
return
}
diff --git a/client/admin_api.go b/client/admin_api.go
index e434fcb19a7..545ba7fc952 100644
--- a/client/admin_api.go
+++ b/client/admin_api.go
@@ -49,7 +49,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
log.Info("api response [/api/reload], code [%d]", res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
- w.Write([]byte(res.Msg))
+ _, _ = w.Write([]byte(res.Msg))
}
}()
@@ -68,7 +68,6 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
return
}
log.Info("success reload conf")
- return
}
type StatusResp struct {
@@ -173,7 +172,7 @@ func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request) {
defer func() {
log.Info("Http response [/api/status]")
buf, _ = json.Marshal(&res)
- w.Write(buf)
+ _, _ = w.Write(buf)
}()
ps := svr.ctl.pm.GetAllProxyStatus()
@@ -202,7 +201,6 @@ func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request) {
sort.Sort(ByProxyStatusResp(res.STCP))
sort.Sort(ByProxyStatusResp(res.XTCP))
sort.Sort(ByProxyStatusResp(res.SUDP))
- return
}
// GET api/config
@@ -214,7 +212,7 @@ func (svr *Service) apiGetConfig(w http.ResponseWriter, r *http.Request) {
log.Info("Http get response [/api/config], code [%d]", res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
- w.Write([]byte(res.Msg))
+ _, _ = w.Write([]byte(res.Msg))
}
}()
@@ -254,7 +252,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
log.Info("Http put response [/api/config], code [%d]", res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
- w.Write([]byte(res.Msg))
+ _, _ = w.Write([]byte(res.Msg))
}
}()
@@ -315,7 +313,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
}
content = strings.Join(newRows, "\n")
- err = os.WriteFile(svr.cfgFile, []byte(content), 0644)
+ err = os.WriteFile(svr.cfgFile, []byte(content), 0o644)
if err != nil {
res.Code = 500
res.Msg = fmt.Sprintf("write content to frpc config file error: %v", err)
diff --git a/client/control.go b/client/control.go
index ef9a766fcda..9fb15c0104f 100644
--- a/client/control.go
+++ b/client/control.go
@@ -16,26 +16,19 @@ package client
import (
"context"
- "crypto/tls"
"io"
"net"
"runtime/debug"
- "strconv"
- "sync"
"time"
+ "github.com/fatedier/golib/control/shutdown"
+ "github.com/fatedier/golib/crypto"
+
"github.com/fatedier/frp/client/proxy"
"github.com/fatedier/frp/pkg/auth"
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/msg"
- "github.com/fatedier/frp/pkg/transport"
- frpNet "github.com/fatedier/frp/pkg/util/net"
"github.com/fatedier/frp/pkg/util/xlog"
-
- "github.com/fatedier/golib/control/shutdown"
- "github.com/fatedier/golib/crypto"
- libdial "github.com/fatedier/golib/net/dial"
- fmux "github.com/hashicorp/yamux"
)
type Control struct {
@@ -52,8 +45,7 @@ type Control struct {
// control connection
conn net.Conn
- // tcp stream multiplexing, if enabled
- session *fmux.Session
+ cm *ConnectionManager
// put a message in this channel to send it over control connection to server
sendCh chan (msg.Message)
@@ -79,8 +71,6 @@ type Control struct {
// The UDP port that the server is listening on
serverUDPPort int
- mu sync.RWMutex
-
xl *xlog.Logger
// service context
@@ -90,18 +80,19 @@ type Control struct {
authSetter auth.Setter
}
-func NewControl(ctx context.Context, runID string, conn net.Conn, session *fmux.Session,
+func NewControl(
+ ctx context.Context, runID string, conn net.Conn, cm *ConnectionManager,
clientCfg config.ClientCommonConf,
pxyCfgs map[string]config.ProxyConf,
visitorCfgs map[string]config.VisitorConf,
serverUDPPort int,
- authSetter auth.Setter) *Control {
-
+ authSetter auth.Setter,
+) *Control {
// new xlog instance
ctl := &Control{
runID: runID,
conn: conn,
- session: session,
+ cm: cm,
pxyCfgs: pxyCfgs,
sendCh: make(chan msg.Message, 100),
readCh: make(chan msg.Message, 100),
@@ -131,13 +122,13 @@ func (ctl *Control) Run() {
// start all visitors
go ctl.vm.Run()
- return
}
func (ctl *Control) HandleReqWorkConn(inMsg *msg.ReqWorkConn) {
xl := ctl.xl
workConn, err := ctl.connectServer()
if err != nil {
+ xl.Warn("start new connection to server error: %v", err)
return
}
@@ -156,7 +147,7 @@ func (ctl *Control) HandleReqWorkConn(inMsg *msg.ReqWorkConn) {
var startMsg msg.StartWorkConn
if err = msg.ReadMsgInto(workConn, &startMsg); err != nil {
- xl.Error("work connection closed before response StartWorkConn message: %v", err)
+ xl.Trace("work connection closed before response StartWorkConn message: %v", err)
workConn.Close()
return
}
@@ -193,9 +184,7 @@ func (ctl *Control) GracefulClose(d time.Duration) error {
time.Sleep(d)
ctl.conn.Close()
- if ctl.session != nil {
- ctl.session.Close()
- }
+ ctl.cm.Close()
return nil
}
@@ -206,70 +195,7 @@ func (ctl *Control) ClosedDoneCh() <-chan struct{} {
// connectServer return a new connection to frps
func (ctl *Control) connectServer() (conn net.Conn, err error) {
- xl := ctl.xl
- if ctl.clientCfg.TCPMux {
- stream, errRet := ctl.session.OpenStream()
- if errRet != nil {
- err = errRet
- xl.Warn("start new connection to server error: %v", err)
- return
- }
- conn = stream
- } else {
- var tlsConfig *tls.Config
- sn := ctl.clientCfg.TLSServerName
- if sn == "" {
- sn = ctl.clientCfg.ServerAddr
- }
-
- if ctl.clientCfg.TLSEnable {
- tlsConfig, err = transport.NewClientTLSConfig(
- ctl.clientCfg.TLSCertFile,
- ctl.clientCfg.TLSKeyFile,
- ctl.clientCfg.TLSTrustedCaFile,
- sn)
-
- if err != nil {
- xl.Warn("fail to build tls configuration when connecting to server, err: %v", err)
- return
- }
- }
-
- proxyType, addr, auth, err := libdial.ParseProxyURL(ctl.clientCfg.HTTPProxy)
- if err != nil {
- xl.Error("fail to parse proxy url")
- return nil, err
- }
- dialOptions := []libdial.DialOption{}
- protocol := ctl.clientCfg.Protocol
- if protocol == "websocket" {
- protocol = "tcp"
- dialOptions = append(dialOptions, libdial.WithAfterHook(libdial.AfterHook{Hook: frpNet.DialHookWebsocket()}))
- }
- if ctl.clientCfg.ConnectServerLocalIP != "" {
- dialOptions = append(dialOptions, libdial.WithLocalAddr(ctl.clientCfg.ConnectServerLocalIP))
- }
- dialOptions = append(dialOptions,
- libdial.WithProtocol(protocol),
- libdial.WithTimeout(time.Duration(ctl.clientCfg.DialServerTimeout)*time.Second),
- libdial.WithKeepAlive(time.Duration(ctl.clientCfg.DialServerKeepAlive)*time.Second),
- libdial.WithProxy(proxyType, addr),
- libdial.WithProxyAuth(auth),
- libdial.WithTLSConfig(tlsConfig),
- libdial.WithAfterHook(libdial.AfterHook{
- Hook: frpNet.DialHookCustomTLSHeadByte(tlsConfig != nil, ctl.clientCfg.DisableCustomTLSFirstByte),
- }),
- )
- conn, err = libdial.Dial(
- net.JoinHostPort(ctl.clientCfg.ServerAddr, strconv.Itoa(ctl.clientCfg.ServerPort)),
- dialOptions...,
- )
- if err != nil {
- xl.Warn("start new connection to server error: %v", err)
- return nil, err
- }
- }
- return
+ return ctl.cm.Connect()
}
// reader read all messages from frps and send to readCh
@@ -400,25 +326,20 @@ func (ctl *Control) worker() {
go ctl.reader()
go ctl.writer()
- select {
- case <-ctl.closedCh:
- // close related channels and wait until other goroutines done
- close(ctl.readCh)
- ctl.readerShutdown.WaitDone()
- ctl.msgHandlerShutdown.WaitDone()
+ <-ctl.closedCh
+ // close related channels and wait until other goroutines done
+ close(ctl.readCh)
+ ctl.readerShutdown.WaitDone()
+ ctl.msgHandlerShutdown.WaitDone()
- close(ctl.sendCh)
- ctl.writerShutdown.WaitDone()
+ close(ctl.sendCh)
+ ctl.writerShutdown.WaitDone()
- ctl.pm.Close()
- ctl.vm.Close()
+ ctl.pm.Close()
+ ctl.vm.Close()
- close(ctl.closedDoneCh)
- if ctl.session != nil {
- ctl.session.Close()
- }
- return
- }
+ close(ctl.closedDoneCh)
+ ctl.cm.Close()
}
func (ctl *Control) ReloadConf(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf) error {
diff --git a/client/event/event.go b/client/event/event.go
index f9718448823..bf7090d9a30 100644
--- a/client/event/event.go
+++ b/client/event/event.go
@@ -6,18 +6,9 @@ import (
"github.com/fatedier/frp/pkg/msg"
)
-type Type int
+var ErrPayloadType = errors.New("error payload type")
-const (
- EvStartProxy Type = iota
- EvCloseProxy
-)
-
-var (
- ErrPayloadType = errors.New("error payload type")
-)
-
-type Handler func(evType Type, payload interface{}) error
+type Handler func(payload interface{}) error
type StartProxyPayload struct {
NewProxyMsg *msg.NewProxy
diff --git a/client/health/health.go b/client/health/health.go
index 829bee3df9f..0ee3d04ac9c 100644
--- a/client/health/health.go
+++ b/client/health/health.go
@@ -26,9 +26,7 @@ import (
"github.com/fatedier/frp/pkg/util/xlog"
)
-var (
- ErrHealthCheckType = errors.New("error health check type")
-)
+var ErrHealthCheckType = errors.New("error health check type")
type Monitor struct {
checkType string
@@ -54,8 +52,8 @@ type Monitor struct {
func NewMonitor(ctx context.Context, checkType string,
intervalS int, timeoutS int, maxFailedTimes int,
addr string, url string,
- statusNormalFn func(), statusFailedFn func()) *Monitor {
-
+ statusNormalFn func(), statusFailedFn func(),
+) *Monitor {
if intervalS <= 0 {
intervalS = 10
}
@@ -152,7 +150,7 @@ func (monitor *Monitor) doTCPCheck(ctx context.Context) error {
}
func (monitor *Monitor) doHTTPCheck(ctx context.Context) error {
- req, err := http.NewRequest("GET", monitor.url, nil)
+ req, err := http.NewRequestWithContext(ctx, "GET", monitor.url, nil)
if err != nil {
return err
}
@@ -161,7 +159,7 @@ func (monitor *Monitor) doHTTPCheck(ctx context.Context) error {
return err
}
defer resp.Body.Close()
- io.Copy(io.Discard, resp.Body)
+ _, _ = io.Copy(io.Discard, resp.Body)
if resp.StatusCode/100 != 2 {
return fmt.Errorf("do http health check, StatusCode is [%d] not 2xx", resp.StatusCode)
diff --git a/client/proxy/proxy.go b/client/proxy/proxy.go
index 340da950c30..158773bc007 100644
--- a/client/proxy/proxy.go
+++ b/client/proxy/proxy.go
@@ -24,14 +24,6 @@ import (
"sync"
"time"
- "github.com/fatedier/frp/pkg/config"
- "github.com/fatedier/frp/pkg/msg"
- plugin "github.com/fatedier/frp/pkg/plugin/client"
- "github.com/fatedier/frp/pkg/proto/udp"
- "github.com/fatedier/frp/pkg/util/limit"
- frpNet "github.com/fatedier/frp/pkg/util/net"
- "github.com/fatedier/frp/pkg/util/xlog"
-
"github.com/fatedier/golib/errors"
frpIo "github.com/fatedier/golib/io"
libdial "github.com/fatedier/golib/net/dial"
@@ -39,6 +31,14 @@ import (
fmux "github.com/hashicorp/yamux"
pp "github.com/pires/go-proxyproto"
"golang.org/x/time/rate"
+
+ "github.com/fatedier/frp/pkg/config"
+ "github.com/fatedier/frp/pkg/msg"
+ plugin "github.com/fatedier/frp/pkg/plugin/client"
+ "github.com/fatedier/frp/pkg/proto/udp"
+ "github.com/fatedier/frp/pkg/util/limit"
+ frpNet "github.com/fatedier/frp/pkg/util/net"
+ "github.com/fatedier/frp/pkg/util/xlog"
)
// Proxy defines how to handle work connections for different proxy type.
@@ -322,7 +322,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
// Wait for client address at most 5 seconds.
var natHoleRespMsg msg.NatHoleResp
- clientConn.SetReadDeadline(time.Now().Add(5 * time.Second))
+ _ = clientConn.SetReadDeadline(time.Now().Add(5 * time.Second))
buf := pool.GetBuf(1024)
n, err := clientConn.Read(buf)
@@ -335,8 +335,8 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
xl.Error("get natHoleRespMsg error: %v", err)
return
}
- clientConn.SetReadDeadline(time.Time{})
- clientConn.Close()
+ _ = clientConn.SetReadDeadline(time.Time{})
+ _ = clientConn.Close()
if natHoleRespMsg.Error != "" {
xl.Error("natHoleRespMsg get error info: %s", natHoleRespMsg.Error)
@@ -357,10 +357,13 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
xl.Error("get natHoleResp visitor address error: %v", natHoleRespMsg.VisitorAddr)
return
}
- pxy.sendDetectMsg(host, int(port), laddr, []byte(natHoleRespMsg.Sid))
+ _ = pxy.sendDetectMsg(host, int(port), laddr, []byte(natHoleRespMsg.Sid))
xl.Trace("send all detect msg done")
- msg.WriteMsg(conn, &msg.NatHoleClientDetectOK{})
+ if err := msg.WriteMsg(conn, &msg.NatHoleClientDetectOK{}); err != nil {
+ xl.Error("write message error: %v", err)
+ return
+ }
// Listen for clientConn's address and wait for visitor connection
lConn, err := net.ListenUDP("udp", laddr)
@@ -370,7 +373,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
}
defer lConn.Close()
- lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
+ _ = lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
sidBuf := pool.GetBuf(1024)
var uAddr *net.UDPAddr
n, uAddr, err = lConn.ReadFromUDP(sidBuf)
@@ -378,7 +381,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
xl.Warn("get sid from visitor error: %v", err)
return
}
- lConn.SetReadDeadline(time.Time{})
+ _ = lConn.SetReadDeadline(time.Time{})
if string(sidBuf[:n]) != natHoleRespMsg.Sid {
xl.Warn("incorrect sid from visitor")
return
@@ -386,7 +389,10 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
pool.PutBuf(sidBuf)
xl.Info("nat hole connection make success, sid [%s]", natHoleRespMsg.Sid)
- lConn.WriteToUDP(sidBuf[:n], uAddr)
+ if _, err := lConn.WriteToUDP(sidBuf[:n], uAddr); err != nil {
+ xl.Error("write uaddr error: %v", err)
+ return
+ }
kcpConn, err := frpNet.NewKCPConnFromUDP(lConn, false, uAddr.String())
if err != nil {
@@ -424,12 +430,13 @@ func (pxy *XTCPProxy) sendDetectMsg(addr string, port int, laddr *net.UDPAddr, c
return err
}
- //uConn := ipv4.NewConn(tConn)
- //uConn.SetTTL(3)
+ // uConn := ipv4.NewConn(tConn)
+ // uConn.SetTTL(3)
- tConn.Write(content)
- tConn.Close()
- return nil
+ if _, err := tConn.Write(content); err != nil {
+ return err
+ }
+ return tConn.Close()
}
// UDP
@@ -539,7 +546,7 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
}
}
}
- heartbeatFn := func(conn net.Conn, sendCh chan msg.Message) {
+ heartbeatFn := func(sendCh chan msg.Message) {
var errRet error
for {
time.Sleep(time.Duration(30) * time.Second)
@@ -554,7 +561,7 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
go workConnSenderFn(pxy.workConn, pxy.sendCh)
go workConnReaderFn(pxy.workConn, pxy.readCh)
- go heartbeatFn(pxy.workConn, pxy.sendCh)
+ go heartbeatFn(pxy.sendCh)
udp.Forwarder(pxy.localAddr, pxy.readCh, pxy.sendCh, int(pxy.clientCfg.UDPPacketSize))
}
@@ -685,7 +692,7 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
}
}
- heartbeatFn := func(conn net.Conn, sendCh chan msg.Message) {
+ heartbeatFn := func(sendCh chan msg.Message) {
ticker := time.NewTicker(30 * time.Second)
defer func() {
ticker.Stop()
@@ -711,14 +718,15 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
go workConnSenderFn(workConn, sendCh)
go workConnReaderFn(workConn, readCh)
- go heartbeatFn(workConn, sendCh)
+ go heartbeatFn(sendCh)
udp.Forwarder(pxy.localAddr, readCh, sendCh, int(pxy.clientCfg.UDPPacketSize))
}
// Common handler for tcp work connections.
func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf, proxyPlugin plugin.Plugin,
- baseInfo *config.BaseProxyConf, limiter *rate.Limiter, workConn net.Conn, encKey []byte, m *msg.StartWorkConn) {
+ baseInfo *config.BaseProxyConf, limiter *rate.Limiter, workConn net.Conn, encKey []byte, m *msg.StartWorkConn,
+) {
xl := xlog.FromContextSafe(ctx)
var (
remote io.ReadWriteCloser
@@ -773,7 +781,7 @@ func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf
}
buf := bytes.NewBuffer(nil)
- h.WriteTo(buf)
+ _, _ = h.WriteTo(buf)
extraInfo = buf.Bytes()
}
}
@@ -800,7 +808,11 @@ func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf
localConn.RemoteAddr().String(), workConn.LocalAddr().String(), workConn.RemoteAddr().String())
if len(extraInfo) > 0 {
- localConn.Write(extraInfo)
+ if _, err := localConn.Write(extraInfo); err != nil {
+ workConn.Close()
+ xl.Error("write extraInfo to local conn error: %v", err)
+ return
+ }
}
frpIo.Join(localConn, remote)
diff --git a/client/proxy/proxy_manager.go b/client/proxy/proxy_manager.go
index 98c17faa984..563531e81df 100644
--- a/client/proxy/proxy_manager.go
+++ b/client/proxy/proxy_manager.go
@@ -6,12 +6,12 @@ import (
"net"
"sync"
+ "github.com/fatedier/golib/errors"
+
"github.com/fatedier/frp/client/event"
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/msg"
"github.com/fatedier/frp/pkg/util/xlog"
-
- "github.com/fatedier/golib/errors"
)
type Manager struct {
@@ -75,7 +75,7 @@ func (pm *Manager) HandleWorkConn(name string, workConn net.Conn, m *msg.StartWo
}
}
-func (pm *Manager) HandleEvent(evType event.Type, payload interface{}) error {
+func (pm *Manager) HandleEvent(payload interface{}) error {
var m msg.Message
switch e := payload.(type) {
case *event.StartProxyPayload:
@@ -113,10 +113,8 @@ func (pm *Manager) Reload(pxyCfgs map[string]config.ProxyConf) {
cfg, ok := pxyCfgs[name]
if !ok {
del = true
- } else {
- if !pxy.Cfg.Compare(cfg) {
- del = true
- }
+ } else if !pxy.Cfg.Compare(cfg) {
+ del = true
}
if del {
diff --git a/client/proxy/proxy_wrapper.go b/client/proxy/proxy_wrapper.go
index a6f0233bd3f..af217f06d1b 100644
--- a/client/proxy/proxy_wrapper.go
+++ b/client/proxy/proxy_wrapper.go
@@ -8,13 +8,13 @@ import (
"sync/atomic"
"time"
+ "github.com/fatedier/golib/errors"
+
"github.com/fatedier/frp/client/event"
"github.com/fatedier/frp/client/health"
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/msg"
"github.com/fatedier/frp/pkg/util/xlog"
-
- "github.com/fatedier/golib/errors"
)
const (
@@ -27,9 +27,9 @@ const (
)
var (
- statusCheckInterval time.Duration = 3 * time.Second
- waitResponseTimeout = 20 * time.Second
- startErrTimeout = 30 * time.Second
+ statusCheckInterval = 3 * time.Second
+ waitResponseTimeout = 20 * time.Second
+ startErrTimeout = 30 * time.Second
)
type WorkingStatus struct {
@@ -145,7 +145,7 @@ func (pw *Wrapper) Stop() {
}
func (pw *Wrapper) close() {
- pw.handler(event.EvCloseProxy, &event.CloseProxyPayload{
+ _ = pw.handler(&event.CloseProxyPayload{
CloseProxyMsg: &msg.CloseProxy{
ProxyName: pw.Name,
},
@@ -174,7 +174,7 @@ func (pw *Wrapper) checkWorker() {
var newProxyMsg msg.NewProxy
pw.Cfg.MarshalToMsg(&newProxyMsg)
pw.lastSendStartMsg = now
- pw.handler(event.EvStartProxy, &event.StartProxyPayload{
+ _ = pw.handler(&event.StartProxyPayload{
NewProxyMsg: &newProxyMsg,
})
}
@@ -201,7 +201,7 @@ func (pw *Wrapper) checkWorker() {
func (pw *Wrapper) statusNormalCallback() {
xl := pw.xl
atomic.StoreUint32(&pw.health, 0)
- errors.PanicToError(func() {
+ _ = errors.PanicToError(func() {
select {
case pw.healthNotifyCh <- struct{}{}:
default:
@@ -213,7 +213,7 @@ func (pw *Wrapper) statusNormalCallback() {
func (pw *Wrapper) statusFailedCallback() {
xl := pw.xl
atomic.StoreUint32(&pw.health, 1)
- errors.PanicToError(func() {
+ _ = errors.PanicToError(func() {
select {
case pw.healthNotifyCh <- struct{}{}:
default:
diff --git a/client/service.go b/client/service.go
index 30bd3f8f5bc..b72fea7731d 100644
--- a/client/service.go
+++ b/client/service.go
@@ -28,6 +28,11 @@ import (
"sync/atomic"
"time"
+ "github.com/fatedier/golib/crypto"
+ libdial "github.com/fatedier/golib/net/dial"
+ fmux "github.com/hashicorp/yamux"
+ quic "github.com/lucas-clemente/quic-go"
+
"github.com/fatedier/frp/assets"
"github.com/fatedier/frp/pkg/auth"
"github.com/fatedier/frp/pkg/config"
@@ -38,10 +43,6 @@ import (
"github.com/fatedier/frp/pkg/util/util"
"github.com/fatedier/frp/pkg/util/version"
"github.com/fatedier/frp/pkg/util/xlog"
- "github.com/fatedier/golib/crypto"
- libdial "github.com/fatedier/golib/net/dial"
-
- fmux "github.com/hashicorp/yamux"
)
func init() {
@@ -81,8 +82,12 @@ type Service struct {
cancel context.CancelFunc
}
-func NewService(cfg config.ClientCommonConf, pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf, cfgFile string) (svr *Service, err error) {
-
+func NewService(
+ cfg config.ClientCommonConf,
+ pxyCfgs map[string]config.ProxyConf,
+ visitorCfgs map[string]config.VisitorConf,
+ cfgFile string,
+) (svr *Service, err error) {
ctx, cancel := context.WithCancel(context.Background())
svr = &Service{
authSetter: auth.NewAuthSetter(cfg.ClientConfig),
@@ -123,7 +128,7 @@ func (svr *Service) Run() error {
// login to frps
for {
- conn, session, err := svr.login()
+ conn, cm, err := svr.login()
if err != nil {
xl.Warn("login to server failed: %v", err)
@@ -135,7 +140,7 @@ func (svr *Service) Run() error {
util.RandomSleep(10*time.Second, 0.9, 1.1)
} else {
// login success
- ctl := NewControl(svr.ctx, svr.runID, conn, session, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort, svr.authSetter)
+ ctl := NewControl(svr.ctx, svr.runID, conn, cm, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort, svr.authSetter)
ctl.Run()
svr.ctlMu.Lock()
svr.ctl = ctl
@@ -198,13 +203,17 @@ func (svr *Service) keepControllerWorking() {
}
for {
+ if atomic.LoadUint32(&svr.exit) != 0 {
+ return
+ }
+
xl.Info("try to reconnect to server...")
- conn, session, err := svr.login()
+ conn, cm, err := svr.login()
if err != nil {
xl.Warn("reconnect to server error: %v, wait %v for another retry", err, delayTime)
util.RandomSleep(delayTime, 0.9, 1.1)
- delayTime = delayTime * 2
+ delayTime *= 2
if delayTime > maxDelayTime {
delayTime = maxDelayTime
}
@@ -213,7 +222,7 @@ func (svr *Service) keepControllerWorking() {
// reconnect success, init delayTime
delayTime = time.Second
- ctl := NewControl(svr.ctx, svr.runID, conn, session, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort, svr.authSetter)
+ ctl := NewControl(svr.ctx, svr.runID, conn, cm, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort, svr.authSetter)
ctl.Run()
svr.ctlMu.Lock()
if svr.ctl != nil {
@@ -229,83 +238,23 @@ func (svr *Service) keepControllerWorking() {
// login creates a connection to frps and registers it self as a client
// conn: control connection
// session: if it's not nil, using tcp mux
-func (svr *Service) login() (conn net.Conn, session *fmux.Session, err error) {
+func (svr *Service) login() (conn net.Conn, cm *ConnectionManager, err error) {
xl := xlog.FromContextSafe(svr.ctx)
- var tlsConfig *tls.Config
- if svr.cfg.TLSEnable {
- sn := svr.cfg.TLSServerName
- if sn == "" {
- sn = svr.cfg.ServerAddr
- }
+ cm = NewConnectionManager(svr.ctx, &svr.cfg)
- tlsConfig, err = transport.NewClientTLSConfig(
- svr.cfg.TLSCertFile,
- svr.cfg.TLSKeyFile,
- svr.cfg.TLSTrustedCaFile,
- sn)
- if err != nil {
- xl.Warn("fail to build tls configuration when service login, err: %v", err)
- return
- }
- }
-
- proxyType, addr, auth, err := libdial.ParseProxyURL(svr.cfg.HTTPProxy)
- if err != nil {
- xl.Error("fail to parse proxy url")
- return
- }
- dialOptions := []libdial.DialOption{}
- protocol := svr.cfg.Protocol
- if protocol == "websocket" {
- protocol = "tcp"
- dialOptions = append(dialOptions, libdial.WithAfterHook(libdial.AfterHook{Hook: frpNet.DialHookWebsocket()}))
- }
- if svr.cfg.ConnectServerLocalIP != "" {
- dialOptions = append(dialOptions, libdial.WithLocalAddr(svr.cfg.ConnectServerLocalIP))
- }
- dialOptions = append(dialOptions,
- libdial.WithProtocol(protocol),
- libdial.WithTimeout(time.Duration(svr.cfg.DialServerTimeout)*time.Second),
- libdial.WithKeepAlive(time.Duration(svr.cfg.DialServerKeepAlive)*time.Second),
- libdial.WithProxy(proxyType, addr),
- libdial.WithProxyAuth(auth),
- libdial.WithTLSConfig(tlsConfig),
- libdial.WithAfterHook(libdial.AfterHook{
- Hook: frpNet.DialHookCustomTLSHeadByte(tlsConfig != nil, svr.cfg.DisableCustomTLSFirstByte),
- }),
- )
- conn, err = libdial.Dial(
- net.JoinHostPort(svr.cfg.ServerAddr, strconv.Itoa(svr.cfg.ServerPort)),
- dialOptions...,
- )
- if err != nil {
- return
+ if err = cm.OpenConnection(); err != nil {
+ return nil, nil, err
}
defer func() {
if err != nil {
- conn.Close()
- if session != nil {
- session.Close()
- }
+ cm.Close()
}
}()
- if svr.cfg.TCPMux {
- fmuxCfg := fmux.DefaultConfig()
- fmuxCfg.KeepAliveInterval = time.Duration(svr.cfg.TCPMuxKeepaliveInterval) * time.Second
- fmuxCfg.LogOutput = io.Discard
- session, err = fmux.Client(conn, fmuxCfg)
- if err != nil {
- return
- }
- stream, errRet := session.OpenStream()
- if errRet != nil {
- session.Close()
- err = errRet
- return
- }
- conn = stream
+ conn, err = cm.Connect()
+ if err != nil {
+ return
}
loginMsg := &msg.Login{
@@ -329,11 +278,11 @@ func (svr *Service) login() (conn net.Conn, session *fmux.Session, err error) {
}
var loginRespMsg msg.LoginResp
- conn.SetReadDeadline(time.Now().Add(10 * time.Second))
+ _ = conn.SetReadDeadline(time.Now().Add(10 * time.Second))
if err = msg.ReadMsgInto(conn, &loginRespMsg); err != nil {
return
}
- conn.SetReadDeadline(time.Time{})
+ _ = conn.SetReadDeadline(time.Time{})
if loginRespMsg.Error != "" {
err = fmt.Errorf("%s", loginRespMsg.Error)
@@ -381,3 +330,159 @@ func (svr *Service) GracefulClose(d time.Duration) {
svr.cancel()
}
+
+type ConnectionManager struct {
+ ctx context.Context
+ cfg *config.ClientCommonConf
+
+ muxSession *fmux.Session
+ quicConn quic.Connection
+}
+
+func NewConnectionManager(ctx context.Context, cfg *config.ClientCommonConf) *ConnectionManager {
+ return &ConnectionManager{
+ ctx: ctx,
+ cfg: cfg,
+ }
+}
+
+func (cm *ConnectionManager) OpenConnection() error {
+ xl := xlog.FromContextSafe(cm.ctx)
+
+ // special for quic
+ if strings.EqualFold(cm.cfg.Protocol, "quic") {
+ var tlsConfig *tls.Config
+ var err error
+ sn := cm.cfg.TLSServerName
+ if sn == "" {
+ sn = cm.cfg.ServerAddr
+ }
+ if cm.cfg.TLSEnable {
+ tlsConfig, err = transport.NewClientTLSConfig(
+ cm.cfg.TLSCertFile,
+ cm.cfg.TLSKeyFile,
+ cm.cfg.TLSTrustedCaFile,
+ sn)
+ } else {
+ tlsConfig, err = transport.NewClientTLSConfig("", "", "", sn)
+ }
+ if err != nil {
+ xl.Warn("fail to build tls configuration, err: %v", err)
+ return err
+ }
+ tlsConfig.NextProtos = []string{"frp"}
+
+ conn, err := quic.DialAddr(
+ net.JoinHostPort(cm.cfg.ServerAddr, strconv.Itoa(cm.cfg.ServerPort)),
+ tlsConfig, &quic.Config{
+ MaxIdleTimeout: time.Duration(cm.cfg.QUICMaxIdleTimeout) * time.Second,
+ MaxIncomingStreams: int64(cm.cfg.QUICMaxIncomingStreams),
+ KeepAlivePeriod: time.Duration(cm.cfg.QUICKeepalivePeriod) * time.Second,
+ })
+ if err != nil {
+ return err
+ }
+ cm.quicConn = conn
+ return nil
+ }
+
+ if !cm.cfg.TCPMux {
+ return nil
+ }
+
+ conn, err := cm.realConnect()
+ if err != nil {
+ return err
+ }
+
+ fmuxCfg := fmux.DefaultConfig()
+ fmuxCfg.KeepAliveInterval = time.Duration(cm.cfg.TCPMuxKeepaliveInterval) * time.Second
+ fmuxCfg.LogOutput = io.Discard
+ session, err := fmux.Client(conn, fmuxCfg)
+ if err != nil {
+ return err
+ }
+ cm.muxSession = session
+ return nil
+}
+
+func (cm *ConnectionManager) Connect() (net.Conn, error) {
+ if cm.quicConn != nil {
+ stream, err := cm.quicConn.OpenStreamSync(context.Background())
+ if err != nil {
+ return nil, err
+ }
+ return frpNet.QuicStreamToNetConn(stream, cm.quicConn), nil
+ } else if cm.muxSession != nil {
+ stream, err := cm.muxSession.OpenStream()
+ if err != nil {
+ return nil, err
+ }
+ return stream, nil
+ }
+
+ return cm.realConnect()
+}
+
+func (cm *ConnectionManager) realConnect() (net.Conn, error) {
+ xl := xlog.FromContextSafe(cm.ctx)
+ var tlsConfig *tls.Config
+ var err error
+ if cm.cfg.TLSEnable {
+ sn := cm.cfg.TLSServerName
+ if sn == "" {
+ sn = cm.cfg.ServerAddr
+ }
+
+ tlsConfig, err = transport.NewClientTLSConfig(
+ cm.cfg.TLSCertFile,
+ cm.cfg.TLSKeyFile,
+ cm.cfg.TLSTrustedCaFile,
+ sn)
+ if err != nil {
+ xl.Warn("fail to build tls configuration, err: %v", err)
+ return nil, err
+ }
+ }
+
+ proxyType, addr, auth, err := libdial.ParseProxyURL(cm.cfg.HTTPProxy)
+ if err != nil {
+ xl.Error("fail to parse proxy url")
+ return nil, err
+ }
+ dialOptions := []libdial.DialOption{}
+ protocol := cm.cfg.Protocol
+ if protocol == "websocket" {
+ protocol = "tcp"
+ dialOptions = append(dialOptions, libdial.WithAfterHook(libdial.AfterHook{Hook: frpNet.DialHookWebsocket()}))
+ }
+ if cm.cfg.ConnectServerLocalIP != "" {
+ dialOptions = append(dialOptions, libdial.WithLocalAddr(cm.cfg.ConnectServerLocalIP))
+ }
+ dialOptions = append(dialOptions,
+ libdial.WithProtocol(protocol),
+ libdial.WithTimeout(time.Duration(cm.cfg.DialServerTimeout)*time.Second),
+ libdial.WithKeepAlive(time.Duration(cm.cfg.DialServerKeepAlive)*time.Second),
+ libdial.WithProxy(proxyType, addr),
+ libdial.WithProxyAuth(auth),
+ libdial.WithTLSConfig(tlsConfig),
+ libdial.WithAfterHook(libdial.AfterHook{
+ Hook: frpNet.DialHookCustomTLSHeadByte(tlsConfig != nil, cm.cfg.DisableCustomTLSFirstByte),
+ }),
+ )
+ conn, err := libdial.Dial(
+ net.JoinHostPort(cm.cfg.ServerAddr, strconv.Itoa(cm.cfg.ServerPort)),
+ dialOptions...,
+ )
+ return conn, err
+}
+
+func (cm *ConnectionManager) Close() error {
+ if cm.quicConn != nil {
+ _ = cm.quicConn.CloseWithError(0, "")
+ }
+ if cm.muxSession != nil {
+ _ = cm.muxSession.Close()
+ }
+ return nil
+}
diff --git a/client/visitor.go b/client/visitor.go
index ba1cd7cb98b..1d7386f70db 100644
--- a/client/visitor.go
+++ b/client/visitor.go
@@ -24,17 +24,17 @@ import (
"sync"
"time"
+ "github.com/fatedier/golib/errors"
+ frpIo "github.com/fatedier/golib/io"
+ "github.com/fatedier/golib/pool"
+ fmux "github.com/hashicorp/yamux"
+
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/msg"
"github.com/fatedier/frp/pkg/proto/udp"
frpNet "github.com/fatedier/frp/pkg/util/net"
"github.com/fatedier/frp/pkg/util/util"
"github.com/fatedier/frp/pkg/util/xlog"
-
- "github.com/fatedier/golib/errors"
- frpIo "github.com/fatedier/golib/io"
- "github.com/fatedier/golib/pool"
- fmux "github.com/hashicorp/yamux"
)
// Visitor is used for forward traffics from local port tot remote service.
@@ -71,9 +71,8 @@ func NewVisitor(ctx context.Context, ctl *Control, cfg config.VisitorConf) (visi
}
type BaseVisitor struct {
- ctl *Control
- l net.Listener
- closed bool
+ ctl *Control
+ l net.Listener
mu sync.RWMutex
ctx context.Context
@@ -138,13 +137,13 @@ func (sv *STCPVisitor) handleConn(userConn net.Conn) {
}
var newVisitorConnRespMsg msg.NewVisitorConnResp
- visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
+ _ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
if err != nil {
xl.Warn("get newVisitorConnRespMsg error: %v", err)
return
}
- visitorConn.SetReadDeadline(time.Time{})
+ _ = visitorConn.SetReadDeadline(time.Time{})
if newVisitorConnRespMsg.Error != "" {
xl.Warn("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
@@ -239,7 +238,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
// Wait for client address at most 10 seconds.
var natHoleRespMsg msg.NatHoleResp
- visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
+ _ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
buf := pool.GetBuf(1024)
n, err := visitorConn.Read(buf)
if err != nil {
@@ -252,7 +251,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
xl.Warn("get natHoleRespMsg error: %v", err)
return
}
- visitorConn.SetReadDeadline(time.Time{})
+ _ = visitorConn.SetReadDeadline(time.Time{})
pool.PutBuf(buf)
if natHoleRespMsg.Error != "" {
@@ -279,17 +278,20 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
}
defer lConn.Close()
- lConn.Write([]byte(natHoleRespMsg.Sid))
+ if _, err := lConn.Write([]byte(natHoleRespMsg.Sid)); err != nil {
+ xl.Error("write sid error: %v", err)
+ return
+ }
// read ack sid from client
sidBuf := pool.GetBuf(1024)
- lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
+ _ = lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
n, err = lConn.Read(sidBuf)
if err != nil {
xl.Warn("get sid from client error: %v", err)
return
}
- lConn.SetReadDeadline(time.Time{})
+ _ = lConn.SetReadDeadline(time.Time{})
if string(sidBuf[:n]) != natHoleRespMsg.Sid {
xl.Warn("incorrect sid from client")
return
@@ -411,7 +413,6 @@ func (sv *SUDPVisitor) dispatcher() {
default:
}
}
-
}
func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
@@ -437,13 +438,13 @@ func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
)
// frpc will send heartbeat in workConn to frpc visitor for keeping alive
- conn.SetReadDeadline(time.Now().Add(60 * time.Second))
+ _ = conn.SetReadDeadline(time.Now().Add(60 * time.Second))
if rawMsg, errRet = msg.ReadMsg(conn); errRet != nil {
xl.Warn("read from workconn for user udp conn error: %v", errRet)
return
}
- conn.SetReadDeadline(time.Time{})
+ _ = conn.SetReadDeadline(time.Time{})
switch m := rawMsg.(type) {
case *msg.Ping:
xl.Debug("frpc visitor get ping message from frpc")
@@ -523,12 +524,12 @@ func (sv *SUDPVisitor) getNewVisitorConn() (net.Conn, error) {
}
var newVisitorConnRespMsg msg.NewVisitorConnResp
- visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
+ _ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
if err != nil {
return nil, fmt.Errorf("frpc read newVisitorConnRespMsg error: %v", err)
}
- visitorConn.SetReadDeadline(time.Time{})
+ _ = visitorConn.SetReadDeadline(time.Time{})
if newVisitorConnRespMsg.Error != "" {
return nil, fmt.Errorf("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
diff --git a/client/visitor_manager.go b/client/visitor_manager.go
index 642b21e8f2f..8df47150937 100644
--- a/client/visitor_manager.go
+++ b/client/visitor_manager.go
@@ -65,7 +65,7 @@ func (vm *VisitorManager) Run() {
name := cfg.GetBaseInfo().ProxyName
if _, exist := vm.visitors[name]; !exist {
xl.Info("try to start visitor [%s]", name)
- vm.startVisitor(cfg)
+ _ = vm.startVisitor(cfg)
}
}
vm.mu.Unlock()
@@ -99,10 +99,8 @@ func (vm *VisitorManager) Reload(cfgs map[string]config.VisitorConf) {
cfg, ok := cfgs[name]
if !ok {
del = true
- } else {
- if !oldCfg.Compare(cfg) {
- del = true
- }
+ } else if !oldCfg.Compare(cfg) {
+ del = true
}
if del {
@@ -123,13 +121,12 @@ func (vm *VisitorManager) Reload(cfgs map[string]config.VisitorConf) {
if _, ok := vm.cfgs[name]; !ok {
vm.cfgs[name] = cfg
addNames = append(addNames, name)
- vm.startVisitor(cfg)
+ _ = vm.startVisitor(cfg)
}
}
if len(addNames) > 0 {
xl.Info("visitor added: %v", addNames)
}
- return
}
func (vm *VisitorManager) Close() {
diff --git a/cmd/frpc/sub/http.go b/cmd/frpc/sub/http.go
index 2e19fce4f67..4e193b7e2b5 100644
--- a/cmd/frpc/sub/http.go
+++ b/cmd/frpc/sub/http.go
@@ -19,10 +19,10 @@ import (
"os"
"strings"
+ "github.com/spf13/cobra"
+
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/consts"
-
- "github.com/spf13/cobra"
)
func init() {
diff --git a/cmd/frpc/sub/reload.go b/cmd/frpc/sub/reload.go
index c625daedb43..258317e7d6a 100644
--- a/cmd/frpc/sub/reload.go
+++ b/cmd/frpc/sub/reload.go
@@ -22,9 +22,9 @@ import (
"os"
"strings"
- "github.com/fatedier/frp/pkg/config"
-
"github.com/spf13/cobra"
+
+ "github.com/fatedier/frp/pkg/config"
)
func init() {
diff --git a/cmd/frpc/sub/root.go b/cmd/frpc/sub/root.go
index f8d7eb17708..cea8ecc6876 100644
--- a/cmd/frpc/sub/root.go
+++ b/cmd/frpc/sub/root.go
@@ -26,13 +26,13 @@ import (
"syscall"
"time"
+ "github.com/spf13/cobra"
+
"github.com/fatedier/frp/client"
"github.com/fatedier/frp/pkg/auth"
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/util/log"
"github.com/fatedier/frp/pkg/util/version"
-
- "github.com/spf13/cobra"
)
const (
@@ -107,7 +107,7 @@ var rootCmd = &cobra.Command{
// Note that it's only designed for testing. It's not guaranteed to be stable.
if cfgDir != "" {
var wg sync.WaitGroup
- filepath.WalkDir(cfgDir, func(path string, d fs.DirEntry, err error) error {
+ _ = filepath.WalkDir(cfgDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return nil
}
@@ -183,7 +183,7 @@ func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) {
cfg.Complete()
if err = cfg.Validate(); err != nil {
- err = fmt.Errorf("Parse config error: %v", err)
+ err = fmt.Errorf("parse config error: %v", err)
return
}
return
@@ -203,7 +203,6 @@ func startService(
visitorCfgs map[string]config.VisitorConf,
cfgFile string,
) (err error) {
-
log.InitLog(cfg.LogWay, cfg.LogFile, cfg.LogLevel,
cfg.LogMaxDays, cfg.DisableLogColor)
diff --git a/cmd/frpc/sub/status.go b/cmd/frpc/sub/status.go
index 52c1c1954cf..c9a6a98dec5 100644
--- a/cmd/frpc/sub/status.go
+++ b/cmd/frpc/sub/status.go
@@ -23,11 +23,11 @@ import (
"os"
"strings"
- "github.com/fatedier/frp/client"
- "github.com/fatedier/frp/pkg/config"
-
"github.com/rodaine/table"
"github.com/spf13/cobra"
+
+ "github.com/fatedier/frp/client"
+ "github.com/fatedier/frp/pkg/config"
)
func init() {
diff --git a/cmd/frpc/sub/stcp.go b/cmd/frpc/sub/stcp.go
index 45f01e59872..989387bb795 100644
--- a/cmd/frpc/sub/stcp.go
+++ b/cmd/frpc/sub/stcp.go
@@ -18,10 +18,10 @@ import (
"fmt"
"os"
+ "github.com/spf13/cobra"
+
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/consts"
-
- "github.com/spf13/cobra"
)
func init() {
diff --git a/cmd/frpc/sub/sudp.go b/cmd/frpc/sub/sudp.go
index 45c5ad61b2d..c781223ddb5 100644
--- a/cmd/frpc/sub/sudp.go
+++ b/cmd/frpc/sub/sudp.go
@@ -18,10 +18,10 @@ import (
"fmt"
"os"
+ "github.com/spf13/cobra"
+
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/consts"
-
- "github.com/spf13/cobra"
)
func init() {
diff --git a/cmd/frpc/sub/udp.go b/cmd/frpc/sub/udp.go
index 2ce4327e4dd..984ad068d95 100644
--- a/cmd/frpc/sub/udp.go
+++ b/cmd/frpc/sub/udp.go
@@ -18,10 +18,10 @@ import (
"fmt"
"os"
+ "github.com/spf13/cobra"
+
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/consts"
-
- "github.com/spf13/cobra"
)
func init() {
diff --git a/cmd/frpc/sub/verify.go b/cmd/frpc/sub/verify.go
index 76872b90b82..c86b1e82b9c 100644
--- a/cmd/frpc/sub/verify.go
+++ b/cmd/frpc/sub/verify.go
@@ -18,9 +18,9 @@ import (
"fmt"
"os"
- "github.com/fatedier/frp/pkg/config"
-
"github.com/spf13/cobra"
+
+ "github.com/fatedier/frp/pkg/config"
)
func init() {
diff --git a/cmd/frpc/sub/xtcp.go b/cmd/frpc/sub/xtcp.go
index 6c6c7d84bb0..069cce7e161 100644
--- a/cmd/frpc/sub/xtcp.go
+++ b/cmd/frpc/sub/xtcp.go
@@ -18,10 +18,10 @@ import (
"fmt"
"os"
+ "github.com/spf13/cobra"
+
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/consts"
-
- "github.com/spf13/cobra"
)
func init() {
diff --git a/cmd/frps/root.go b/cmd/frps/root.go
index d31944ac409..955c90fb730 100644
--- a/cmd/frps/root.go
+++ b/cmd/frps/root.go
@@ -18,14 +18,14 @@ import (
"fmt"
"os"
+ "github.com/spf13/cobra"
+
"github.com/fatedier/frp/pkg/auth"
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/util/log"
"github.com/fatedier/frp/pkg/util/util"
"github.com/fatedier/frp/pkg/util/version"
"github.com/fatedier/frp/server"
-
- "github.com/spf13/cobra"
)
const (
@@ -50,16 +50,13 @@ var (
dashboardUser string
dashboardPwd string
enablePrometheus bool
- assetsDir string
logFile string
logLevel string
logMaxDays int64
disableLogColor bool
token string
subDomainHost string
- tcpMux bool
allowPorts string
- maxPoolCount int64
maxPortsPerClient int64
tlsOnly bool
dashboardTLSMode bool
@@ -151,7 +148,7 @@ func parseServerCommonCfg(fileType int, source []byte) (cfg config.ServerCommonC
cfg.Complete()
err = cfg.Validate()
if err != nil {
- err = fmt.Errorf("Parse config error: %v", err)
+ err = fmt.Errorf("parse config error: %v", err)
return
}
return
@@ -189,7 +186,7 @@ func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) {
// e.g. 1000-2000,2001,2002,3000-4000
ports, errRet := util.ParseRangeNumbers(allowPorts)
if errRet != nil {
- err = fmt.Errorf("Parse conf error: allow_ports: %v", errRet)
+ err = fmt.Errorf("parse conf error: allow_ports: %v", errRet)
return
}
diff --git a/cmd/frps/verify.go b/cmd/frps/verify.go
index 35b2acdf181..42f2ca74b08 100644
--- a/cmd/frps/verify.go
+++ b/cmd/frps/verify.go
@@ -18,9 +18,9 @@ import (
"fmt"
"os"
- "github.com/fatedier/frp/pkg/config"
-
"github.com/spf13/cobra"
+
+ "github.com/fatedier/frp/pkg/config"
)
func init() {
diff --git a/conf/frpc_full.ini b/conf/frpc_full.ini
index 9c939678b1f..8e39de1c9f7 100644
--- a/conf/frpc_full.ini
+++ b/conf/frpc_full.ini
@@ -40,6 +40,8 @@ authenticate_new_work_conns = false
# auth token
token = 12345678
+authentication_method =
+
# oidc_client_id specifies the client ID to use to get a token in OIDC authentication if AuthenticationMethod == "oidc".
# By default, this value is "".
oidc_client_id =
@@ -51,6 +53,9 @@ oidc_client_secret =
# oidc_audience specifies the audience of the token in OIDC authentication if AuthenticationMethod == "oidc". By default, this value is "".
oidc_audience =
+# oidc_scope specifies the permisssions of the token in OIDC authentication if AuthenticationMethod == "oidc". By default, this value is "".
+oidc_scope =
+
# oidc_token_endpoint_url specifies the URL which implements OIDC Token Endpoint.
# It will be used to get an OIDC token if AuthenticationMethod == "oidc". By default, this value is "".
oidc_token_endpoint_url =
@@ -87,13 +92,18 @@ user = your_name
login_fail_exit = true
# communication protocol used to connect to server
-# now it supports tcp, kcp and websocket, default is tcp
+# supports tcp, kcp, quic and websocket now, default is tcp
protocol = tcp
# set client binding ip when connect server, default is empty.
# only when protocol = tcp or websocket, the value will be used.
connect_server_local_ip = 0.0.0.0
+# quic protocol options
+# quic_keepalive_period = 10
+# quic_max_idle_timeout = 30
+# quic_max_incoming_streams = 100000
+
# if tls_enable is true, frpc will connect frps by tls
tls_enable = true
diff --git a/conf/frps_full.ini b/conf/frps_full.ini
index 45b222f4d6e..2d5e08e172e 100644
--- a/conf/frps_full.ini
+++ b/conf/frps_full.ini
@@ -9,10 +9,18 @@ bind_port = 7000
# udp port to help make udp hole to penetrate nat
bind_udp_port = 7001
-# udp port used for kcp protocol, it can be same with 'bind_port'
-# if not set, kcp is disabled in frps
+# udp port used for kcp protocol, it can be same with 'bind_port'.
+# if not set, kcp is disabled in frps.
kcp_bind_port = 7000
+# udp port used for quic protocol.
+# if not set, quic is disabled in frps.
+# quic_bind_port = 7002
+# quic protocol options
+# quic_keepalive_period = 10
+# quic_max_idle_timeout = 30
+# quic_max_incoming_streams = 100000
+
# specify which address proxy will listen for, default value is same with bind_addr
# proxy_bind_addr = 127.0.0.1
diff --git a/dockerfiles/Dockerfile-for-frpc b/dockerfiles/Dockerfile-for-frpc
index ece950f2190..b749be0704b 100644
--- a/dockerfiles/Dockerfile-for-frpc
+++ b/dockerfiles/Dockerfile-for-frpc
@@ -1,4 +1,4 @@
-FROM golang:1.18 AS building
+FROM golang:1.19 AS building
COPY . /building
WORKDIR /building
diff --git a/dockerfiles/Dockerfile-for-frps b/dockerfiles/Dockerfile-for-frps
index d8ab8247a3a..cd716123fb1 100644
--- a/dockerfiles/Dockerfile-for-frps
+++ b/dockerfiles/Dockerfile-for-frps
@@ -1,4 +1,4 @@
-FROM golang:1.18 AS building
+FROM golang:1.19 AS building
COPY . /building
WORKDIR /building
diff --git a/go.mod b/go.mod
index 0a92dfb5a65..d518a612d0c 100644
--- a/go.mod
+++ b/go.mod
@@ -1,33 +1,76 @@
module github.com/fatedier/frp
-go 1.16
+go 1.19
require (
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
- github.com/coreos/go-oidc v2.2.1+incompatible
+ github.com/coreos/go-oidc/v3 v3.4.0
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb
github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible
- github.com/go-playground/validator/v10 v10.6.1
- github.com/google/uuid v1.2.0
+ github.com/go-playground/validator/v10 v10.11.0
+ github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
- github.com/gorilla/websocket v1.4.2
- github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c
- github.com/leodido/go-urn v1.2.1 // indirect
+ github.com/gorilla/websocket v1.5.0
+ github.com/hashicorp/yamux v0.1.1
+ github.com/lucas-clemente/quic-go v0.31.0
github.com/onsi/ginkgo v1.16.4
- github.com/onsi/gomega v1.13.0
+ github.com/onsi/gomega v1.20.2
github.com/pires/go-proxyproto v0.6.2
- github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
- github.com/prometheus/client_golang v1.11.0
+ github.com/prometheus/client_golang v1.13.0
github.com/rodaine/table v1.0.1
github.com/spf13/cobra v1.1.3
github.com/stretchr/testify v1.7.0
- golang.org/x/net v0.0.0-20210428140749-89ef3d95e781
- golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
- golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
- golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
- gopkg.in/ini.v1 v1.62.0
- gopkg.in/square/go-jose.v2 v2.4.1 // indirect
- k8s.io/apimachinery v0.21.2
- k8s.io/client-go v0.21.2
+ golang.org/x/net v0.4.0
+ golang.org/x/oauth2 v0.3.0
+ golang.org/x/time v0.0.0-20220210224613-90d013bbcef8
+ gopkg.in/ini.v1 v1.67.0
+ k8s.io/apimachinery v0.25.0
+ k8s.io/client-go v0.25.0
+)
+
+require (
+ github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
+ github.com/beorn7/perks v1.0.1 // indirect
+ github.com/cespare/xxhash/v2 v2.1.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fsnotify/fsnotify v1.4.9 // indirect
+ github.com/go-playground/locales v0.14.0 // indirect
+ github.com/go-playground/universal-translator v0.18.0 // indirect
+ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
+ github.com/golang/mock v1.6.0 // indirect
+ github.com/golang/protobuf v1.5.2 // indirect
+ github.com/golang/snappy v0.0.3 // indirect
+ github.com/google/go-cmp v0.5.8 // indirect
+ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
+ github.com/inconshreveable/mousetrap v1.0.0 // indirect
+ github.com/klauspost/cpuid/v2 v2.0.6 // indirect
+ github.com/klauspost/reedsolomon v1.9.15 // indirect
+ github.com/leodido/go-urn v1.2.1 // indirect
+ github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
+ github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
+ github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
+ github.com/nxadm/tail v1.4.8 // indirect
+ github.com/onsi/ginkgo/v2 v2.2.0 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/prometheus/client_model v0.2.0 // indirect
+ github.com/prometheus/common v0.37.0 // indirect
+ github.com/prometheus/procfs v0.8.0 // indirect
+ github.com/spf13/pflag v1.0.5 // 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
+ golang.org/x/crypto v0.4.0 // indirect
+ golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
+ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/sys v0.3.0 // indirect
+ golang.org/x/text v0.5.0 // indirect
+ golang.org/x/tools v0.1.12 // indirect
+ google.golang.org/appengine v1.6.7 // indirect
+ google.golang.org/protobuf v1.28.1 // indirect
+ gopkg.in/square/go-jose.v2 v2.6.0 // indirect
+ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+ k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
)
diff --git a/go.sum b/go.sum
index 433f03e281a..3471287169a 100644
--- a/go.sum
+++ b/go.sum
@@ -9,45 +9,68 @@ cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6T
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
+cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
+cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
+cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
+cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
+cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
+cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
+cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
+cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
+cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
+cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
+cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
+cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
+cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
+cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
+cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
+cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
+cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
+cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
+cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
+cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
+cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
-github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
-github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
-github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
-github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
-github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
-github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
-github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
-github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
-github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -55,19 +78,27 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
-github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
+github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
-github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
-github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
+github.com/coreos/go-oidc/v3 v3.4.0 h1:xz7elHb/LDwm/ERpwHd+5nb7wFHL32rsr6bBOgaeu6g=
+github.com/coreos/go-oidc/v3 v3.4.0/go.mod h1:eHUXhZtXPQLgEaDrOVTgwbgmz1xGOkJNye6h3zkD2Pw=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
@@ -78,14 +109,16 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
-github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
-github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
-github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
+github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
+github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
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.1.1-0.20220321042308-c306138b83ac h1:td1FJwN/oz8+9GldeEm3YdBX0Husc0FSPywLesZxi4w=
@@ -93,7 +126,6 @@ github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac/go.mod h1:fLV0TLw
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/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@@ -104,31 +136,25 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
+github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
-github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
-github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
-github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
-github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
-github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
-github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
-github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
-github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
-github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
-github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
-github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
-github.com/go-playground/validator/v10 v10.6.1 h1:W6TRDXt4WcWp4c4nf/G+6BkGdhiIo0k417gfr+V6u4I=
-github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
+github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
+github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
+github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
+github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
+github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
+github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
-github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -139,11 +165,17 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
+github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
+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=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
@@ -153,46 +185,71 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
-github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
+github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
+github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
+github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
-github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
-github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
+github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
+github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
+github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
+github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
+github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
+github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
-github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
+github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
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/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -213,11 +270,11 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
-github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c h1:nqkErwUGfpZZMqj29WZ9U/wz2OpJVDuiokLhE/3Y7IQ=
-github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
+github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
+github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
@@ -225,14 +282,13 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
-github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
-github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
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=
@@ -242,18 +298,22 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
+github.com/lucas-clemente/quic-go v0.31.0 h1:MfNp3fk0wjWRajw6quMFA3ap1AVtlU+2mtwmbVogB2M=
+github.com/lucas-clemente/quic-go v0.31.0/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
-github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
+github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
+github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
+github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
@@ -269,39 +329,32 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
-github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
-github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
-github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
-github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
+github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
-github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
+github.com/onsi/gomega v1.20.2 h1:8uQq0zMgLEfa0vRrrBgaJF2gyW9Da9BmfGV+OyUzfkY=
+github.com/onsi/gomega v1.20.2/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
-github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -309,14 +362,14 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
-github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
-github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
-github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
+github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU=
+github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -326,19 +379,27 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
-github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
+github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
+github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
+github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
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.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
+github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rodaine/table v1.0.1 h1:U/VwCnUxlVYxw8+NJiLIuCxA/xa6jL38MY3FYysVWWQ=
github.com/rodaine/table v1.0.1/go.mod h1:UVEtfBsflpeEcD56nF4F5AocNFta0ZuolpSVdPtlmP4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
+github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
@@ -346,9 +407,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@@ -358,14 +417,12 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
-github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -383,14 +440,20 @@ github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVc
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
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.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
+go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
+go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@@ -399,13 +462,12 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/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-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
-golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
+golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -416,6 +478,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
+golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -428,6 +492,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@@ -436,6 +502,11 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -452,8 +523,8 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -461,27 +532,71 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
-golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
+golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
+golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
+golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
+golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
+golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
+golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
+golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8=
+golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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-20190227155943-e225da77a7e6/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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20201207232520-09787c993a3a/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-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -496,13 +611,11 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -514,33 +627,72 @@ golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/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-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
+golang.org/x/sys v0.0.0-20210603125802-9665404d3644/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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
+golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
+golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
-golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -553,7 +705,6 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -574,15 +725,38 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
+golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
+golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
+golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -592,13 +766,44 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
+google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
+google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
+google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
+google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
+google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
+google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
+google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
+google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
+google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
+google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
+google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
+google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
+google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
+google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
+google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
+google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
+google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
+google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
+google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
+google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
+google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
+google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
-google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -616,8 +821,67 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
+google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
+google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
+google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
+google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
+google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
+google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
+google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
+google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
+google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
+google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
+google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
+google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
+google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
+google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
+google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
+google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
+google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
+google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
+google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
+google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
+google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
+google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
+google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
+google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
+google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
+google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
+google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
+google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
+google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
+google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
+google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -626,7 +890,30 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
+google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
+google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
+google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
+google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
+google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
+google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
+google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
+google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
+google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
+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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -635,57 +922,56 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
-gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
-gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y=
-gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
+gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU=
-k8s.io/apimachinery v0.21.2 h1:vezUc/BHqWlQDnZ+XkrpXSmnANSLbpnlpwo0Lhk0gpc=
-k8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM=
-k8s.io/client-go v0.21.2 h1:Q1j4L/iMN4pTw6Y4DWppBoUxgKO8LbffEMVEV00MUp0=
-k8s.io/client-go v0.21.2/go.mod h1:HdJ9iknWpbl3vMGtib6T2PyI/VYxiZfq936WNVHBRrA=
-k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU=
+k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0=
+k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E=
+k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
-k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
-k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=
-k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
+k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
+k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
-sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
-sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/hack/run-e2e.sh b/hack/run-e2e.sh
index ee396652215..d8cfb052b32 100755
--- a/hack/run-e2e.sh
+++ b/hack/run-e2e.sh
@@ -5,7 +5,7 @@ ROOT=$(unset CDPATH && cd $(dirname "${BASH_SOURCE[0]}")/.. && pwd)
which ginkgo &> /dev/null
if [ $? -ne 0 ]; then
echo "ginkgo not found, try to install..."
- go install github.com/onsi/ginkgo/ginkgo@latest
+ go install github.com/onsi/ginkgo/ginkgo@v1.16.5
fi
debug=false
diff --git a/package.sh b/package.sh
index 2f9a0f205f4..1a63a4e8c30 100755
--- a/package.sh
+++ b/package.sh
@@ -15,7 +15,7 @@ rm -rf ./release/packages
mkdir -p ./release/packages
os_all='linux windows darwin freebsd'
-arch_all='386 amd64 arm arm64 mips64 mips64le mips mipsle'
+arch_all='386 amd64 arm arm64 mips64 mips64le mips mipsle riscv64'
cd ./release
diff --git a/pkg/auth/oidc.go b/pkg/auth/oidc.go
index 8a9f3404bf1..c8ef923d3fc 100644
--- a/pkg/auth/oidc.go
+++ b/pkg/auth/oidc.go
@@ -18,10 +18,10 @@ import (
"context"
"fmt"
- "github.com/fatedier/frp/pkg/msg"
-
- "github.com/coreos/go-oidc"
+ "github.com/coreos/go-oidc/v3/oidc"
"golang.org/x/oauth2/clientcredentials"
+
+ "github.com/fatedier/frp/pkg/msg"
)
type OidcClientConfig struct {
@@ -34,8 +34,11 @@ type OidcClientConfig struct {
// is "".
OidcClientSecret string `ini:"oidc_client_secret" json:"oidc_client_secret"`
// OidcAudience specifies the audience of the token in OIDC authentication
- //if AuthenticationMethod == "oidc". By default, this value is "".
+ // if AuthenticationMethod == "oidc". By default, this value is "".
OidcAudience string `ini:"oidc_audience" json:"oidc_audience"`
+ // OidcScope specifies the scope of the token in OIDC authentication
+ // if AuthenticationMethod == "oidc". By default, this value is "".
+ OidcScope string `ini:"oidc_scope" json:"oidc_scope"`
// OidcTokenEndpointURL specifies the URL which implements OIDC Token Endpoint.
// It will be used to get an OIDC token if AuthenticationMethod == "oidc".
// By default, this value is "".
@@ -52,6 +55,7 @@ func getDefaultOidcClientConf() OidcClientConfig {
OidcClientID: "",
OidcClientSecret: "",
OidcAudience: "",
+ OidcScope: "",
OidcTokenEndpointURL: "",
OidcAdditionalEndpointParams: make(map[string]string),
}
@@ -99,10 +103,14 @@ func NewOidcAuthSetter(baseCfg BaseConfig, cfg OidcClientConfig) *OidcAuthProvid
eps[k] = []string{v}
}
+ if cfg.OidcAudience != "" {
+ eps["audience"] = []string{cfg.OidcAudience}
+ }
+
tokenGenerator := &clientcredentials.Config{
ClientID: cfg.OidcClientID,
ClientSecret: cfg.OidcClientSecret,
- Scopes: []string{cfg.OidcAudience},
+ Scopes: []string{cfg.OidcScope},
TokenURL: cfg.OidcTokenEndpointURL,
EndpointParams: eps,
}
diff --git a/pkg/config/client.go b/pkg/config/client.go
index f503711b07a..906ee985ebb 100644
--- a/pkg/config/client.go
+++ b/pkg/config/client.go
@@ -20,10 +20,10 @@ import (
"path/filepath"
"strings"
+ "gopkg.in/ini.v1"
+
"github.com/fatedier/frp/pkg/auth"
"github.com/fatedier/frp/pkg/util/util"
-
- "gopkg.in/ini.v1"
)
// ClientCommonConf contains information for a client service. It is
@@ -113,11 +113,15 @@ type ClientCommonConf struct {
// all supplied proxies are enabled. By default, this value is an empty
// set.
Start []string `ini:"start" json:"start"`
- //Start map[string]struct{} `json:"start"`
+ // Start map[string]struct{} `json:"start"`
// Protocol specifies the protocol to use when interacting with the server.
- // Valid values are "tcp", "kcp" and "websocket". By default, this value
+ // Valid values are "tcp", "kcp", "quic" and "websocket". By default, this value
// is "tcp".
Protocol string `ini:"protocol" json:"protocol"`
+ // QUIC protocol options
+ QUICKeepalivePeriod int `ini:"quic_keepalive_period" json:"quic_keepalive_period" validate:"gte=0"`
+ QUICMaxIdleTimeout int `ini:"quic_max_idle_timeout" json:"quic_max_idle_timeout" validate:"gte=0"`
+ QUICMaxIncomingStreams int `ini:"quic_max_incoming_streams" json:"quic_max_incoming_streams" validate:"gte=0"`
// TLSEnable specifies whether or not TLS should be used when communicating
// with the server. If "tls_cert_file" and "tls_key_file" are valid,
// client will load the supplied tls configuration.
@@ -172,30 +176,21 @@ func GetDefaultClientConf() ClientCommonConf {
LogWay: "console",
LogLevel: "info",
LogMaxDays: 3,
- DisableLogColor: false,
AdminAddr: "127.0.0.1",
- AdminPort: 0,
- AdminUser: "",
- AdminPwd: "",
- AssetsDir: "",
PoolCount: 1,
TCPMux: true,
TCPMuxKeepaliveInterval: 60,
- User: "",
- DNSServer: "",
LoginFailExit: true,
Start: make([]string, 0),
Protocol: "tcp",
- TLSEnable: false,
- TLSCertFile: "",
- TLSKeyFile: "",
- TLSTrustedCaFile: "",
+ QUICKeepalivePeriod: 10,
+ QUICMaxIdleTimeout: 30,
+ QUICMaxIncomingStreams: 100000,
HeartbeatInterval: 30,
HeartbeatTimeout: 90,
Metas: make(map[string]string),
UDPPacketSize: 1500,
IncludeConfigFiles: make([]string, 0),
- PprofEnable: false,
}
}
@@ -214,7 +209,7 @@ func (cfg *ClientCommonConf) Validate() error {
}
}
- if cfg.TLSEnable == false {
+ if !cfg.TLSEnable {
if cfg.TLSCertFile != "" {
fmt.Println("WARNING! tls_cert_file is invalid when tls_enable is false")
}
@@ -228,7 +223,7 @@ func (cfg *ClientCommonConf) Validate() error {
}
}
- if cfg.Protocol != "tcp" && cfg.Protocol != "kcp" && cfg.Protocol != "websocket" {
+ if cfg.Protocol != "tcp" && cfg.Protocol != "kcp" && cfg.Protocol != "websocket" && cfg.Protocol != "quic" {
return fmt.Errorf("invalid protocol")
}
@@ -281,7 +276,6 @@ func LoadAllProxyConfsFromIni(
source interface{},
start []string,
) (map[string]ProxyConf, map[string]VisitorConf, error) {
-
f, err := ini.LoadSources(ini.LoadOptions{
Insensitive: false,
InsensitiveSections: false,
@@ -366,7 +360,6 @@ func LoadAllProxyConfsFromIni(
}
func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
-
// Validation
localPortStr := section.Key("local_port").String()
remotePortStr := section.Key("remote_port").String()
@@ -404,8 +397,12 @@ func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
}
copySection(section, tmpsection)
- tmpsection.NewKey("local_port", fmt.Sprintf("%d", localPorts[i]))
- tmpsection.NewKey("remote_port", fmt.Sprintf("%d", remotePorts[i]))
+ if _, err := tmpsection.NewKey("local_port", fmt.Sprintf("%d", localPorts[i])); err != nil {
+ return fmt.Errorf("local_port new key in section error: %v", err)
+ }
+ if _, err := tmpsection.NewKey("remote_port", fmt.Sprintf("%d", remotePorts[i])); err != nil {
+ return fmt.Errorf("remote_port new key in section error: %v", err)
+ }
}
return nil
@@ -413,6 +410,6 @@ func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
func copySection(source, target *ini.Section) {
for key, value := range source.KeysHash() {
- target.NewKey(key, value)
+ _, _ = target.NewKey(key, value)
}
}
diff --git a/pkg/config/client_test.go b/pkg/config/client_test.go
index 12f1c9e1985..9cf8c805286 100644
--- a/pkg/config/client_test.go
+++ b/pkg/config/client_test.go
@@ -17,18 +17,17 @@ package config
import (
"testing"
+ "github.com/stretchr/testify/assert"
+
"github.com/fatedier/frp/pkg/auth"
"github.com/fatedier/frp/pkg/consts"
-
- "github.com/stretchr/testify/assert"
)
const (
testUser = "test"
)
-var (
- testClientBytesWithFull = []byte(`
+var testClientBytesWithFull = []byte(`
# [common] is integral section
[common]
server_addr = 0.0.0.9
@@ -237,7 +236,6 @@ var (
use_encryption = false
use_compression = false
`)
-)
func Test_LoadClientCommonConf(t *testing.T) {
assert := assert.New(t)
@@ -280,6 +278,9 @@ func Test_LoadClientCommonConf(t *testing.T) {
User: "your_name",
LoginFailExit: true,
Protocol: "tcp",
+ QUICKeepalivePeriod: 10,
+ QUICMaxIdleTimeout: 30,
+ QUICMaxIncomingStreams: 100000,
TLSEnable: true,
TLSCertFile: "client.crt",
TLSKeyFile: "client.key",
diff --git a/pkg/config/parse.go b/pkg/config/parse.go
index 7767981e32c..9f4cdb6b74b 100644
--- a/pkg/config/parse.go
+++ b/pkg/config/parse.go
@@ -42,7 +42,7 @@ func ParseClientConfig(filePath string) (
}
cfg.Complete()
if err = cfg.Validate(); err != nil {
- err = fmt.Errorf("Parse config error: %v", err)
+ err = fmt.Errorf("parse config error: %v", err)
return
}
diff --git a/pkg/config/proxy.go b/pkg/config/proxy.go
index e168520d377..92b499f271b 100644
--- a/pkg/config/proxy.go
+++ b/pkg/config/proxy.go
@@ -21,10 +21,10 @@ import (
"strconv"
"strings"
+ "gopkg.in/ini.v1"
+
"github.com/fatedier/frp/pkg/consts"
"github.com/fatedier/frp/pkg/msg"
-
- "gopkg.in/ini.v1"
)
// Proxy
@@ -420,10 +420,6 @@ func (cfg *BaseProxyConf) checkForCli() (err error) {
return nil
}
-func (cfg *BaseProxyConf) checkForSvr(conf ServerCommonConf) error {
- return nil
-}
-
// DomainConf
func (cfg *DomainConf) check() (err error) {
if len(cfg.CustomDomains) == 0 && cfg.SubDomain == "" {
diff --git a/pkg/config/proxy_test.go b/pkg/config/proxy_test.go
index 68c87b95e78..c603dd7f4d2 100644
--- a/pkg/config/proxy_test.go
+++ b/pkg/config/proxy_test.go
@@ -17,10 +17,10 @@ package config
import (
"testing"
- "github.com/fatedier/frp/pkg/consts"
"github.com/stretchr/testify/assert"
-
"gopkg.in/ini.v1"
+
+ "github.com/fatedier/frp/pkg/consts"
)
var (
@@ -49,7 +49,6 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
source []byte
expected ProxyConf
}{
-
{
sname: "ssh",
source: []byte(`
@@ -457,5 +456,4 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) {
assert.Equal(c.expected, actual)
}
-
}
diff --git a/pkg/config/server.go b/pkg/config/server.go
index 50eb3054c3f..040eaf65fe0 100644
--- a/pkg/config/server.go
+++ b/pkg/config/server.go
@@ -18,12 +18,12 @@ import (
"fmt"
"strings"
+ "github.com/go-playground/validator/v10"
+ "gopkg.in/ini.v1"
+
"github.com/fatedier/frp/pkg/auth"
plugin "github.com/fatedier/frp/pkg/plugin/server"
"github.com/fatedier/frp/pkg/util/util"
-
- "github.com/go-playground/validator/v10"
- "gopkg.in/ini.v1"
)
// ServerCommonConf contains information for a server service. It is
@@ -46,6 +46,14 @@ type ServerCommonConf struct {
// value is 0, the server will not listen for KCP connections. By default,
// this value is 0.
KCPBindPort int `ini:"kcp_bind_port" json:"kcp_bind_port" validate:"gte=0,lte=65535"`
+ // QUICBindPort specifies the QUIC port that the server listens on.
+ // Set this value to 0 will disable this feature.
+ // By default, the value is 0.
+ QUICBindPort int `ini:"quic_bind_port" json:"quic_bind_port" validate:"gte=0,lte=65535"`
+ // QUIC protocol options
+ QUICKeepalivePeriod int `ini:"quic_keepalive_period" json:"quic_keepalive_period" validate:"gte=0"`
+ QUICMaxIdleTimeout int `ini:"quic_max_idle_timeout" json:"quic_max_idle_timeout" validate:"gte=0"`
+ QUICMaxIncomingStreams int `ini:"quic_max_incoming_streams" json:"quic_max_incoming_streams" validate:"gte=0"`
// ProxyBindAddr specifies the address that the proxy binds to. This value
// may be the same as BindAddr.
ProxyBindAddr string `ini:"proxy_bind_addr" json:"proxy_bind_addr"`
@@ -195,48 +203,30 @@ func GetDefaultServerConf() ServerCommonConf {
ServerConfig: auth.GetDefaultServerConf(),
BindAddr: "0.0.0.0",
BindPort: 7000,
- BindUDPPort: 0,
- KCPBindPort: 0,
- ProxyBindAddr: "",
- VhostHTTPPort: 0,
- VhostHTTPSPort: 0,
- TCPMuxHTTPConnectPort: 0,
- TCPMuxPassthrough: false,
+ QUICKeepalivePeriod: 10,
+ QUICMaxIdleTimeout: 30,
+ QUICMaxIncomingStreams: 100000,
VhostHTTPTimeout: 60,
DashboardAddr: "0.0.0.0",
- DashboardPort: 0,
- DashboardUser: "",
- DashboardPwd: "",
- EnablePrometheus: false,
- AssetsDir: "",
LogFile: "console",
LogWay: "console",
LogLevel: "info",
LogMaxDays: 3,
- DisableLogColor: false,
DetailedErrorsToClient: true,
- SubDomainHost: "",
TCPMux: true,
TCPMuxKeepaliveInterval: 60,
TCPKeepAlive: 7200,
AllowPorts: make(map[int]struct{}),
MaxPoolCount: 5,
MaxPortsPerClient: 0,
- TLSOnly: false,
- TLSCertFile: "",
- TLSKeyFile: "",
- TLSTrustedCaFile: "",
HeartbeatTimeout: 90,
UserConnTimeout: 10,
- Custom404Page: "",
HTTPPlugins: make(map[string]plugin.HTTPPluginOptions),
UDPPacketSize: 1500,
- PprofEnable: false,
}
}
func UnmarshalServerConfFromIni(source interface{}) (ServerCommonConf, error) {
-
f, err := ini.LoadSources(ini.LoadOptions{
Insensitive: false,
InsensitiveSections: false,
@@ -308,7 +298,7 @@ func (cfg *ServerCommonConf) Complete() {
}
func (cfg *ServerCommonConf) Validate() error {
- if cfg.DashboardTLSMode == false {
+ if !cfg.DashboardTLSMode {
if cfg.DashboardTLSCertFile != "" {
fmt.Println("WARNING! dashboard_tls_cert_file is invalid when dashboard_tls_mode is false")
}
diff --git a/pkg/config/server_test.go b/pkg/config/server_test.go
index 8646ca62038..475a86b6f3e 100644
--- a/pkg/config/server_test.go
+++ b/pkg/config/server_test.go
@@ -17,10 +17,10 @@ package config
import (
"testing"
+ "github.com/stretchr/testify/assert"
+
"github.com/fatedier/frp/pkg/auth"
plugin "github.com/fatedier/frp/pkg/plugin/server"
-
- "github.com/stretchr/testify/assert"
)
func Test_LoadServerCommonConf(t *testing.T) {
@@ -106,6 +106,9 @@ func Test_LoadServerCommonConf(t *testing.T) {
BindPort: 7009,
BindUDPPort: 7008,
KCPBindPort: 7007,
+ QUICKeepalivePeriod: 10,
+ QUICMaxIdleTimeout: 30,
+ QUICMaxIncomingStreams: 100000,
ProxyBindAddr: "127.0.0.9",
VhostHTTPPort: 89,
VhostHTTPSPort: 449,
@@ -126,10 +129,10 @@ func Test_LoadServerCommonConf(t *testing.T) {
HeartbeatTimeout: 99,
UserConnTimeout: 9,
AllowPorts: map[int]struct{}{
- 10: struct{}{},
- 11: struct{}{},
- 12: struct{}{},
- 99: struct{}{},
+ 10: {},
+ 11: {},
+ 12: {},
+ 99: {},
},
MaxPoolCount: 59,
MaxPortsPerClient: 9,
@@ -179,6 +182,9 @@ func Test_LoadServerCommonConf(t *testing.T) {
BindAddr: "0.0.0.9",
BindPort: 7009,
BindUDPPort: 7008,
+ QUICKeepalivePeriod: 10,
+ QUICMaxIdleTimeout: 30,
+ QUICMaxIncomingStreams: 100000,
ProxyBindAddr: "0.0.0.9",
VhostHTTPTimeout: 60,
DashboardAddr: "0.0.0.0",
diff --git a/pkg/config/types.go b/pkg/config/types.go
index 062cc7462cf..28a0e46d87e 100644
--- a/pkg/config/types.go
+++ b/pkg/config/types.go
@@ -75,21 +75,22 @@ func (q *BandwidthQuantity) UnmarshalString(s string) error {
f float64
err error
)
- if strings.HasSuffix(s, "MB") {
+ switch {
+ case strings.HasSuffix(s, "MB"):
base = MB
fstr := strings.TrimSuffix(s, "MB")
f, err = strconv.ParseFloat(fstr, 64)
if err != nil {
return err
}
- } else if strings.HasSuffix(s, "KB") {
+ case strings.HasSuffix(s, "KB"):
base = KB
fstr := strings.TrimSuffix(s, "KB")
f, err = strconv.ParseFloat(fstr, 64)
if err != nil {
return err
}
- } else {
+ default:
return errors.New("unit not support")
}
diff --git a/pkg/config/value.go b/pkg/config/value.go
index e44fbd693e1..2f228823376 100644
--- a/pkg/config/value.go
+++ b/pkg/config/value.go
@@ -21,9 +21,7 @@ import (
"text/template"
)
-var (
- glbEnvs map[string]string
-)
+var glbEnvs map[string]string
func init() {
glbEnvs = make(map[string]string)
diff --git a/pkg/config/visitor.go b/pkg/config/visitor.go
index aede14d8b04..3d9440cd023 100644
--- a/pkg/config/visitor.go
+++ b/pkg/config/visitor.go
@@ -18,9 +18,9 @@ import (
"fmt"
"reflect"
- "github.com/fatedier/frp/pkg/consts"
-
"gopkg.in/ini.v1"
+
+ "github.com/fatedier/frp/pkg/consts"
)
// Visitor
@@ -136,6 +136,7 @@ func (cfg *BaseVisitorConf) check() (err error) {
}
func (cfg *BaseVisitorConf) unmarshalFromIni(prefix string, name string, section *ini.Section) error {
+ _ = section
// Custom decoration after basic unmarshal:
// proxy name
diff --git a/pkg/config/visitor_test.go b/pkg/config/visitor_test.go
index ce200ed049b..cdfbbf4673a 100644
--- a/pkg/config/visitor_test.go
+++ b/pkg/config/visitor_test.go
@@ -17,10 +17,10 @@ package config
import (
"testing"
- "github.com/fatedier/frp/pkg/consts"
-
"github.com/stretchr/testify/assert"
"gopkg.in/ini.v1"
+
+ "github.com/fatedier/frp/pkg/consts"
)
const testVisitorPrefix = "test."
diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go
index 907bc73e763..9e4438349b6 100644
--- a/pkg/consts/consts.go
+++ b/pkg/consts/consts.go
@@ -16,26 +16,26 @@ package consts
var (
// proxy status
- Idle string = "idle"
- Working string = "working"
- Closed string = "closed"
- Online string = "online"
- Offline string = "offline"
+ Idle = "idle"
+ Working = "working"
+ Closed = "closed"
+ Online = "online"
+ Offline = "offline"
// proxy type
- TCPProxy string = "tcp"
- UDPProxy string = "udp"
- TCPMuxProxy string = "tcpmux"
- HTTPProxy string = "http"
- HTTPSProxy string = "https"
- STCPProxy string = "stcp"
- XTCPProxy string = "xtcp"
- SUDPProxy string = "sudp"
+ TCPProxy = "tcp"
+ UDPProxy = "udp"
+ TCPMuxProxy = "tcpmux"
+ HTTPProxy = "http"
+ HTTPSProxy = "https"
+ STCPProxy = "stcp"
+ XTCPProxy = "xtcp"
+ SUDPProxy = "sudp"
// authentication method
- TokenAuthMethod string = "token"
- OidcAuthMethod string = "oidc"
+ TokenAuthMethod = "token"
+ OidcAuthMethod = "oidc"
// TCP multiplexer
- HTTPConnectTCPMultiplexer string = "httpconnect"
+ HTTPConnectTCPMultiplexer = "httpconnect"
)
diff --git a/pkg/metrics/aggregate/server.go b/pkg/metrics/aggregate/server.go
index 1ff15e42d0e..354d85c2b68 100644
--- a/pkg/metrics/aggregate/server.go
+++ b/pkg/metrics/aggregate/server.go
@@ -30,7 +30,7 @@ func EnablePrometheus() {
sm.Add(prometheus.ServerMetrics)
}
-var sm *serverMetrics = &serverMetrics{}
+var sm = &serverMetrics{}
func init() {
metrics.Register(sm)
diff --git a/pkg/metrics/mem/server.go b/pkg/metrics/mem/server.go
index 55d8daf120a..38a8c68b9b4 100644
--- a/pkg/metrics/mem/server.go
+++ b/pkg/metrics/mem/server.go
@@ -23,9 +23,12 @@ import (
server "github.com/fatedier/frp/server/metrics"
)
-var sm *serverMetrics = newServerMetrics()
-var ServerMetrics server.ServerMetrics
-var StatsCollector Collector
+var (
+ sm = newServerMetrics()
+
+ ServerMetrics server.ServerMetrics
+ StatsCollector Collector
+)
func init() {
ServerMetrics = sm
diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go
index 6520317d8fd..696496a2357 100644
--- a/pkg/metrics/metrics.go
+++ b/pkg/metrics/metrics.go
@@ -4,5 +4,7 @@ import (
"github.com/fatedier/frp/pkg/metrics/aggregate"
)
-var EnableMem = aggregate.EnableMem
-var EnablePrometheus = aggregate.EnablePrometheus
+var (
+ EnableMem = aggregate.EnableMem
+ EnablePrometheus = aggregate.EnablePrometheus
+)
diff --git a/pkg/metrics/prometheus/server.go b/pkg/metrics/prometheus/server.go
index 9cfdfda65aa..19eceb72fa7 100644
--- a/pkg/metrics/prometheus/server.go
+++ b/pkg/metrics/prometheus/server.go
@@ -1,9 +1,9 @@
package prometheus
import (
- "github.com/fatedier/frp/server/metrics"
-
"github.com/prometheus/client_golang/prometheus"
+
+ "github.com/fatedier/frp/server/metrics"
)
const (
diff --git a/pkg/msg/ctl.go b/pkg/msg/ctl.go
index 0eafdbcc5be..bf0c71a779b 100644
--- a/pkg/msg/ctl.go
+++ b/pkg/msg/ctl.go
@@ -22,9 +22,7 @@ import (
type Message = jsonMsg.Message
-var (
- msgCtl *jsonMsg.MsgCtl
-)
+var msgCtl *jsonMsg.MsgCtl
func init() {
msgCtl = jsonMsg.NewMsgCtl()
diff --git a/pkg/msg/msg.go b/pkg/msg/msg.go
index ba6dd63e450..4b2823c729b 100644
--- a/pkg/msg/msg.go
+++ b/pkg/msg/msg.go
@@ -37,28 +37,26 @@ const (
TypeNatHoleSid = '5'
)
-var (
- msgTypeMap = map[byte]interface{}{
- TypeLogin: Login{},
- TypeLoginResp: LoginResp{},
- TypeNewProxy: NewProxy{},
- TypeNewProxyResp: NewProxyResp{},
- TypeCloseProxy: CloseProxy{},
- TypeNewWorkConn: NewWorkConn{},
- TypeReqWorkConn: ReqWorkConn{},
- TypeStartWorkConn: StartWorkConn{},
- TypeNewVisitorConn: NewVisitorConn{},
- TypeNewVisitorConnResp: NewVisitorConnResp{},
- TypePing: Ping{},
- TypePong: Pong{},
- TypeUDPPacket: UDPPacket{},
- TypeNatHoleVisitor: NatHoleVisitor{},
- TypeNatHoleClient: NatHoleClient{},
- TypeNatHoleResp: NatHoleResp{},
- TypeNatHoleClientDetectOK: NatHoleClientDetectOK{},
- TypeNatHoleSid: NatHoleSid{},
- }
-)
+var msgTypeMap = map[byte]interface{}{
+ TypeLogin: Login{},
+ TypeLoginResp: LoginResp{},
+ TypeNewProxy: NewProxy{},
+ TypeNewProxyResp: NewProxyResp{},
+ TypeCloseProxy: CloseProxy{},
+ TypeNewWorkConn: NewWorkConn{},
+ TypeReqWorkConn: ReqWorkConn{},
+ TypeStartWorkConn: StartWorkConn{},
+ TypeNewVisitorConn: NewVisitorConn{},
+ TypeNewVisitorConnResp: NewVisitorConnResp{},
+ TypePing: Ping{},
+ TypePong: Pong{},
+ TypeUDPPacket: UDPPacket{},
+ TypeNatHoleVisitor: NatHoleVisitor{},
+ TypeNatHoleClient: NatHoleClient{},
+ TypeNatHoleResp: NatHoleResp{},
+ TypeNatHoleClientDetectOK: NatHoleClientDetectOK{},
+ TypeNatHoleSid: NatHoleSid{},
+}
// When frpc start, client send this message to login to server.
type Login struct {
@@ -129,8 +127,7 @@ type NewWorkConn struct {
Timestamp int64 `json:"timestamp,omitempty"`
}
-type ReqWorkConn struct {
-}
+type ReqWorkConn struct{}
type StartWorkConn struct {
ProxyName string `json:"proxy_name,omitempty"`
@@ -187,8 +184,7 @@ type NatHoleResp struct {
Error string `json:"error,omitempty"`
}
-type NatHoleClientDetectOK struct {
-}
+type NatHoleClientDetectOK struct{}
type NatHoleSid struct {
Sid string `json:"sid,omitempty"`
diff --git a/pkg/nathole/nathole.go b/pkg/nathole/nathole.go
index 545ad7aa035..da8b49c47d9 100644
--- a/pkg/nathole/nathole.go
+++ b/pkg/nathole/nathole.go
@@ -7,15 +7,15 @@ import (
"sync"
"time"
+ "github.com/fatedier/golib/errors"
+ "github.com/fatedier/golib/pool"
+
"github.com/fatedier/frp/pkg/msg"
"github.com/fatedier/frp/pkg/util/log"
"github.com/fatedier/frp/pkg/util/util"
-
- "github.com/fatedier/golib/errors"
- "github.com/fatedier/golib/pool"
)
-// Timeout seconds.
+// NatHoleTimeout seconds.
var NatHoleTimeout int64 = 10
type SidRequest struct {
@@ -107,7 +107,7 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
session := &Session{
Sid: sid,
VisitorAddr: raddr,
- NotifyCh: make(chan struct{}, 0),
+ NotifyCh: make(chan struct{}),
}
nc.mu.Lock()
clientCfg, ok := nc.clientCfgs[m.ProxyName]
@@ -115,14 +115,14 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
nc.mu.Unlock()
errInfo := fmt.Sprintf("xtcp server for [%s] doesn't exist", m.ProxyName)
log.Debug(errInfo)
- nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
+ _, _ = nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
return
}
if m.SignKey != util.GetAuthKey(clientCfg.Sk, m.Timestamp) {
nc.mu.Unlock()
errInfo := fmt.Sprintf("xtcp connection of [%s] auth failed", m.ProxyName)
log.Debug(errInfo)
- nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
+ _, _ = nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
return
}
@@ -151,7 +151,7 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
case <-session.NotifyCh:
resp := nc.GenNatHoleResponse(session, "")
log.Trace("send nat hole response to visitor")
- nc.listener.WriteToUDP(resp, raddr)
+ _, _ = nc.listener.WriteToUDP(resp, raddr)
case <-time.After(time.Duration(NatHoleTimeout) * time.Second):
return
}
@@ -169,7 +169,7 @@ func (nc *Controller) HandleClient(m *msg.NatHoleClient, raddr *net.UDPAddr) {
resp := nc.GenNatHoleResponse(session, "")
log.Trace("send nat hole response to client")
- nc.listener.WriteToUDP(resp, raddr)
+ _, _ = nc.listener.WriteToUDP(resp, raddr)
}
func (nc *Controller) GenNatHoleResponse(session *Session, errInfo string) []byte {
diff --git a/pkg/plugin/client/http2https.go b/pkg/plugin/client/http2https.go
index 3074cddf34e..f50a6c41f7a 100644
--- a/pkg/plugin/client/http2https.go
+++ b/pkg/plugin/client/http2https.go
@@ -86,17 +86,20 @@ func NewHTTP2HTTPSPlugin(params map[string]string) (Plugin, error) {
}
p.s = &http.Server{
- Handler: rp,
+ Handler: rp,
+ ReadHeaderTimeout: 0,
}
- go p.s.Serve(listener)
+ go func() {
+ _ = p.s.Serve(listener)
+ }()
return p, nil
}
func (p *HTTP2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
- p.l.PutConn(wrapConn)
+ _ = p.l.PutConn(wrapConn)
}
func (p *HTTP2HTTPSPlugin) Name() string {
diff --git a/pkg/plugin/client/http_proxy.go b/pkg/plugin/client/http_proxy.go
index 45bd3a9a792..78930e3952e 100644
--- a/pkg/plugin/client/http_proxy.go
+++ b/pkg/plugin/client/http_proxy.go
@@ -22,10 +22,10 @@ import (
"net/http"
"strings"
- frpNet "github.com/fatedier/frp/pkg/util/net"
-
frpIo "github.com/fatedier/golib/io"
gnet "github.com/fatedier/golib/net"
+
+ frpNet "github.com/fatedier/frp/pkg/util/net"
)
const PluginHTTPProxy = "http_proxy"
@@ -56,7 +56,9 @@ func NewHTTPProxyPlugin(params map[string]string) (Plugin, error) {
Handler: hp,
}
- go hp.s.Serve(listener)
+ go func() {
+ _ = hp.s.Serve(listener)
+ }()
return hp, nil
}
@@ -86,8 +88,7 @@ func (hp *HTTPProxy) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBuf
return
}
- hp.l.PutConn(sc)
- return
+ _ = hp.l.PutConn(sc)
}
func (hp *HTTPProxy) Close() error {
@@ -153,7 +154,7 @@ func (hp *HTTPProxy) ConnectHandler(rw http.ResponseWriter, req *http.Request) {
client.Close()
return
}
- client.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
+ _, _ = client.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
go frpIo.Join(remote, client)
}
@@ -188,7 +189,10 @@ func (hp *HTTPProxy) handleConnectReq(req *http.Request, rwc io.ReadWriteCloser)
defer rwc.Close()
if ok := hp.Auth(req); !ok {
res := getBadResponse()
- res.Write(rwc)
+ _ = res.Write(rwc)
+ if res.Body != nil {
+ res.Body.Close()
+ }
return
}
@@ -200,10 +204,10 @@ func (hp *HTTPProxy) handleConnectReq(req *http.Request, rwc io.ReadWriteCloser)
ProtoMajor: 1,
ProtoMinor: 1,
}
- res.Write(rwc)
+ _ = res.Write(rwc)
return
}
- rwc.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
+ _, _ = rwc.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
frpIo.Join(remote, rwc)
}
diff --git a/pkg/plugin/client/https2http.go b/pkg/plugin/client/https2http.go
index 5aec067b17c..18138dc1c7b 100644
--- a/pkg/plugin/client/https2http.go
+++ b/pkg/plugin/client/https2http.go
@@ -106,7 +106,9 @@ func NewHTTPS2HTTPPlugin(params map[string]string) (Plugin, error) {
}
ln := tls.NewListener(listener, tlsConfig)
- go p.s.Serve(ln)
+ go func() {
+ _ = p.s.Serve(ln)
+ }()
return p, nil
}
@@ -122,7 +124,7 @@ func (p *HTTPS2HTTPPlugin) genTLSConfig() (*tls.Config, error) {
func (p *HTTPS2HTTPPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
- p.l.PutConn(wrapConn)
+ _ = p.l.PutConn(wrapConn)
}
func (p *HTTPS2HTTPPlugin) Name() string {
diff --git a/pkg/plugin/client/https2https.go b/pkg/plugin/client/https2https.go
index cefa203017a..596bdc138a9 100644
--- a/pkg/plugin/client/https2https.go
+++ b/pkg/plugin/client/https2https.go
@@ -111,7 +111,9 @@ func NewHTTPS2HTTPSPlugin(params map[string]string) (Plugin, error) {
}
ln := tls.NewListener(listener, tlsConfig)
- go p.s.Serve(ln)
+ go func() {
+ _ = p.s.Serve(ln)
+ }()
return p, nil
}
@@ -127,7 +129,7 @@ func (p *HTTPS2HTTPSPlugin) genTLSConfig() (*tls.Config, error) {
func (p *HTTPS2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
- p.l.PutConn(wrapConn)
+ _ = p.l.PutConn(wrapConn)
}
func (p *HTTPS2HTTPSPlugin) Name() string {
diff --git a/pkg/plugin/client/socks5.go b/pkg/plugin/client/socks5.go
index 3a543d9d2d4..f731e87da9a 100644
--- a/pkg/plugin/client/socks5.go
+++ b/pkg/plugin/client/socks5.go
@@ -19,9 +19,9 @@ import (
"log"
"net"
- frpNet "github.com/fatedier/frp/pkg/util/net"
-
gosocks5 "github.com/armon/go-socks5"
+
+ frpNet "github.com/fatedier/frp/pkg/util/net"
)
const PluginSocks5 = "socks5"
@@ -32,9 +32,6 @@ func init() {
type Socks5Plugin struct {
Server *gosocks5.Server
-
- user string
- passwd string
}
func NewSocks5Plugin(params map[string]string) (p Plugin, err error) {
@@ -56,7 +53,7 @@ func NewSocks5Plugin(params map[string]string) (p Plugin, err error) {
func (sp *Socks5Plugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
defer conn.Close()
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
- sp.Server.ServeConn(wrapConn)
+ _ = sp.Server.ServeConn(wrapConn)
}
func (sp *Socks5Plugin) Name() string {
diff --git a/pkg/plugin/client/static_file.go b/pkg/plugin/client/static_file.go
index 1eeea3ba92e..4d31ea53e8b 100644
--- a/pkg/plugin/client/static_file.go
+++ b/pkg/plugin/client/static_file.go
@@ -19,9 +19,9 @@ import (
"net"
"net/http"
- frpNet "github.com/fatedier/frp/pkg/util/net"
-
"github.com/gorilla/mux"
+
+ frpNet "github.com/fatedier/frp/pkg/util/net"
)
const PluginStaticFile = "static_file"
@@ -69,13 +69,15 @@ func NewStaticFilePlugin(params map[string]string) (Plugin, error) {
sp.s = &http.Server{
Handler: router,
}
- go sp.s.Serve(listener)
+ go func() {
+ _ = sp.s.Serve(listener)
+ }()
return sp, nil
}
func (sp *StaticFilePlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
- sp.l.PutConn(wrapConn)
+ _ = sp.l.PutConn(wrapConn)
}
func (sp *StaticFilePlugin) Name() string {
diff --git a/pkg/plugin/client/unix_domain_socket.go b/pkg/plugin/client/unix_domain_socket.go
index a85ada702f8..68902472242 100644
--- a/pkg/plugin/client/unix_domain_socket.go
+++ b/pkg/plugin/client/unix_domain_socket.go
@@ -57,7 +57,9 @@ func (uds *UnixDomainSocketPlugin) Handle(conn io.ReadWriteCloser, realConn net.
return
}
if len(extraBufToLocal) > 0 {
- localConn.Write(extraBufToLocal)
+ if _, err := localConn.Write(extraBufToLocal); err != nil {
+ return
+ }
}
frpIo.Join(localConn, conn)
diff --git a/pkg/plugin/server/http.go b/pkg/plugin/server/http.go
index 5ca8c0635bb..b120332dcdb 100644
--- a/pkg/plugin/server/http.go
+++ b/pkg/plugin/server/http.go
@@ -43,12 +43,12 @@ type httpPlugin struct {
}
func NewHTTPPluginOptions(options HTTPPluginOptions) Plugin {
- var url = fmt.Sprintf("%s%s", options.Addr, options.Path)
+ url := fmt.Sprintf("%s%s", options.Addr, options.Path)
var client *http.Client
if strings.HasPrefix(url, "https://") {
tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: options.TLSVerify == false},
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: !options.TLSVerify},
}
client = &http.Client{Transport: tr}
} else {
diff --git a/pkg/plugin/server/manager.go b/pkg/plugin/server/manager.go
index 47d11d1c245..5a8a309c61f 100644
--- a/pkg/plugin/server/manager.go
+++ b/pkg/plugin/server/manager.go
@@ -154,9 +154,8 @@ func (m *Manager) CloseProxy(content *CloseProxyContent) error {
if len(errs) > 0 {
return fmt.Errorf("send CloseProxy request to plugin errors: %s", strings.Join(errs, "; "))
- } else {
- return nil
}
+ return nil
}
func (m *Manager) Ping(content *PingContent) (*PingContent, error) {
diff --git a/pkg/proto/udp/udp.go b/pkg/proto/udp/udp.go
index 97f6ea4098f..7a11984b2e4 100644
--- a/pkg/proto/udp/udp.go
+++ b/pkg/proto/udp/udp.go
@@ -20,10 +20,10 @@ import (
"sync"
"time"
- "github.com/fatedier/frp/pkg/msg"
-
"github.com/fatedier/golib/errors"
"github.com/fatedier/golib/pool"
+
+ "github.com/fatedier/frp/pkg/msg"
)
func NewUDPPacket(buf []byte, laddr, raddr *net.UDPAddr) *msg.UDPPacket {
@@ -47,7 +47,7 @@ func ForwardUserConn(udpConn *net.UDPConn, readCh <-chan *msg.UDPPacket, sendCh
if err != nil {
continue
}
- udpConn.WriteToUDP(buf, udpMsg.RemoteAddr)
+ _, _ = udpConn.WriteToUDP(buf, udpMsg.RemoteAddr)
}
}()
@@ -70,9 +70,7 @@ func ForwardUserConn(udpConn *net.UDPConn, readCh <-chan *msg.UDPPacket, sendCh
}
func Forwarder(dstAddr *net.UDPAddr, readCh <-chan *msg.UDPPacket, sendCh chan<- msg.Message, bufSize int) {
- var (
- mu sync.RWMutex
- )
+ var mu sync.RWMutex
udpConnMap := make(map[string]*net.UDPConn)
// read from dstAddr and write to sendCh
@@ -87,7 +85,7 @@ func Forwarder(dstAddr *net.UDPAddr, readCh <-chan *msg.UDPPacket, sendCh chan<-
buf := pool.GetBuf(bufSize)
for {
- udpConn.SetReadDeadline(time.Now().Add(30 * time.Second))
+ _ = udpConn.SetReadDeadline(time.Now().Add(30 * time.Second))
n, _, err := udpConn.ReadFromUDP(buf)
if err != nil {
return
diff --git a/pkg/transport/tls.go b/pkg/transport/tls.go
index 38201f8e900..02950cc546e 100644
--- a/pkg/transport/tls.go
+++ b/pkg/transport/tls.go
@@ -19,7 +19,7 @@ func newCustomTLSKeyPair(certfile, keyfile string) (*tls.Certificate, error) {
}
func newRandomTLSKeyPair() *tls.Certificate {
- key, err := rsa.GenerateKey(rand.Reader, 1024)
+ key, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
@@ -58,7 +58,7 @@ func newCertPool(caPath string) (*x509.CertPool, error) {
}
func NewServerTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) {
- var base = &tls.Config{}
+ base := &tls.Config{}
if certPath == "" || keyPath == "" {
// server will generate tls conf by itself
@@ -87,7 +87,7 @@ func NewServerTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) {
}
func NewClientTLSConfig(certPath, keyPath, caPath, serverName string) (*tls.Config, error) {
- var base = &tls.Config{}
+ base := &tls.Config{}
if certPath == "" || keyPath == "" {
// client will not generate tls conf by itself
diff --git a/pkg/util/log/log.go b/pkg/util/log/log.go
index 1ddf4cdc042..01a454d595d 100644
--- a/pkg/util/log/log.go
+++ b/pkg/util/log/log.go
@@ -40,19 +40,19 @@ func SetLogFile(logWay string, logFile string, maxdays int64, disableLogColor bo
if logWay == "console" {
params := ""
if disableLogColor {
- params = fmt.Sprintf(`{"color": false}`)
+ params = `{"color": false}`
}
- Log.SetLogger("console", params)
+ _ = Log.SetLogger("console", params)
} else {
params := fmt.Sprintf(`{"filename": "%s", "maxdays": %d}`, logFile, maxdays)
- Log.SetLogger("file", params)
+ _ = Log.SetLogger("file", params)
}
}
// SetLogLevel set log level, default is warning
// value: error, warning, info, debug, trace
func SetLogLevel(logLevel string) {
- level := 4 // warning
+ var level int
switch logLevel {
case "error":
level = 3
@@ -65,7 +65,7 @@ func SetLogLevel(logLevel string) {
case "trace":
level = 8
default:
- level = 4
+ level = 4 // warning
}
Log.SetLevel(level)
}
diff --git a/pkg/util/net/conn.go b/pkg/util/net/conn.go
index f3d8caee400..1258ed48063 100644
--- a/pkg/util/net/conn.go
+++ b/pkg/util/net/conn.go
@@ -22,6 +22,8 @@ import (
"sync/atomic"
"time"
+ quic "github.com/lucas-clemente/quic-go"
+
"github.com/fatedier/frp/pkg/util/xlog"
)
@@ -183,3 +185,29 @@ func (statsConn *StatsConn) Close() (err error) {
}
return
}
+
+type wrapQuicStream struct {
+ quic.Stream
+ c quic.Connection
+}
+
+func QuicStreamToNetConn(s quic.Stream, c quic.Connection) net.Conn {
+ return &wrapQuicStream{
+ Stream: s,
+ c: c,
+ }
+}
+
+func (conn *wrapQuicStream) LocalAddr() net.Addr {
+ if conn.c != nil {
+ return conn.c.LocalAddr()
+ }
+ return (*net.TCPAddr)(nil)
+}
+
+func (conn *wrapQuicStream) RemoteAddr() net.Addr {
+ if conn.c != nil {
+ return conn.c.RemoteAddr()
+ }
+ return (*net.TCPAddr)(nil)
+}
diff --git a/pkg/util/net/kcp.go b/pkg/util/net/kcp.go
index e9e0b1269b6..77b6bfa76ff 100644
--- a/pkg/util/net/kcp.go
+++ b/pkg/util/net/kcp.go
@@ -32,8 +32,8 @@ func ListenKcp(address string) (l *KCPListener, err error) {
if err != nil {
return l, err
}
- listener.SetReadBuffer(4194304)
- listener.SetWriteBuffer(4194304)
+ _ = listener.SetReadBuffer(4194304)
+ _ = listener.SetWriteBuffer(4194304)
l = &KCPListener{
listener: listener,
diff --git a/pkg/util/net/tls.go b/pkg/util/net/tls.go
index 1bae196adb8..3aecb482f15 100644
--- a/pkg/util/net/tls.go
+++ b/pkg/util/net/tls.go
@@ -23,32 +23,30 @@ import (
gnet "github.com/fatedier/golib/net"
)
-var (
- FRPTLSHeadByte = 0x17
-)
+var FRPTLSHeadByte = 0x17
func CheckAndEnableTLSServerConnWithTimeout(
c net.Conn, tlsConfig *tls.Config, tlsOnly bool, timeout time.Duration,
) (out net.Conn, isTLS bool, custom bool, err error) {
-
sc, r := gnet.NewSharedConnSize(c, 2)
buf := make([]byte, 1)
var n int
- c.SetReadDeadline(time.Now().Add(timeout))
+ _ = c.SetReadDeadline(time.Now().Add(timeout))
n, err = r.Read(buf)
- c.SetReadDeadline(time.Time{})
+ _ = c.SetReadDeadline(time.Time{})
if err != nil {
return
}
- if n == 1 && int(buf[0]) == FRPTLSHeadByte {
+ switch {
+ case n == 1 && int(buf[0]) == FRPTLSHeadByte:
out = tls.Server(c, tlsConfig)
isTLS = true
custom = true
- } else if n == 1 && int(buf[0]) == 0x16 {
+ case n == 1 && int(buf[0]) == 0x16:
out = tls.Server(sc, tlsConfig)
isTLS = true
- } else {
+ default:
if tlsOnly {
err = fmt.Errorf("non-TLS connection received on a TlsOnly server")
return
diff --git a/pkg/util/net/udp.go b/pkg/util/net/udp.go
index 6689732e40c..82999a5f5c2 100644
--- a/pkg/util/net/udp.go
+++ b/pkg/util/net/udp.go
@@ -55,7 +55,7 @@ func NewFakeUDPConn(l *UDPListener, laddr, raddr net.Addr) *FakeUDPConn {
for {
time.Sleep(5 * time.Second)
fc.mu.RLock()
- if time.Now().Sub(fc.lastActive) > 10*time.Second {
+ if time.Since(fc.lastActive) > 10*time.Second {
fc.mu.RUnlock()
fc.Close()
break
@@ -68,8 +68,7 @@ func NewFakeUDPConn(l *UDPListener, laddr, raddr net.Addr) *FakeUDPConn {
func (c *FakeUDPConn) putPacket(content []byte) {
defer func() {
- if err := recover(); err != nil {
- }
+ _ = recover()
}()
select {
@@ -109,7 +108,7 @@ func (c *FakeUDPConn) Write(b []byte) (n int, err error) {
LocalAddr: c.localAddr,
RemoteAddr: c.remoteAddr,
}
- c.l.writeUDPPacket(packet)
+ _ = c.l.writeUDPPacket(packet)
c.mu.Lock()
c.lastActive = time.Now()
@@ -208,7 +207,7 @@ func ListenUDP(bindAddr string, bindPort int) (l *UDPListener, err error) {
}
if addr, ok := packet.RemoteAddr.(*net.UDPAddr); ok {
- readConn.WriteToUDP(packet.Buf, addr)
+ _, _ = readConn.WriteToUDP(packet.Buf, addr)
}
}
}()
diff --git a/pkg/util/net/websocket.go b/pkg/util/net/websocket.go
index 4ec5c9fe079..6a8d369c4a9 100644
--- a/pkg/util/net/websocket.go
+++ b/pkg/util/net/websocket.go
@@ -9,9 +9,7 @@ import (
"golang.org/x/net/websocket"
)
-var (
- ErrWebsocketListenerClosed = errors.New("websocket listener closed")
-)
+var ErrWebsocketListenerClosed = errors.New("websocket listener closed")
const (
FrpWebsocketPath = "/~!frp"
@@ -21,8 +19,7 @@ type WebsocketListener struct {
ln net.Listener
acceptCh chan net.Conn
- server *http.Server
- httpMutex *http.ServeMux
+ server *http.Server
}
// NewWebsocketListener to handle websocket connections
@@ -47,7 +44,9 @@ func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) {
Handler: muxer,
}
- go wl.server.Serve(ln)
+ go func() {
+ _ = wl.server.Serve(ln)
+ }()
return
}
diff --git a/pkg/util/tcpmux/httpconnect.go b/pkg/util/tcpmux/httpconnect.go
index 2639c493644..e94ff4b2bb2 100644
--- a/pkg/util/tcpmux/httpconnect.go
+++ b/pkg/util/tcpmux/httpconnect.go
@@ -22,9 +22,10 @@ import (
"net/http"
"time"
+ gnet "github.com/fatedier/golib/net"
+
"github.com/fatedier/frp/pkg/util/util"
"github.com/fatedier/frp/pkg/util/vhost"
- gnet "github.com/fatedier/golib/net"
)
type HTTPConnectTCPMuxer struct {
@@ -66,7 +67,11 @@ func (muxer *HTTPConnectTCPMuxer) sendConnectResponse(c net.Conn, reqInfo map[st
if muxer.passthrough {
return nil
}
- return util.OkResponse().Write(c)
+ res := util.OkResponse()
+ if res.Body != nil {
+ defer res.Body.Close()
+ }
+ return res.Write(c)
}
func (muxer *HTTPConnectTCPMuxer) getHostFromHTTPConnect(c net.Conn) (net.Conn, map[string]string, error) {
@@ -82,11 +87,15 @@ func (muxer *HTTPConnectTCPMuxer) getHostFromHTTPConnect(c net.Conn) (net.Conn,
reqInfoMap["Scheme"] = "tcp"
reqInfoMap["HTTPUser"] = httpUser
- var outConn net.Conn = c
+ outConn := c
if muxer.passthrough {
outConn = sc
if muxer.authRequired && httpUser == "" {
- util.ProxyUnauthorizedResponse().Write(c)
+ resp := util.ProxyUnauthorizedResponse()
+ if resp.Body != nil {
+ defer resp.Body.Close()
+ }
+ _ = resp.Write(c)
outConn = c
}
}
diff --git a/pkg/util/util/http.go b/pkg/util/util/http.go
index 3b8117346f9..d89af08b76a 100644
--- a/pkg/util/util/http.go
+++ b/pkg/util/util/http.go
@@ -60,10 +60,8 @@ func CanonicalHost(host string) (string, error) {
return "", err
}
}
- if strings.HasSuffix(host, ".") {
- // Strip trailing dot from fully qualified domain names.
- host = host[:len(host)-1]
- }
+ // Strip trailing dot from fully qualified domain names.
+ host = strings.TrimSuffix(host, ".")
return host, nil
}
diff --git a/pkg/util/util/util.go b/pkg/util/util/util.go
index 032675fb761..b13f9a77356 100644
--- a/pkg/util/util/util.go
+++ b/pkg/util/util/util.go
@@ -44,7 +44,7 @@ func RandIDWithLen(idLen int) (id string, err error) {
}
func GetAuthKey(token string, timestamp int64) (key string) {
- token = token + fmt.Sprintf("%d", timestamp)
+ token += fmt.Sprintf("%d", timestamp)
md5Ctx := md5.New()
md5Ctx.Write([]byte(token))
data := md5Ctx.Sum(nil)
@@ -70,7 +70,8 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
numArray := strings.Split(numRangeStr, "-")
// length: only 1 or 2 is correct
rangeType := len(numArray)
- if rangeType == 1 {
+ switch rangeType {
+ case 1:
// single number
singleNum, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
if errRet != nil {
@@ -78,7 +79,7 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
return
}
numbers = append(numbers, singleNum)
- } else if rangeType == 2 {
+ case 2:
// range numbers
min, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
if errRet != nil {
@@ -97,7 +98,7 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
for i := min; i <= max; i++ {
numbers = append(numbers, i)
}
- } else {
+ default:
err = fmt.Errorf("range number is invalid")
return
}
diff --git a/pkg/util/version/version.go b/pkg/util/version/version.go
index b5eca31735b..6228c092a58 100644
--- a/pkg/util/version/version.go
+++ b/pkg/util/version/version.go
@@ -19,7 +19,7 @@ import (
"strings"
)
-var version string = "0.44.0"
+var version = "0.46.0"
func Full() string {
return version
diff --git a/pkg/util/vhost/http.go b/pkg/util/vhost/http.go
index bfbd16ea9b6..5addb47542e 100644
--- a/pkg/util/vhost/http.go
+++ b/pkg/util/vhost/http.go
@@ -23,27 +23,26 @@ import (
"log"
"net"
"net/http"
+ "net/http/httputil"
"net/url"
"strings"
"time"
- frpLog "github.com/fatedier/frp/pkg/util/log"
- "github.com/fatedier/frp/pkg/util/util"
frpIo "github.com/fatedier/golib/io"
-
"github.com/fatedier/golib/pool"
-)
-var (
- ErrNoRouteFound = errors.New("no route found")
+ frpLog "github.com/fatedier/frp/pkg/util/log"
+ "github.com/fatedier/frp/pkg/util/util"
)
+var ErrNoRouteFound = errors.New("no route found")
+
type HTTPReverseProxyOptions struct {
ResponseHeaderTimeoutS int64
}
type HTTPReverseProxy struct {
- proxy *ReverseProxy
+ proxy *httputil.ReverseProxy
vhostRouter *Routers
responseHeaderTimeout time.Duration
@@ -57,23 +56,32 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
responseHeaderTimeout: time.Duration(option.ResponseHeaderTimeoutS) * time.Second,
vhostRouter: vhostRouter,
}
- proxy := &ReverseProxy{
+ proxy := &httputil.ReverseProxy{
// Modify incoming requests by route policies.
Director: func(req *http.Request) {
req.URL.Scheme = "http"
- url := req.Context().Value(RouteInfoURL).(string)
- routeByHTTPUser := req.Context().Value(RouteInfoHTTPUser).(string)
- oldHost, _ := util.CanonicalHost(req.Context().Value(RouteInfoHost).(string))
- rc := rp.GetRouteConfig(oldHost, url, routeByHTTPUser)
+ reqRouteInfo := req.Context().Value(RouteInfoKey).(*RequestRouteInfo)
+ oldHost, _ := util.CanonicalHost(reqRouteInfo.Host)
+
+ rc := rp.GetRouteConfig(oldHost, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
if rc != nil {
if rc.RewriteHost != "" {
req.Host = rc.RewriteHost
}
- // Set {domain}.{location}.{routeByHTTPUser} as URL host here to let http transport reuse connections.
- // TODO(fatedier): use proxy name instead?
+
+ var endpoint string
+ if rc.ChooseEndpointFn != nil {
+ // ignore error here, it will use CreateConnFn instead later
+ endpoint, _ = rc.ChooseEndpointFn()
+ reqRouteInfo.Endpoint = endpoint
+ frpLog.Trace("choose endpoint name [%s] for http request host [%s] path [%s] httpuser [%s]",
+ endpoint, oldHost, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
+ }
+ // Set {domain}.{location}.{routeByHTTPUser}.{endpoint} as URL host here to let http transport reuse connections.
req.URL.Host = rc.Domain + "." +
base64.StdEncoding.EncodeToString([]byte(rc.Location)) + "." +
- base64.StdEncoding.EncodeToString([]byte(rc.RouteByHTTPUser))
+ base64.StdEncoding.EncodeToString([]byte(rc.RouteByHTTPUser)) + "." +
+ base64.StdEncoding.EncodeToString([]byte(endpoint))
for k, v := range rc.Headers {
req.Header.Set(k, v)
@@ -81,18 +89,14 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
} else {
req.URL.Host = req.Host
}
-
},
// Create a connection to one proxy routed by route policy.
Transport: &http.Transport{
ResponseHeaderTimeout: rp.responseHeaderTimeout,
IdleConnTimeout: 60 * time.Second,
+ MaxIdleConnsPerHost: 5,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
- url := ctx.Value(RouteInfoURL).(string)
- host, _ := util.CanonicalHost(ctx.Value(RouteInfoHost).(string))
- routerByHTTPUser := ctx.Value(RouteInfoHTTPUser).(string)
- remote := ctx.Value(RouteInfoRemote).(string)
- return rp.CreateConnection(host, url, routerByHTTPUser, remote)
+ return rp.CreateConnection(ctx.Value(RouteInfoKey).(*RequestRouteInfo), true)
},
Proxy: func(req *http.Request) (*url.URL, error) {
// Use proxy mode if there is host in HTTP first request line.
@@ -102,7 +106,7 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
// Normal:
// GET / HTTP/1.1
// Host: example.com
- urlHost := req.Context().Value(RouteInfoURLHost).(string)
+ urlHost := req.Context().Value(RouteInfoKey).(*RequestRouteInfo).URLHost
if urlHost != "" {
return req.URL, nil
}
@@ -114,7 +118,7 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) {
frpLog.Warn("do http proxy request [host: %s] error: %v", req.Host, err)
rw.WriteHeader(http.StatusNotFound)
- rw.Write(getNotFoundPageContent())
+ _, _ = rw.Write(getNotFoundPageContent())
},
}
rp.proxy = proxy
@@ -145,14 +149,6 @@ func (rp *HTTPReverseProxy) GetRouteConfig(domain, location, routeByHTTPUser str
return nil
}
-func (rp *HTTPReverseProxy) GetRealHost(domain, location, routeByHTTPUser string) (host string) {
- vr, ok := rp.getVhost(domain, location, routeByHTTPUser)
- if ok {
- host = vr.payload.(*RouteConfig).RewriteHost
- }
- return
-}
-
func (rp *HTTPReverseProxy) GetHeaders(domain, location, routeByHTTPUser string) (headers map[string]string) {
vr, ok := rp.getVhost(domain, location, routeByHTTPUser)
if ok {
@@ -162,15 +158,22 @@ func (rp *HTTPReverseProxy) GetHeaders(domain, location, routeByHTTPUser string)
}
// CreateConnection create a new connection by route config
-func (rp *HTTPReverseProxy) CreateConnection(domain, location, routeByHTTPUser string, remoteAddr string) (net.Conn, error) {
- vr, ok := rp.getVhost(domain, location, routeByHTTPUser)
+func (rp *HTTPReverseProxy) CreateConnection(reqRouteInfo *RequestRouteInfo, byEndpoint bool) (net.Conn, error) {
+ host, _ := util.CanonicalHost(reqRouteInfo.Host)
+ vr, ok := rp.getVhost(host, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
if ok {
+ if byEndpoint {
+ fn := vr.payload.(*RouteConfig).CreateConnByEndpointFn
+ if fn != nil {
+ return fn(reqRouteInfo.Endpoint, reqRouteInfo.RemoteAddr)
+ }
+ }
fn := vr.payload.(*RouteConfig).CreateConnFn
if fn != nil {
- return fn(remoteAddr)
+ return fn(reqRouteInfo.RemoteAddr)
}
}
- return nil, fmt.Errorf("%v: %s %s %s", ErrNoRouteFound, domain, location, routeByHTTPUser)
+ return nil, fmt.Errorf("%v: %s %s %s", ErrNoRouteFound, host, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
}
func (rp *HTTPReverseProxy) CheckAuth(domain, location, routeByHTTPUser, user, passwd string) bool {
@@ -246,27 +249,35 @@ func (rp *HTTPReverseProxy) connectHandler(rw http.ResponseWriter, req *http.Req
return
}
- url := req.Context().Value(RouteInfoURL).(string)
- routeByHTTPUser := req.Context().Value(RouteInfoHTTPUser).(string)
- domain, _ := util.CanonicalHost(req.Context().Value(RouteInfoHost).(string))
- remoteAddr := req.Context().Value(RouteInfoRemote).(string)
-
- remote, err := rp.CreateConnection(domain, url, routeByHTTPUser, remoteAddr)
+ remote, err := rp.CreateConnection(req.Context().Value(RouteInfoKey).(*RequestRouteInfo), false)
if err != nil {
- http.Error(rw, "Failed", http.StatusBadRequest)
+ _ = notFoundResponse().Write(client)
client.Close()
return
}
- req.Write(remote)
+ _ = req.Write(remote)
go frpIo.Join(remote, client)
}
-func (rp *HTTPReverseProxy) injectRequestInfoToCtx(req *http.Request) *http.Request {
- newctx := req.Context()
- newctx = context.WithValue(newctx, RouteInfoURL, req.URL.Path)
- newctx = context.WithValue(newctx, RouteInfoHost, req.Host)
- newctx = context.WithValue(newctx, RouteInfoURLHost, req.URL.Host)
+func parseBasicAuth(auth string) (username, password string, ok bool) {
+ const prefix = "Basic "
+ // Case insensitive prefix match. See Issue 22736.
+ if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
+ return
+ }
+ c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
+ if err != nil {
+ return
+ }
+ cs := string(c)
+ s := strings.IndexByte(cs, ':')
+ if s < 0 {
+ return
+ }
+ return cs[:s], cs[s+1:], true
+}
+func (rp *HTTPReverseProxy) injectRequestInfoToCtx(req *http.Request) *http.Request {
user := ""
// If url host isn't empty, it's a proxy request. Get http user from Proxy-Authorization header.
if req.URL.Host != "" {
@@ -278,8 +289,16 @@ func (rp *HTTPReverseProxy) injectRequestInfoToCtx(req *http.Request) *http.Requ
if user == "" {
user, _, _ = req.BasicAuth()
}
- newctx = context.WithValue(newctx, RouteInfoHTTPUser, user)
- newctx = context.WithValue(newctx, RouteInfoRemote, req.RemoteAddr)
+
+ reqRouteInfo := &RequestRouteInfo{
+ URL: req.URL.Path,
+ Host: req.Host,
+ HTTPUser: user,
+ RemoteAddr: req.RemoteAddr,
+ URLHost: req.URL.Host,
+ }
+ newctx := req.Context()
+ newctx = context.WithValue(newctx, RouteInfoKey, reqRouteInfo)
return req.Clone(newctx)
}
diff --git a/pkg/util/vhost/resource.go b/pkg/util/vhost/resource.go
index 446f40f91f2..65bdbcb6288 100644
--- a/pkg/util/vhost/resource.go
+++ b/pkg/util/vhost/resource.go
@@ -24,9 +24,7 @@ import (
"github.com/fatedier/frp/pkg/util/version"
)
-var (
- NotFoundPagePath = ""
-)
+var NotFoundPagePath = ""
const (
NotFound = `
@@ -74,14 +72,16 @@ func notFoundResponse() *http.Response {
header.Set("server", "frp/"+version.Full())
header.Set("Content-Type", "text/html")
+ content := getNotFoundPageContent()
res := &http.Response{
- Status: "Not Found",
- StatusCode: 404,
- Proto: "HTTP/1.0",
- ProtoMajor: 1,
- ProtoMinor: 0,
- Header: header,
- Body: io.NopCloser(bytes.NewReader(getNotFoundPageContent())),
+ Status: "Not Found",
+ StatusCode: 404,
+ Proto: "HTTP/1.1",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Header: header,
+ Body: io.NopCloser(bytes.NewReader(content)),
+ ContentLength: int64(len(content)),
}
return res
}
diff --git a/pkg/util/vhost/reverseproxy.go b/pkg/util/vhost/reverseproxy.go
deleted file mode 100644
index 975f1d14ecf..00000000000
--- a/pkg/util/vhost/reverseproxy.go
+++ /dev/null
@@ -1,636 +0,0 @@
-// Copyright 2011 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.
-
-// HTTP reverse proxy handler
-
-package vhost
-
-import (
- "context"
- "encoding/base64"
- "fmt"
- "io"
- "log"
- "net"
- "net/http"
- "net/textproto"
- "net/url"
- "strings"
- "sync"
- "time"
-
- "golang.org/x/net/http/httpguts"
-)
-
-// ReverseProxy is an HTTP Handler that takes an incoming request and
-// sends it to another server, proxying the response back to the
-// client.
-//
-// ReverseProxy by default sets the client IP as the value of the
-// X-Forwarded-For header.
-//
-// If an X-Forwarded-For header already exists, the client IP is
-// appended to the existing values. As a special case, if the header
-// exists in the Request.Header map but has a nil value (such as when
-// set by the Director func), the X-Forwarded-For header is
-// not modified.
-//
-// To prevent IP spoofing, be sure to delete any pre-existing
-// X-Forwarded-For header coming from the client or
-// an untrusted proxy.
-type ReverseProxy struct {
- // Director must be a function which modifies
- // the request into a new request to be sent
- // using Transport. Its response is then copied
- // back to the original client unmodified.
- // Director must not access the provided Request
- // after returning.
- Director func(*http.Request)
-
- // The transport used to perform proxy requests.
- // If nil, http.DefaultTransport is used.
- Transport http.RoundTripper
-
- // FlushInterval specifies the flush interval
- // to flush to the client while copying the
- // response body.
- // If zero, no periodic flushing is done.
- // A negative value means to flush immediately
- // after each write to the client.
- // The FlushInterval is ignored when ReverseProxy
- // recognizes a response as a streaming response, or
- // if its ContentLength is -1; for such responses, writes
- // are flushed to the client immediately.
- FlushInterval time.Duration
-
- // ErrorLog specifies an optional logger for errors
- // that occur when attempting to proxy the request.
- // If nil, logging is done via the log package's standard logger.
- ErrorLog *log.Logger
-
- // BufferPool optionally specifies a buffer pool to
- // get byte slices for use by io.CopyBuffer when
- // copying HTTP response bodies.
- BufferPool BufferPool
-
- // ModifyResponse is an optional function that modifies the
- // Response from the backend. It is called if the backend
- // returns a response at all, with any HTTP status code.
- // If the backend is unreachable, the optional ErrorHandler is
- // called without any call to ModifyResponse.
- //
- // If ModifyResponse returns an error, ErrorHandler is called
- // with its error value. If ErrorHandler is nil, its default
- // implementation is used.
- ModifyResponse func(*http.Response) error
-
- // ErrorHandler is an optional function that handles errors
- // reaching the backend or errors from ModifyResponse.
- //
- // If nil, the default is to log the provided error and return
- // a 502 Status Bad Gateway response.
- ErrorHandler func(http.ResponseWriter, *http.Request, error)
-}
-
-// A BufferPool is an interface for getting and returning temporary
-// byte slices for use by io.CopyBuffer.
-type BufferPool interface {
- Get() []byte
- Put([]byte)
-}
-
-func singleJoiningSlash(a, b string) string {
- aslash := strings.HasSuffix(a, "/")
- bslash := strings.HasPrefix(b, "/")
- switch {
- case aslash && bslash:
- return a + b[1:]
- case !aslash && !bslash:
- return a + "/" + b
- }
- return a + b
-}
-
-func joinURLPath(a, b *url.URL) (path, rawpath string) {
- if a.RawPath == "" && b.RawPath == "" {
- return singleJoiningSlash(a.Path, b.Path), ""
- }
- // Same as singleJoiningSlash, but uses EscapedPath to determine
- // whether a slash should be added
- apath := a.EscapedPath()
- bpath := b.EscapedPath()
-
- aslash := strings.HasSuffix(apath, "/")
- bslash := strings.HasPrefix(bpath, "/")
-
- switch {
- case aslash && bslash:
- return a.Path + b.Path[1:], apath + bpath[1:]
- case !aslash && !bslash:
- return a.Path + "/" + b.Path, apath + "/" + bpath
- }
- return a.Path + b.Path, apath + bpath
-}
-
-// NewSingleHostReverseProxy returns a new ReverseProxy that routes
-// URLs to the scheme, host, and base path provided in target. If the
-// target's path is "/base" and the incoming request was for "/dir",
-// the target request will be for /base/dir.
-// NewSingleHostReverseProxy does not rewrite the Host header.
-// To rewrite Host headers, use ReverseProxy directly with a custom
-// Director policy.
-func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
- targetQuery := target.RawQuery
- director := func(req *http.Request) {
- req.URL.Scheme = target.Scheme
- req.URL.Host = target.Host
- req.URL.Path, req.URL.RawPath = joinURLPath(target, req.URL)
- if targetQuery == "" || req.URL.RawQuery == "" {
- req.URL.RawQuery = targetQuery + req.URL.RawQuery
- } else {
- req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
- }
- if _, ok := req.Header["User-Agent"]; !ok {
- // explicitly disable User-Agent so it's not set to default value
- req.Header.Set("User-Agent", "")
- }
- }
- return &ReverseProxy{Director: director}
-}
-
-func copyHeader(dst, src http.Header) {
- for k, vv := range src {
- for _, v := range vv {
- dst.Add(k, v)
- }
- }
-}
-
-// Hop-by-hop headers. These are removed when sent to the backend.
-// As of RFC 7230, hop-by-hop headers are required to appear in the
-// Connection header field. These are the headers defined by the
-// obsoleted RFC 2616 (section 13.5.1) and are used for backward
-// compatibility.
-var hopHeaders = []string{
- "Connection",
- "Proxy-Connection", // non-standard but still sent by libcurl and rejected by e.g. google
- "Keep-Alive",
- "Proxy-Authenticate",
- "Proxy-Authorization",
- "Te", // canonicalized version of "TE"
- "Trailer", // not Trailers per URL above; https://www.rfc-editor.org/errata_search.php?eid=4522
- "Transfer-Encoding",
- "Upgrade",
-}
-
-func (p *ReverseProxy) defaultErrorHandler(rw http.ResponseWriter, req *http.Request, err error) {
- p.logf("http: proxy error: %v", err)
- rw.WriteHeader(http.StatusBadGateway)
-}
-
-func (p *ReverseProxy) getErrorHandler() func(http.ResponseWriter, *http.Request, error) {
- if p.ErrorHandler != nil {
- return p.ErrorHandler
- }
- return p.defaultErrorHandler
-}
-
-// modifyResponse conditionally runs the optional ModifyResponse hook
-// and reports whether the request should proceed.
-func (p *ReverseProxy) modifyResponse(rw http.ResponseWriter, res *http.Response, req *http.Request) bool {
- if p.ModifyResponse == nil {
- return true
- }
- if err := p.ModifyResponse(res); err != nil {
- res.Body.Close()
- p.getErrorHandler()(rw, req, err)
- return false
- }
- return true
-}
-
-func parseBasicAuth(auth string) (username, password string, ok bool) {
- const prefix = "Basic "
- // Case insensitive prefix match. See Issue 22736.
- if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
- return
- }
- c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
- if err != nil {
- return
- }
- cs := string(c)
- s := strings.IndexByte(cs, ':')
- if s < 0 {
- return
- }
- return cs[:s], cs[s+1:], true
-}
-
-func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
- transport := p.Transport
- if transport == nil {
- transport = http.DefaultTransport
- }
-
- ctx := req.Context()
- if cn, ok := rw.(http.CloseNotifier); ok {
- var cancel context.CancelFunc
- ctx, cancel = context.WithCancel(ctx)
- defer cancel()
- notifyChan := cn.CloseNotify()
- go func() {
- select {
- case <-notifyChan:
- cancel()
- case <-ctx.Done():
- }
- }()
- }
-
- outreq := req.Clone(ctx)
- if req.ContentLength == 0 {
- outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
- }
- if outreq.Header == nil {
- outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate
- }
-
- p.Director(outreq)
- outreq.Close = false
-
- reqUpType := upgradeType(outreq.Header)
- removeConnectionHeaders(outreq.Header)
-
- // Remove hop-by-hop headers to the backend. Especially
- // important is "Connection" because we want a persistent
- // connection, regardless of what the client sent to us.
- for _, h := range hopHeaders {
- hv := outreq.Header.Get(h)
- if hv == "" {
- continue
- }
- if h == "Te" && hv == "trailers" {
- // Issue 21096: tell backend applications that
- // care about trailer support that we support
- // trailers. (We do, but we don't go out of
- // our way to advertise that unless the
- // incoming client request thought it was
- // worth mentioning)
- continue
- }
- outreq.Header.Del(h)
- }
-
- // After stripping all the hop-by-hop connection headers above, add back any
- // necessary for protocol upgrades, such as for websockets.
- if reqUpType != "" {
- outreq.Header.Set("Connection", "Upgrade")
- outreq.Header.Set("Upgrade", reqUpType)
- }
-
- if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
- // If we aren't the first proxy retain prior
- // X-Forwarded-For information as a comma+space
- // separated list and fold multiple headers into one.
- prior, ok := outreq.Header["X-Forwarded-For"]
- omit := ok && prior == nil // Issue 38079: nil now means don't populate the header
- if len(prior) > 0 {
- clientIP = strings.Join(prior, ", ") + ", " + clientIP
- }
- if !omit {
- outreq.Header.Set("X-Forwarded-For", clientIP)
- }
- }
-
- res, err := transport.RoundTrip(outreq)
- if err != nil {
- p.getErrorHandler()(rw, outreq, err)
- return
- }
-
- // Deal with 101 Switching Protocols responses: (WebSocket, h2c, etc)
- if res.StatusCode == http.StatusSwitchingProtocols {
- if !p.modifyResponse(rw, res, outreq) {
- return
- }
- p.handleUpgradeResponse(rw, outreq, res)
- return
- }
-
- removeConnectionHeaders(res.Header)
-
- for _, h := range hopHeaders {
- res.Header.Del(h)
- }
-
- if !p.modifyResponse(rw, res, outreq) {
- return
- }
-
- copyHeader(rw.Header(), res.Header)
-
- // The "Trailer" header isn't included in the Transport's response,
- // at least for *http.Transport. Build it up from Trailer.
- announcedTrailers := len(res.Trailer)
- if announcedTrailers > 0 {
- trailerKeys := make([]string, 0, len(res.Trailer))
- for k := range res.Trailer {
- trailerKeys = append(trailerKeys, k)
- }
- rw.Header().Add("Trailer", strings.Join(trailerKeys, ", "))
- }
-
- rw.WriteHeader(res.StatusCode)
-
- err = p.copyResponse(rw, res.Body, p.flushInterval(res))
- if err != nil {
- defer res.Body.Close()
- // Since we're streaming the response, if we run into an error all we can do
- // is abort the request. Issue 23643: ReverseProxy should use ErrAbortHandler
- // on read error while copying body.
- if !shouldPanicOnCopyError(req) {
- p.logf("suppressing panic for copyResponse error in test; copy error: %v", err)
- return
- }
- panic(http.ErrAbortHandler)
- }
- res.Body.Close() // close now, instead of defer, to populate res.Trailer
-
- if len(res.Trailer) > 0 {
- // Force chunking if we saw a response trailer.
- // This prevents net/http from calculating the length for short
- // bodies and adding a Content-Length.
- if fl, ok := rw.(http.Flusher); ok {
- fl.Flush()
- }
- }
-
- if len(res.Trailer) == announcedTrailers {
- copyHeader(rw.Header(), res.Trailer)
- return
- }
-
- for k, vv := range res.Trailer {
- k = http.TrailerPrefix + k
- for _, v := range vv {
- rw.Header().Add(k, v)
- }
- }
-}
-
-var inOurTests bool // whether we're in our own tests
-
-// shouldPanicOnCopyError reports whether the reverse proxy should
-// panic with http.ErrAbortHandler. This is the right thing to do by
-// default, but Go 1.10 and earlier did not, so existing unit tests
-// weren't expecting panics. Only panic in our own tests, or when
-// running under the HTTP server.
-func shouldPanicOnCopyError(req *http.Request) bool {
- if inOurTests {
- // Our tests know to handle this panic.
- return true
- }
- if req.Context().Value(http.ServerContextKey) != nil {
- // We seem to be running under an HTTP server, so
- // it'll recover the panic.
- return true
- }
- // Otherwise act like Go 1.10 and earlier to not break
- // existing tests.
- return false
-}
-
-// removeConnectionHeaders removes hop-by-hop headers listed in the "Connection" header of h.
-// See RFC 7230, section 6.1
-func removeConnectionHeaders(h http.Header) {
- for _, f := range h["Connection"] {
- for _, sf := range strings.Split(f, ",") {
- if sf = textproto.TrimString(sf); sf != "" {
- h.Del(sf)
- }
- }
- }
-}
-
-// flushInterval returns the p.FlushInterval value, conditionally
-// overriding its value for a specific request/response.
-func (p *ReverseProxy) flushInterval(res *http.Response) time.Duration {
- resCT := res.Header.Get("Content-Type")
-
- // For Server-Sent Events responses, flush immediately.
- // The MIME type is defined in https://www.w3.org/TR/eventsource/#text-event-stream
- if resCT == "text/event-stream" {
- return -1 // negative means immediately
- }
-
- // We might have the case of streaming for which Content-Length might be unset.
- if res.ContentLength == -1 {
- return -1
- }
-
- return p.FlushInterval
-}
-
-func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader, flushInterval time.Duration) error {
- if flushInterval != 0 {
- if wf, ok := dst.(writeFlusher); ok {
- mlw := &maxLatencyWriter{
- dst: wf,
- latency: flushInterval,
- }
- defer mlw.stop()
-
- // set up initial timer so headers get flushed even if body writes are delayed
- mlw.flushPending = true
- mlw.t = time.AfterFunc(flushInterval, mlw.delayedFlush)
-
- dst = mlw
- }
- }
-
- var buf []byte
- if p.BufferPool != nil {
- buf = p.BufferPool.Get()
- defer p.BufferPool.Put(buf)
- }
- _, err := p.copyBuffer(dst, src, buf)
- return err
-}
-
-// copyBuffer returns any write errors or non-EOF read errors, and the amount
-// of bytes written.
-func (p *ReverseProxy) copyBuffer(dst io.Writer, src io.Reader, buf []byte) (int64, error) {
- if len(buf) == 0 {
- buf = make([]byte, 32*1024)
- }
- var written int64
- for {
- nr, rerr := src.Read(buf)
- if rerr != nil && rerr != io.EOF && rerr != context.Canceled {
- p.logf("httputil: ReverseProxy read error during body copy: %v", rerr)
- }
- if nr > 0 {
- nw, werr := dst.Write(buf[:nr])
- if nw > 0 {
- written += int64(nw)
- }
- if werr != nil {
- return written, werr
- }
- if nr != nw {
- return written, io.ErrShortWrite
- }
- }
- if rerr != nil {
- if rerr == io.EOF {
- rerr = nil
- }
- return written, rerr
- }
- }
-}
-
-func (p *ReverseProxy) logf(format string, args ...interface{}) {
- if p.ErrorLog != nil {
- p.ErrorLog.Printf(format, args...)
- } else {
- log.Printf(format, args...)
- }
-}
-
-type writeFlusher interface {
- io.Writer
- http.Flusher
-}
-
-type maxLatencyWriter struct {
- dst writeFlusher
- latency time.Duration // non-zero; negative means to flush immediately
-
- mu sync.Mutex // protects t, flushPending, and dst.Flush
- t *time.Timer
- flushPending bool
-}
-
-func (m *maxLatencyWriter) Write(p []byte) (n int, err error) {
- m.mu.Lock()
- defer m.mu.Unlock()
- n, err = m.dst.Write(p)
- if m.latency < 0 {
- m.dst.Flush()
- return
- }
- if m.flushPending {
- return
- }
- if m.t == nil {
- m.t = time.AfterFunc(m.latency, m.delayedFlush)
- } else {
- m.t.Reset(m.latency)
- }
- m.flushPending = true
- return
-}
-
-func (m *maxLatencyWriter) delayedFlush() {
- m.mu.Lock()
- defer m.mu.Unlock()
- if !m.flushPending { // if stop was called but AfterFunc already started this goroutine
- return
- }
- m.dst.Flush()
- m.flushPending = false
-}
-
-func (m *maxLatencyWriter) stop() {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.flushPending = false
- if m.t != nil {
- m.t.Stop()
- }
-}
-
-func upgradeType(h http.Header) string {
- if !httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade") {
- return ""
- }
- return strings.ToLower(h.Get("Upgrade"))
-}
-
-func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.Request, res *http.Response) {
- reqUpType := upgradeType(req.Header)
- resUpType := upgradeType(res.Header)
- if reqUpType != resUpType {
- p.getErrorHandler()(rw, req, fmt.Errorf("backend tried to switch protocol %q when %q was requested", resUpType, reqUpType))
- return
- }
-
- hj, ok := rw.(http.Hijacker)
- if !ok {
- p.getErrorHandler()(rw, req, fmt.Errorf("can't switch protocols using non-Hijacker ResponseWriter type %T", rw))
- return
- }
- backConn, ok := res.Body.(io.ReadWriteCloser)
- if !ok {
- p.getErrorHandler()(rw, req, fmt.Errorf("internal error: 101 switching protocols response with non-writable body"))
- return
- }
-
- backConnCloseCh := make(chan bool)
- go func() {
- // Ensure that the cancelation of a request closes the backend.
- // See issue https://golang.org/issue/35559.
- select {
- case <-req.Context().Done():
- case <-backConnCloseCh:
- }
- backConn.Close()
- }()
-
- defer close(backConnCloseCh)
-
- conn, brw, err := hj.Hijack()
- if err != nil {
- p.getErrorHandler()(rw, req, fmt.Errorf("Hijack failed on protocol switch: %v", err))
- return
- }
- defer conn.Close()
-
- copyHeader(rw.Header(), res.Header)
-
- res.Header = rw.Header()
- res.Body = nil // so res.Write only writes the headers; we have res.Body in backConn above
- if err := res.Write(brw); err != nil {
- p.getErrorHandler()(rw, req, fmt.Errorf("response write: %v", err))
- return
- }
- if err := brw.Flush(); err != nil {
- p.getErrorHandler()(rw, req, fmt.Errorf("response flush: %v", err))
- return
- }
- errc := make(chan error, 1)
- spc := switchProtocolCopier{user: conn, backend: backConn}
- go spc.copyToBackend(errc)
- go spc.copyFromBackend(errc)
- <-errc
- return
-}
-
-// switchProtocolCopier exists so goroutines proxying data back and
-// forth have nice names in stacks.
-type switchProtocolCopier struct {
- user, backend io.ReadWriter
-}
-
-func (c switchProtocolCopier) copyFromBackend(errc chan<- error) {
- _, err := io.Copy(c.user, c.backend)
- errc <- err
-}
-
-func (c switchProtocolCopier) copyToBackend(errc chan<- error) {
- _, err := io.Copy(c.backend, c.user)
- errc <- err
-}
diff --git a/pkg/util/vhost/router.go b/pkg/util/vhost/router.go
index 768420a47e7..281e164bdf9 100644
--- a/pkg/util/vhost/router.go
+++ b/pkg/util/vhost/router.go
@@ -7,9 +7,7 @@ import (
"sync"
)
-var (
- ErrRouterConfigConflict = errors.New("router config conflict")
-)
+var ErrRouterConfigConflict = errors.New("router config conflict")
type routerByHTTPUser map[string][]*Router
@@ -133,9 +131,11 @@ 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
}
diff --git a/pkg/util/vhost/vhost.go b/pkg/util/vhost/vhost.go
index 2957cec4e78..651d9607221 100644
--- a/pkg/util/vhost/vhost.go
+++ b/pkg/util/vhost/vhost.go
@@ -19,27 +19,34 @@ import (
"strings"
"time"
+ "github.com/fatedier/golib/errors"
+
"github.com/fatedier/frp/pkg/util/log"
frpNet "github.com/fatedier/frp/pkg/util/net"
"github.com/fatedier/frp/pkg/util/xlog"
-
- "github.com/fatedier/golib/errors"
)
type RouteInfo string
const (
- RouteInfoURL RouteInfo = "url"
- RouteInfoHost RouteInfo = "host"
- RouteInfoHTTPUser RouteInfo = "httpUser"
- RouteInfoRemote RouteInfo = "remote"
- RouteInfoURLHost RouteInfo = "urlHost"
+ RouteInfoKey RouteInfo = "routeInfo"
)
-type muxFunc func(net.Conn) (net.Conn, map[string]string, error)
-type httpAuthFunc func(net.Conn, string, string, string) (bool, error)
-type hostRewriteFunc func(net.Conn, string) (net.Conn, error)
-type successFunc func(net.Conn, map[string]string) error
+type RequestRouteInfo struct {
+ URL string
+ Host string
+ HTTPUser string
+ RemoteAddr string
+ URLHost string
+ Endpoint string
+}
+
+type (
+ muxFunc func(net.Conn) (net.Conn, map[string]string, error)
+ httpAuthFunc func(net.Conn, string, string, string) (bool, error)
+ hostRewriteFunc func(net.Conn, string) (net.Conn, error)
+ successFunc func(net.Conn, map[string]string) error
+)
// Muxer is only used for https and tcpmux proxy.
type Muxer struct {
@@ -60,7 +67,6 @@ func NewMuxer(
rewriteFunc hostRewriteFunc,
timeout time.Duration,
) (mux *Muxer, err error) {
-
mux = &Muxer{
listener: listener,
timeout: timeout,
@@ -74,8 +80,12 @@ func NewMuxer(
return mux, nil
}
+type ChooseEndpointFunc func() (string, error)
+
type CreateConnFunc func(remoteAddr string) (net.Conn, error)
+type CreateConnByEndpointFunc func(endpoint, remoteAddr string) (net.Conn, error)
+
// RouteConfig is the params used to match HTTP requests
type RouteConfig struct {
Domain string
@@ -86,7 +96,9 @@ type RouteConfig struct {
Headers map[string]string
RouteByHTTPUser string
- CreateConnFn CreateConnFunc
+ CreateConnFn CreateConnFunc
+ ChooseEndpointFn ChooseEndpointFunc
+ CreateConnByEndpointFn CreateConnByEndpointFunc
}
// listen for a new domain name, if rewriteHost is not empty and rewriteFunc is not nil
@@ -111,9 +123,8 @@ func (v *Muxer) Listen(ctx context.Context, cfg *RouteConfig) (l *Listener, err
}
func (v *Muxer) getListener(name, path, httpUser string) (*Listener, bool) {
-
findRouter := func(inName, inPath, inHTTPUser string) (*Listener, bool) {
- vr, ok := v.registryRouter.Get(inName, inPath, httpUser)
+ vr, ok := v.registryRouter.Get(inName, inPath, inHTTPUser)
if ok {
return vr.payload.(*Listener), true
}
@@ -167,14 +178,14 @@ func (v *Muxer) run() {
func (v *Muxer) handle(c net.Conn) {
if err := c.SetDeadline(time.Now().Add(v.timeout)); err != nil {
- c.Close()
+ _ = c.Close()
return
}
sConn, reqInfoMap, err := v.vhostFunc(c)
if err != nil {
log.Debug("get hostname from http/https request error: %v", err)
- c.Close()
+ _ = c.Close()
return
}
@@ -184,9 +195,12 @@ func (v *Muxer) handle(c net.Conn) {
l, ok := v.getListener(name, path, httpUser)
if !ok {
res := notFoundResponse()
- res.Write(c)
+ if res.Body != nil {
+ defer res.Body.Close()
+ }
+ _ = res.Write(c)
log.Debug("http request for host [%s] path [%s] httpUser [%s] not found", name, path, httpUser)
- c.Close()
+ _ = c.Close()
return
}
@@ -194,7 +208,7 @@ func (v *Muxer) handle(c net.Conn) {
if v.successFunc != nil {
if err := v.successFunc(c, reqInfoMap); err != nil {
xl.Info("success func failure on vhost connection: %v", err)
- c.Close()
+ _ = c.Close()
return
}
}
@@ -203,17 +217,20 @@ func (v *Muxer) handle(c net.Conn) {
// then verify user access
if l.mux.authFunc != nil && l.userName != "" && l.passWord != "" {
bAccess, err := l.mux.authFunc(c, l.userName, l.passWord, reqInfoMap["Authorization"])
- if bAccess == false || err != nil {
+ if !bAccess || err != nil {
xl.Debug("check http Authorization failed")
res := noAuthResponse()
- res.Write(c)
- c.Close()
+ if res.Body != nil {
+ defer res.Body.Close()
+ }
+ _ = res.Write(c)
+ _ = c.Close()
return
}
}
if err = sConn.SetDeadline(time.Time{}); err != nil {
- c.Close()
+ _ = c.Close()
return
}
c = sConn
diff --git a/server/control.go b/server/control.go
index 197c94de968..3fcd3ae434a 100644
--- a/server/control.go
+++ b/server/control.go
@@ -23,6 +23,10 @@ import (
"sync"
"time"
+ "github.com/fatedier/golib/control/shutdown"
+ "github.com/fatedier/golib/crypto"
+ "github.com/fatedier/golib/errors"
+
"github.com/fatedier/frp/pkg/auth"
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/consts"
@@ -35,10 +39,6 @@ import (
"github.com/fatedier/frp/server/controller"
"github.com/fatedier/frp/server/metrics"
"github.com/fatedier/frp/server/proxy"
-
- "github.com/fatedier/golib/control/shutdown"
- "github.com/fatedier/golib/crypto"
- "github.com/fatedier/golib/errors"
)
type ControlManager struct {
@@ -154,7 +154,6 @@ func NewControl(
loginMsg *msg.Login,
serverCfg config.ServerCommonConf,
) *Control {
-
poolCount := loginMsg.PoolCount
if poolCount > int(serverCfg.MaxPoolCount) {
poolCount = int(serverCfg.MaxPoolCount)
@@ -193,7 +192,7 @@ func (ctl *Control) Start() {
ServerUDPPort: ctl.serverCfg.BindUDPPort,
Error: "",
}
- msg.WriteMsg(ctl.conn, loginRespMsg)
+ _ = msg.WriteMsg(ctl.conn, loginRespMsg)
go ctl.writer()
for i := 0; i < ctl.poolCount; i++ {
@@ -270,7 +269,7 @@ func (ctl *Control) GetWorkConn() (workConn net.Conn, err error) {
}
// When we get a work connection from pool, replace it with a new one.
- errors.PanicToError(func() {
+ _ = errors.PanicToError(func() {
ctl.sendCh <- &msg.ReqWorkConn{}
})
return
@@ -388,7 +387,7 @@ func (ctl *Control) stoper() {
},
}
go func() {
- ctl.pluginManager.CloseProxy(notifyContent)
+ _ = ctl.pluginManager.CloseProxy(notifyContent)
}()
}
@@ -467,7 +466,7 @@ func (ctl *Control) manager() {
}
ctl.sendCh <- resp
case *msg.CloseProxy:
- ctl.CloseProxy(m)
+ _ = ctl.CloseProxy(m)
xl.Info("close proxy [%s] success", m.ProxyName)
case *msg.Ping:
content := &plugin.PingContent{
@@ -528,13 +527,13 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err
err = fmt.Errorf("exceed the max_ports_per_client")
return
}
- ctl.portsUsedNum = ctl.portsUsedNum + pxy.GetUsedPortsNum()
+ ctl.portsUsedNum += pxy.GetUsedPortsNum()
ctl.mu.Unlock()
defer func() {
if err != nil {
ctl.mu.Lock()
- ctl.portsUsedNum = ctl.portsUsedNum - pxy.GetUsedPortsNum()
+ ctl.portsUsedNum -= pxy.GetUsedPortsNum()
ctl.mu.Unlock()
}
}()
@@ -570,7 +569,7 @@ func (ctl *Control) CloseProxy(closeMsg *msg.CloseProxy) (err error) {
}
if ctl.serverCfg.MaxPortsPerClient > 0 {
- ctl.portsUsedNum = ctl.portsUsedNum - pxy.GetUsedPortsNum()
+ ctl.portsUsedNum -= pxy.GetUsedPortsNum()
}
pxy.Close()
ctl.pxyManager.Del(pxy.GetName())
@@ -590,7 +589,7 @@ func (ctl *Control) CloseProxy(closeMsg *msg.CloseProxy) (err error) {
},
}
go func() {
- ctl.pluginManager.CloseProxy(notifyContent)
+ _ = ctl.pluginManager.CloseProxy(notifyContent)
}()
return
diff --git a/server/dashboard.go b/server/dashboard.go
index 68e99f8a2c1..02c86325b61 100644
--- a/server/dashboard.go
+++ b/server/dashboard.go
@@ -21,11 +21,11 @@ import (
"net/http/pprof"
"time"
- "github.com/fatedier/frp/assets"
- frpNet "github.com/fatedier/frp/pkg/util/net"
-
"github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus/promhttp"
+
+ "github.com/fatedier/frp/assets"
+ frpNet "github.com/fatedier/frp/pkg/util/net"
)
var (
@@ -92,6 +92,8 @@ func (svr *Service) RunDashboardServer(address string) (err error) {
}
ln = tls.NewListener(ln, tlsCfg)
}
- go server.Serve(ln)
+ go func() {
+ _ = server.Serve(ln)
+ }()
return
}
diff --git a/server/dashboard_api.go b/server/dashboard_api.go
index 7d159c7a89a..6f7ecfd793c 100644
--- a/server/dashboard_api.go
+++ b/server/dashboard_api.go
@@ -18,13 +18,13 @@ import (
"encoding/json"
"net/http"
+ "github.com/gorilla/mux"
+
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/consts"
"github.com/fatedier/frp/pkg/metrics/mem"
"github.com/fatedier/frp/pkg/util/log"
"github.com/fatedier/frp/pkg/util/version"
-
- "github.com/gorilla/mux"
)
type GeneralResponse struct {
@@ -63,7 +63,7 @@ func (svr *Service) APIServerInfo(w http.ResponseWriter, r *http.Request) {
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
- w.Write([]byte(res.Msg))
+ _, _ = w.Write([]byte(res.Msg))
}
}()
@@ -179,7 +179,7 @@ func (svr *Service) APIProxyByType(w http.ResponseWriter, r *http.Request) {
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
- w.Write([]byte(res.Msg))
+ _, _ = w.Write([]byte(res.Msg))
}
}()
log.Info("Http request: [%s]", r.URL.Path)
@@ -245,12 +245,12 @@ func (svr *Service) APIProxyByTypeAndName(w http.ResponseWriter, r *http.Request
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
- w.Write([]byte(res.Msg))
+ _, _ = w.Write([]byte(res.Msg))
}
}()
log.Info("Http request: [%s]", r.URL.Path)
- proxyStatsResp := GetProxyStatsResp{}
+ var proxyStatsResp GetProxyStatsResp
proxyStatsResp, res.Code, res.Msg = svr.getProxyStatsByTypeAndName(proxyType, name)
if res.Code != 200 {
return
@@ -313,7 +313,7 @@ func (svr *Service) APIProxyTraffic(w http.ResponseWriter, r *http.Request) {
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
w.WriteHeader(res.Code)
if len(res.Msg) > 0 {
- w.Write([]byte(res.Msg))
+ _, _ = w.Write([]byte(res.Msg))
}
}()
log.Info("Http request: [%s]", r.URL.Path)
diff --git a/server/group/http.go b/server/group/http.go
index fb00f0c7086..640919251d3 100644
--- a/server/group/http.go
+++ b/server/group/http.go
@@ -10,7 +10,7 @@ import (
)
type HTTPGroupController struct {
- // groups by indexKey
+ // groups indexed by group name
groups map[string]*HTTPGroup
// register createConn for each group to vhostRouter.
@@ -31,7 +31,6 @@ func (ctl *HTTPGroupController) Register(
proxyName, group, groupKey string,
routeConfig vhost.RouteConfig,
) (err error) {
-
indexKey := group
ctl.mu.Lock()
g, ok := ctl.groups[indexKey]
@@ -66,7 +65,7 @@ type HTTPGroup struct {
location string
routeByHTTPUser string
- // CreateConnFuncs indexed by echo proxy name
+ // CreateConnFuncs indexed by proxy name
createFuncs map[string]vhost.CreateConnFunc
pxyNames []string
index uint64
@@ -86,13 +85,14 @@ func (g *HTTPGroup) Register(
proxyName, group, groupKey string,
routeConfig vhost.RouteConfig,
) (err error) {
-
g.mu.Lock()
defer g.mu.Unlock()
if len(g.createFuncs) == 0 {
// the first proxy in this group
tmp := routeConfig // copy object
tmp.CreateConnFn = g.createConn
+ tmp.ChooseEndpointFn = g.chooseEndpoint
+ tmp.CreateConnByEndpointFn = g.createConnByEndpoint
err = g.ctl.vhostRouter.Add(routeConfig.Domain, routeConfig.Location, routeConfig.RouteByHTTPUser, &tmp)
if err != nil {
return
@@ -152,7 +152,7 @@ func (g *HTTPGroup) createConn(remoteAddr string) (net.Conn, error) {
routeByHTTPUser := g.routeByHTTPUser
if len(g.pxyNames) > 0 {
name := g.pxyNames[int(newIndex)%len(g.pxyNames)]
- f, _ = g.createFuncs[name]
+ f = g.createFuncs[name]
}
g.mu.RUnlock()
@@ -163,3 +163,36 @@ func (g *HTTPGroup) createConn(remoteAddr string) (net.Conn, error) {
return f(remoteAddr)
}
+
+func (g *HTTPGroup) chooseEndpoint() (string, error) {
+ newIndex := atomic.AddUint64(&g.index, 1)
+ name := ""
+
+ g.mu.RLock()
+ group := g.group
+ domain := g.domain
+ location := g.location
+ routeByHTTPUser := g.routeByHTTPUser
+ if len(g.pxyNames) > 0 {
+ name = g.pxyNames[int(newIndex)%len(g.pxyNames)]
+ }
+ g.mu.RUnlock()
+
+ if name == "" {
+ return "", fmt.Errorf("no healthy endpoint for http group [%s], domain [%s], location [%s], routeByHTTPUser [%s]",
+ group, domain, location, routeByHTTPUser)
+ }
+ return name, nil
+}
+
+func (g *HTTPGroup) createConnByEndpoint(endpoint, remoteAddr string) (net.Conn, error) {
+ var f vhost.CreateConnFunc
+ g.mu.RLock()
+ f = g.createFuncs[endpoint]
+ g.mu.RUnlock()
+
+ if f == nil {
+ return nil, fmt.Errorf("no CreateConnFunc for endpoint [%s] in group [%s]", endpoint, g.group)
+ }
+ return f(remoteAddr)
+}
diff --git a/server/group/tcp.go b/server/group/tcp.go
index c7fd2b2799d..c0dcd5f7e3c 100644
--- a/server/group/tcp.go
+++ b/server/group/tcp.go
@@ -19,9 +19,9 @@ import (
"strconv"
"sync"
- "github.com/fatedier/frp/server/ports"
-
gerr "github.com/fatedier/golib/errors"
+
+ "github.com/fatedier/frp/server/ports"
)
// TCPGroupCtl manage all TCPGroups
@@ -44,8 +44,8 @@ func NewTCPGroupCtl(portManager *ports.Manager) *TCPGroupCtl {
// Listen is the wrapper for TCPGroup's Listen
// If there are no group, we will create one here
func (tgc *TCPGroupCtl) Listen(proxyName string, group string, groupKey string,
- addr string, port int) (l net.Listener, realPort int, err error) {
-
+ addr string, port int,
+) (l net.Listener, realPort int, err error) {
tgc.mu.Lock()
tcpGroup, ok := tgc.groups[group]
if !ok {
@@ -73,7 +73,6 @@ type TCPGroup struct {
realPort int
acceptCh chan net.Conn
- index uint64
tcpLn net.Listener
lns []*TCPGroupListener
ctl *TCPGroupCtl
diff --git a/server/group/tcpmux.go b/server/group/tcpmux.go
index fd805d91ebe..2da85cee4fe 100644
--- a/server/group/tcpmux.go
+++ b/server/group/tcpmux.go
@@ -20,11 +20,11 @@ import (
"net"
"sync"
+ gerr "github.com/fatedier/golib/errors"
+
"github.com/fatedier/frp/pkg/consts"
"github.com/fatedier/frp/pkg/util/tcpmux"
"github.com/fatedier/frp/pkg/util/vhost"
-
- gerr "github.com/fatedier/golib/errors"
)
// TCPMuxGroupCtl manage all TCPMuxGroups
@@ -51,7 +51,6 @@ func (tmgc *TCPMuxGroupCtl) Listen(
multiplexer, group, groupKey string,
routeConfig vhost.RouteConfig,
) (l net.Listener, err error) {
-
tmgc.mu.Lock()
tcpMuxGroup, ok := tmgc.groups[group]
if !ok {
@@ -84,7 +83,6 @@ type TCPMuxGroup struct {
routeByHTTPUser string
acceptCh chan net.Conn
- index uint64
tcpMuxLn net.Listener
lns []*TCPMuxGroupListener
ctl *TCPMuxGroupCtl
@@ -108,7 +106,6 @@ func (tmg *TCPMuxGroup) HTTPConnectListen(
group, groupKey string,
routeConfig vhost.RouteConfig,
) (ln *TCPMuxGroupListener, err error) {
-
tmg.mu.Lock()
defer tmg.mu.Unlock()
if len(tmg.lns) == 0 {
diff --git a/server/proxy/http.go b/server/proxy/http.go
index e0e2f23cb50..e70cb65f1c5 100644
--- a/server/proxy/http.go
+++ b/server/proxy/http.go
@@ -19,13 +19,13 @@ import (
"net"
"strings"
+ frpIo "github.com/fatedier/golib/io"
+
"github.com/fatedier/frp/pkg/config"
frpNet "github.com/fatedier/frp/pkg/util/net"
"github.com/fatedier/frp/pkg/util/util"
"github.com/fatedier/frp/pkg/util/vhost"
"github.com/fatedier/frp/server/metrics"
-
- frpIo "github.com/fatedier/golib/io"
)
type HTTPProxy struct {
@@ -89,7 +89,7 @@ func (pxy *HTTPProxy) Run() (remoteAddr string, err error) {
pxy.rc.HTTPReverseProxy.UnRegister(tmpRouteConfig)
})
}
- addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(pxy.serverCfg.VhostHTTPPort)))
+ addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, pxy.serverCfg.VhostHTTPPort))
xl.Info("http proxy listen for host [%s] location [%s] group [%s], routeByHTTPUser [%s]",
routeConfig.Domain, routeConfig.Location, pxy.cfg.Group, pxy.cfg.RouteByHTTPUser)
}
diff --git a/server/proxy/https.go b/server/proxy/https.go
index cd566462201..42ecf35d76f 100644
--- a/server/proxy/https.go
+++ b/server/proxy/https.go
@@ -62,7 +62,7 @@ func (pxy *HTTPSProxy) Run() (remoteAddr string, err error) {
}
xl.Info("https proxy listen for host [%s]", routeConfig.Domain)
pxy.listeners = append(pxy.listeners, l)
- addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(pxy.serverCfg.VhostHTTPSPort)))
+ addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, pxy.serverCfg.VhostHTTPSPort))
}
pxy.startListenHandler(pxy, HandleUserTCPConnection)
diff --git a/server/proxy/proxy.go b/server/proxy/proxy.go
index 43c2c74e9b1..808d93161d5 100644
--- a/server/proxy/proxy.go
+++ b/server/proxy/proxy.go
@@ -23,6 +23,8 @@ import (
"sync"
"time"
+ frpIo "github.com/fatedier/golib/io"
+
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/msg"
plugin "github.com/fatedier/frp/pkg/plugin/server"
@@ -30,8 +32,6 @@ import (
"github.com/fatedier/frp/pkg/util/xlog"
"github.com/fatedier/frp/server/controller"
"github.com/fatedier/frp/server/metrics"
-
- frpIo "github.com/fatedier/golib/io"
)
type GetWorkConnFn func() (net.Conn, error)
@@ -184,8 +184,8 @@ func (pxy *BaseProxy) startListenHandler(p Proxy, handler func(Proxy, net.Conn,
}
func NewProxy(ctx context.Context, userInfo plugin.UserInfo, rc *controller.ResourceController, poolCount int,
- getWorkConnFn GetWorkConnFn, pxyConf config.ProxyConf, serverCfg config.ServerCommonConf) (pxy Proxy, err error) {
-
+ getWorkConnFn GetWorkConnFn, pxyConf config.ProxyConf, serverCfg config.ServerCommonConf,
+) (pxy Proxy, err error) {
xl := xlog.FromContextSafe(ctx).Spawn().AppendPrefix(pxyConf.GetBaseInfo().ProxyName)
basePxy := BaseProxy{
name: pxyConf.GetBaseInfo().ProxyName,
diff --git a/server/proxy/udp.go b/server/proxy/udp.go
index 9e3c067509d..53865540325 100644
--- a/server/proxy/udp.go
+++ b/server/proxy/udp.go
@@ -22,14 +22,14 @@ import (
"strconv"
"time"
+ "github.com/fatedier/golib/errors"
+ frpIo "github.com/fatedier/golib/io"
+
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/msg"
"github.com/fatedier/frp/pkg/proto/udp"
frpNet "github.com/fatedier/frp/pkg/util/net"
"github.com/fatedier/frp/server/metrics"
-
- "github.com/fatedier/golib/errors"
- frpIo "github.com/fatedier/golib/io"
)
type UDPProxy struct {
@@ -98,18 +98,20 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) {
)
xl.Trace("loop waiting message from udp workConn")
// client will send heartbeat in workConn for keeping alive
- conn.SetReadDeadline(time.Now().Add(time.Duration(60) * time.Second))
+ _ = conn.SetReadDeadline(time.Now().Add(time.Duration(60) * time.Second))
if rawMsg, errRet = msg.ReadMsg(conn); errRet != nil {
xl.Warn("read from workConn for udp error: %v", errRet)
- conn.Close()
+ _ = conn.Close()
// notify proxy to start a new work connection
// ignore error here, it means the proxy is closed
- errors.PanicToError(func() {
+ _ = errors.PanicToError(func() {
pxy.checkCloseCh <- 1
})
return
}
- conn.SetReadDeadline(time.Time{})
+ if err := conn.SetReadDeadline(time.Time{}); err != nil {
+ xl.Warn("set read deadline error: %v", err)
+ }
switch m := rawMsg.(type) {
case *msg.Ping:
xl.Trace("udp work conn get ping message")
diff --git a/server/proxy/xtcp.go b/server/proxy/xtcp.go
index 317a3d484c9..a1b45d5446c 100644
--- a/server/proxy/xtcp.go
+++ b/server/proxy/xtcp.go
@@ -17,10 +17,10 @@ package proxy
import (
"fmt"
+ "github.com/fatedier/golib/errors"
+
"github.com/fatedier/frp/pkg/config"
"github.com/fatedier/frp/pkg/msg"
-
- "github.com/fatedier/golib/errors"
)
type XTCPProxy struct {
@@ -91,7 +91,7 @@ func (pxy *XTCPProxy) GetConf() config.ProxyConf {
func (pxy *XTCPProxy) Close() {
pxy.BaseProxy.Close()
pxy.rc.NatHoleController.CloseClient(pxy.GetName())
- errors.PanicToError(func() {
+ _ = errors.PanicToError(func() {
close(pxy.closeCh)
})
}
diff --git a/server/service.go b/server/service.go
index c3d398b2749..fc59b39c64b 100644
--- a/server/service.go
+++ b/server/service.go
@@ -26,6 +26,10 @@ import (
"strconv"
"time"
+ "github.com/fatedier/golib/net/mux"
+ fmux "github.com/hashicorp/yamux"
+ quic "github.com/lucas-clemente/quic-go"
+
"github.com/fatedier/frp/assets"
"github.com/fatedier/frp/pkg/auth"
"github.com/fatedier/frp/pkg/config"
@@ -47,9 +51,6 @@ import (
"github.com/fatedier/frp/server/ports"
"github.com/fatedier/frp/server/proxy"
"github.com/fatedier/frp/server/visitor"
-
- "github.com/fatedier/golib/net/mux"
- fmux "github.com/hashicorp/yamux"
)
const (
@@ -68,6 +69,9 @@ type Service struct {
// Accept connections using kcp
kcpListener net.Listener
+ // Accept connections using quic
+ quicListener quic.Listener
+
// Accept connections using websocket
websocketListener net.Listener
@@ -127,26 +131,26 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.TCPMuxHTTPConnectPort))
l, err = net.Listen("tcp", address)
if err != nil {
- err = fmt.Errorf("Create server listener error, %v", err)
+ err = fmt.Errorf("create server listener error, %v", err)
return
}
svr.rc.TCPMuxHTTPConnectMuxer, err = tcpmux.NewHTTPConnectTCPMuxer(l, cfg.TCPMuxPassthrough, vhostReadWriteTimeout)
if err != nil {
- err = fmt.Errorf("Create vhost tcpMuxer error, %v", err)
+ err = fmt.Errorf("create vhost tcpMuxer error, %v", err)
return
}
log.Info("tcpmux httpconnect multiplexer listen on %s, passthough: %v", address, cfg.TCPMuxPassthrough)
}
// Init all plugins
- plugin_names := make([]string, 0, len(cfg.HTTPPlugins))
+ pluginNames := make([]string, 0, len(cfg.HTTPPlugins))
for n := range cfg.HTTPPlugins {
- plugin_names = append(plugin_names, n)
+ pluginNames = append(pluginNames, n)
}
- sort.Strings(plugin_names)
+ sort.Strings(pluginNames)
- for _, name := range plugin_names {
+ for _, name := range pluginNames {
svr.pluginManager.Register(plugin.NewHTTPPluginOptions(cfg.HTTPPlugins[name]))
log.Info("plugin [%s] has been registered", name)
}
@@ -181,13 +185,15 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.BindPort))
ln, err := net.Listen("tcp", address)
if err != nil {
- err = fmt.Errorf("Create server listener error, %v", err)
+ err = fmt.Errorf("create server listener error, %v", err)
return
}
svr.muxer = mux.NewMux(ln)
svr.muxer.SetKeepAlive(time.Duration(cfg.TCPKeepAlive) * time.Second)
- go svr.muxer.Serve()
+ go func() {
+ _ = svr.muxer.Serve()
+ }()
ln = svr.muxer.DefaultListener()
svr.listener = ln
@@ -198,12 +204,28 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.KCPBindPort))
svr.kcpListener, err = frpNet.ListenKcp(address)
if err != nil {
- err = fmt.Errorf("Listen on kcp address udp %s error: %v", address, err)
+ err = fmt.Errorf("listen on kcp udp address %s error: %v", address, err)
return
}
log.Info("frps kcp listen on udp %s", address)
}
+ if cfg.QUICBindPort > 0 {
+ address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.QUICBindPort))
+ quicTLSCfg := tlsConfig.Clone()
+ quicTLSCfg.NextProtos = []string{"frp"}
+ svr.quicListener, err = quic.ListenAddr(address, quicTLSCfg, &quic.Config{
+ MaxIdleTimeout: time.Duration(cfg.QUICMaxIdleTimeout) * time.Second,
+ MaxIncomingStreams: int64(cfg.QUICMaxIncomingStreams),
+ KeepAlivePeriod: time.Duration(cfg.QUICKeepalivePeriod) * time.Second,
+ })
+ if err != nil {
+ err = fmt.Errorf("listen on quic udp address %s error: %v", address, err)
+ return
+ }
+ log.Info("frps quic listen on quic %s", address)
+ }
+
// Listen for accepting connections from client using websocket protocol.
websocketPrefix := []byte("GET " + frpNet.FrpWebsocketPath)
websocketLn := svr.muxer.Listen(0, uint32(len(websocketPrefix)), func(data []byte) bool {
@@ -229,11 +251,13 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
} else {
l, err = net.Listen("tcp", address)
if err != nil {
- err = fmt.Errorf("Create vhost http listener error, %v", err)
+ err = fmt.Errorf("create vhost http listener error, %v", err)
return
}
}
- go server.Serve(l)
+ go func() {
+ _ = server.Serve(l)
+ }()
log.Info("http service listen on %s", address)
}
@@ -246,7 +270,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.VhostHTTPSPort))
l, err = net.Listen("tcp", address)
if err != nil {
- err = fmt.Errorf("Create server listener error, %v", err)
+ err = fmt.Errorf("create server listener error, %v", err)
return
}
log.Info("https service listen on %s", address)
@@ -254,7 +278,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
svr.rc.VhostHTTPSMuxer, err = vhost.NewHTTPSMuxer(l, vhostReadWriteTimeout)
if err != nil {
- err = fmt.Errorf("Create vhost httpsMuxer error, %v", err)
+ err = fmt.Errorf("create vhost httpsMuxer error, %v", err)
return
}
}
@@ -271,7 +295,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.BindUDPPort))
nc, err = nathole.NewController(address)
if err != nil {
- err = fmt.Errorf("Create nat hole controller error, %v", err)
+ err = fmt.Errorf("create nat hole controller error, %v", err)
return
}
svr.rc.NatHoleController = nc
@@ -287,7 +311,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
address := net.JoinHostPort(cfg.DashboardAddr, strconv.Itoa(cfg.DashboardPort))
err = svr.RunDashboardServer(address)
if err != nil {
- err = fmt.Errorf("Create dashboard web server error, %v", err)
+ err = fmt.Errorf("create dashboard web server error, %v", err)
return
}
log.Info("Dashboard listen on %s", address)
@@ -306,9 +330,12 @@ func (svr *Service) Run() {
if svr.rc.NatHoleController != nil {
go svr.rc.NatHoleController.Run()
}
- if svr.cfg.KCPBindPort > 0 {
+ if svr.kcpListener != nil {
go svr.HandleListener(svr.kcpListener)
}
+ if svr.quicListener != nil {
+ go svr.HandleQUICListener(svr.quicListener)
+ }
go svr.HandleListener(svr.websocketListener)
go svr.HandleListener(svr.tlsListener)
@@ -324,13 +351,13 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn) {
err error
)
- conn.SetReadDeadline(time.Now().Add(connReadTimeout))
+ _ = conn.SetReadDeadline(time.Now().Add(connReadTimeout))
if rawMsg, err = msg.ReadMsg(conn); err != nil {
log.Trace("Failed to read message: %v", err)
conn.Close()
return
}
- conn.SetReadDeadline(time.Time{})
+ _ = conn.SetReadDeadline(time.Time{})
switch m := rawMsg.(type) {
case *msg.Login:
@@ -349,7 +376,7 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn) {
// Otherwise send success message in control's work goroutine.
if err != nil {
xl.Warn("register control error: %v", err)
- msg.WriteMsg(conn, &msg.LoginResp{
+ _ = msg.WriteMsg(conn, &msg.LoginResp{
Version: version.Full(),
Error: util.GenerateResponseErrorString("register control error", err, svr.cfg.DetailedErrorsToClient),
})
@@ -362,13 +389,13 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn) {
case *msg.NewVisitorConn:
if err = svr.RegisterVisitorConn(conn, m); err != nil {
xl.Warn("register visitor conn error: %v", err)
- msg.WriteMsg(conn, &msg.NewVisitorConnResp{
+ _ = msg.WriteMsg(conn, &msg.NewVisitorConnResp{
ProxyName: m.ProxyName,
Error: util.GenerateResponseErrorString("register visitor conn error", err, svr.cfg.DetailedErrorsToClient),
})
conn.Close()
} else {
- msg.WriteMsg(conn, &msg.NewVisitorConnResp{
+ _ = msg.WriteMsg(conn, &msg.NewVisitorConnResp{
ProxyName: m.ProxyName,
Error: "",
})
@@ -433,6 +460,29 @@ func (svr *Service) HandleListener(l net.Listener) {
}
}
+func (svr *Service) HandleQUICListener(l quic.Listener) {
+ // Listen for incoming connections from client.
+ for {
+ c, err := l.Accept(context.Background())
+ if err != nil {
+ log.Warn("QUICListener for incoming connections from client closed")
+ return
+ }
+ // Start a new goroutine to handle connection.
+ go func(ctx context.Context, frpConn quic.Connection) {
+ for {
+ stream, err := frpConn.AcceptStream(context.Background())
+ if err != nil {
+ log.Debug("Accept new quic mux stream error: %v", err)
+ _ = frpConn.CloseWithError(0, "")
+ return
+ }
+ go svr.handleConnection(ctx, frpNet.QuicStreamToNetConn(stream, frpConn))
+ }
+ }(context.Background(), c)
+ }
+}
+
func (svr *Service) RegisterControl(ctlConn net.Conn, loginMsg *msg.Login) (err error) {
// If client's RunID is empty, it's a new client, we just create a new controller.
// Otherwise, we check if there is one controller has the same run id. If so, we release previous controller and start new one.
@@ -504,7 +554,7 @@ func (svr *Service) RegisterWorkConn(workConn net.Conn, newMsg *msg.NewWorkConn)
}
if err != nil {
xl.Warn("invalid NewWorkConn with run id [%s]", newMsg.RunID)
- msg.WriteMsg(workConn, &msg.StartWorkConn{
+ _ = msg.WriteMsg(workConn, &msg.StartWorkConn{
Error: util.GenerateResponseErrorString("invalid NewWorkConn", err, ctl.serverCfg.DetailedErrorsToClient),
})
return fmt.Errorf("invalid NewWorkConn with run id [%s]", newMsg.RunID)
diff --git a/server/visitor/visitor.go b/server/visitor/visitor.go
index 4796b416fbb..70f603b2de6 100644
--- a/server/visitor/visitor.go
+++ b/server/visitor/visitor.go
@@ -20,10 +20,10 @@ import (
"net"
"sync"
+ frpIo "github.com/fatedier/golib/io"
+
frpNet "github.com/fatedier/frp/pkg/util/net"
"github.com/fatedier/frp/pkg/util/util"
-
- frpIo "github.com/fatedier/golib/io"
)
// Manager for visitor listeners.
@@ -57,8 +57,8 @@ func (vm *Manager) Listen(name string, sk string) (l *frpNet.CustomListener, err
}
func (vm *Manager) NewConn(name string, conn net.Conn, timestamp int64, signKey string,
- useEncryption bool, useCompression bool) (err error) {
-
+ useEncryption bool, useCompression bool,
+) (err error) {
vm.mu.RLock()
defer vm.mu.RUnlock()
diff --git a/test/e2e/basic/basic.go b/test/e2e/basic/basic.go
index 13f17168477..1f1b20072f2 100644
--- a/test/e2e/basic/basic.go
+++ b/test/e2e/basic/basic.go
@@ -5,6 +5,8 @@ import (
"fmt"
"strings"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/pkg/transport"
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
@@ -12,18 +14,16 @@ import (
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
"github.com/fatedier/frp/test/e2e/pkg/port"
"github.com/fatedier/frp/test/e2e/pkg/request"
-
- . "github.com/onsi/ginkgo"
)
-var _ = Describe("[Feature: Basic]", func() {
+var _ = ginkgo.Describe("[Feature: Basic]", func() {
f := framework.NewDefaultFramework()
- Describe("TCP && UDP", func() {
+ ginkgo.Describe("TCP && UDP", func() {
types := []string{"tcp", "udp"}
for _, t := range types {
proxyType := t
- It(fmt.Sprintf("Expose a %s echo server", strings.ToUpper(proxyType)), func() {
+ ginkgo.It(fmt.Sprintf("Expose a %s echo server", strings.ToUpper(proxyType)), func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -93,8 +93,8 @@ var _ = Describe("[Feature: Basic]", func() {
}
})
- Describe("HTTP", func() {
- It("proxy to HTTP server", func() {
+ ginkgo.Describe("HTTP", func() {
+ ginkgo.It("proxy to HTTP server", func() {
serverConf := consts.DefaultServerConfig
vhostHTTPPort := f.AllocPort()
serverConf += fmt.Sprintf(`
@@ -175,8 +175,8 @@ var _ = Describe("[Feature: Basic]", func() {
})
})
- Describe("HTTPS", func() {
- It("proxy to HTTPS server", func() {
+ ginkgo.Describe("HTTPS", func() {
+ ginkgo.It("proxy to HTTPS server", func() {
serverConf := consts.DefaultServerConfig
vhostHTTPSPort := f.AllocPort()
serverConf += fmt.Sprintf(`
@@ -237,7 +237,7 @@ var _ = Describe("[Feature: Basic]", func() {
framework.ExpectNoError(err)
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
- httpserver.WithTlsConfig(tlsConfig),
+ httpserver.WithTLSConfig(tlsConfig),
httpserver.WithResponse([]byte("test")),
)
f.RunServer("", localServer)
@@ -275,11 +275,11 @@ var _ = Describe("[Feature: Basic]", func() {
})
})
- Describe("STCP && SUDP", func() {
+ ginkgo.Describe("STCP && SUDP", func() {
types := []string{"stcp", "sudp"}
for _, t := range types {
proxyType := t
- It(fmt.Sprintf("Expose echo server with %s", strings.ToUpper(proxyType)), func() {
+ ginkgo.It(fmt.Sprintf("Expose echo server with %s", strings.ToUpper(proxyType)), func() {
serverConf := consts.DefaultServerConfig
clientServerConf := consts.DefaultClientConfig
clientVisitorConf := consts.DefaultClientConfig
@@ -381,8 +381,8 @@ var _ = Describe("[Feature: Basic]", func() {
}
})
- Describe("TCPMUX", func() {
- It("Type tcpmux", func() {
+ ginkgo.Describe("TCPMUX", func() {
+ ginkgo.It("Type tcpmux", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
diff --git a/test/e2e/basic/client.go b/test/e2e/basic/client.go
index 8d370928c51..10489d494d3 100644
--- a/test/e2e/basic/client.go
+++ b/test/e2e/basic/client.go
@@ -6,18 +6,18 @@ import (
"strings"
"time"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/pkg/request"
clientsdk "github.com/fatedier/frp/test/e2e/pkg/sdk/client"
-
- . "github.com/onsi/ginkgo"
)
-var _ = Describe("[Feature: ClientManage]", func() {
+var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
f := framework.NewDefaultFramework()
- It("Update && Reload API", func() {
+ ginkgo.It("Update && Reload API", func() {
serverConf := consts.DefaultServerConfig
adminPort := f.AllocPort()
@@ -62,7 +62,9 @@ var _ = Describe("[Feature: ClientManage]", func() {
// change p2 port and remove p3 proxy
newClientConf := strings.ReplaceAll(conf, strconv.Itoa(p2Port), strconv.Itoa(newP2Port))
p3Index := strings.Index(newClientConf, "[p3]")
- newClientConf = newClientConf[:p3Index]
+ if p3Index >= 0 {
+ newClientConf = newClientConf[:p3Index]
+ }
err = client.UpdateConfig(newClientConf)
framework.ExpectNoError(err)
@@ -77,7 +79,7 @@ var _ = Describe("[Feature: ClientManage]", func() {
framework.NewRequestExpect(f).Port(p3Port).Explain("p3 port").ExpectError(true).Ensure()
})
- It("healthz", func() {
+ ginkgo.It("healthz", func() {
serverConf := consts.DefaultServerConfig
dashboardPort := f.AllocPort()
@@ -99,5 +101,4 @@ var _ = Describe("[Feature: ClientManage]", func() {
}).Port(dashboardPort).
Ensure(framework.ExpectResponseCode(401))
})
-
})
diff --git a/test/e2e/basic/client_server.go b/test/e2e/basic/client_server.go
index c19077c4825..32a6bbe13da 100644
--- a/test/e2e/basic/client_server.go
+++ b/test/e2e/basic/client_server.go
@@ -4,12 +4,12 @@ import (
"fmt"
"strings"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/pkg/cert"
"github.com/fatedier/frp/test/e2e/pkg/port"
-
- . "github.com/onsi/ginkgo"
)
type generalTestConfigures struct {
@@ -18,6 +18,15 @@ type generalTestConfigures struct {
expectError bool
}
+func renderBindPortConfig(protocol string) string {
+ if protocol == "kcp" {
+ return fmt.Sprintf(`kcp_bind_port = {{ .%s }}`, consts.PortServerName)
+ } else if protocol == "quic" {
+ return fmt.Sprintf(`quic_bind_port = {{ .%s }}`, consts.PortServerName)
+ }
+ return ""
+}
+
func runClientServerTest(f *framework.Framework, configures *generalTestConfigures) {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -54,29 +63,28 @@ func runClientServerTest(f *framework.Framework, configures *generalTestConfigur
// defineClientServerTest test a normal tcp and udp proxy with specified TestConfigures.
func defineClientServerTest(desc string, f *framework.Framework, configures *generalTestConfigures) {
- It(desc, func() {
+ ginkgo.It(desc, func() {
runClientServerTest(f, configures)
})
}
-var _ = Describe("[Feature: Client-Server]", func() {
+var _ = ginkgo.Describe("[Feature: Client-Server]", func() {
f := framework.NewDefaultFramework()
- Describe("Protocol", func() {
- supportProtocols := []string{"tcp", "kcp", "websocket"}
+ ginkgo.Describe("Protocol", func() {
+ supportProtocols := []string{"tcp", "kcp", "quic", "websocket"}
for _, protocol := range supportProtocols {
configures := &generalTestConfigures{
server: fmt.Sprintf(`
- kcp_bind_port = {{ .%s }}
- protocol = %s"
- `, consts.PortServerName, protocol),
+ %s
+ `, renderBindPortConfig(protocol)),
client: "protocol = " + protocol,
}
defineClientServerTest(protocol, f, configures)
}
})
- Describe("Authentication", func() {
+ ginkgo.Describe("Authentication", func() {
defineClientServerTest("Token Correct", f, &generalTestConfigures{
server: "token = 123456",
client: "token = 123456",
@@ -89,15 +97,14 @@ var _ = Describe("[Feature: Client-Server]", func() {
})
})
- Describe("TLS", func() {
- supportProtocols := []string{"tcp", "kcp", "websocket"}
+ ginkgo.Describe("TLS", func() {
+ supportProtocols := []string{"tcp", "kcp", "quic", "websocket"}
for _, protocol := range supportProtocols {
tmp := protocol
defineClientServerTest("TLS over "+strings.ToUpper(tmp), f, &generalTestConfigures{
server: fmt.Sprintf(`
- kcp_bind_port = {{ .%s }}
- protocol = %s
- `, consts.PortServerName, protocol),
+ %s
+ `, renderBindPortConfig(protocol)),
client: fmt.Sprintf(`tls_enable = true
protocol = %s
`, protocol),
@@ -114,24 +121,25 @@ var _ = Describe("[Feature: Client-Server]", func() {
})
})
- Describe("TLS with custom certificate", func() {
- supportProtocols := []string{"tcp", "kcp", "websocket"}
+ ginkgo.Describe("TLS with custom certificate", func() {
+ supportProtocols := []string{"tcp", "kcp", "quic", "websocket"}
var (
caCrtPath string
serverCrtPath, serverKeyPath string
clientCrtPath, clientKeyPath string
)
- JustBeforeEach(func() {
+ ginkgo.JustBeforeEach(func() {
generator := &cert.SelfSignedCertGenerator{}
- artifacts, err := generator.Generate("0.0.0.0")
+ artifacts, err := generator.Generate("127.0.0.1")
framework.ExpectNoError(err)
caCrtPath = f.WriteTempFile("ca.crt", string(artifacts.CACert))
serverCrtPath = f.WriteTempFile("server.crt", string(artifacts.Cert))
serverKeyPath = f.WriteTempFile("server.key", string(artifacts.Key))
generator.SetCA(artifacts.CACert, artifacts.CAKey)
- generator.Generate("0.0.0.0")
+ _, err = generator.Generate("127.0.0.1")
+ framework.ExpectNoError(err)
clientCrtPath = f.WriteTempFile("client.crt", string(artifacts.Cert))
clientKeyPath = f.WriteTempFile("client.key", string(artifacts.Key))
})
@@ -139,13 +147,12 @@ var _ = Describe("[Feature: Client-Server]", func() {
for _, protocol := range supportProtocols {
tmp := protocol
- It("one-way authentication: "+tmp, func() {
+ ginkgo.It("one-way authentication: "+tmp, func() {
runClientServerTest(f, &generalTestConfigures{
server: fmt.Sprintf(`
- protocol = %s
- kcp_bind_port = {{ .%s }}
+ %s
tls_trusted_ca_file = %s
- `, tmp, consts.PortServerName, caCrtPath),
+ `, renderBindPortConfig(tmp), caCrtPath),
client: fmt.Sprintf(`
protocol = %s
tls_enable = true
@@ -155,15 +162,14 @@ var _ = Describe("[Feature: Client-Server]", func() {
})
})
- It("mutual authentication: "+tmp, func() {
+ ginkgo.It("mutual authentication: "+tmp, func() {
runClientServerTest(f, &generalTestConfigures{
server: fmt.Sprintf(`
- protocol = %s
- kcp_bind_port = {{ .%s }}
+ %s
tls_cert_file = %s
tls_key_file = %s
tls_trusted_ca_file = %s
- `, tmp, consts.PortServerName, serverCrtPath, serverKeyPath, caCrtPath),
+ `, renderBindPortConfig(tmp), serverCrtPath, serverKeyPath, caCrtPath),
client: fmt.Sprintf(`
protocol = %s
tls_enable = true
@@ -176,13 +182,13 @@ var _ = Describe("[Feature: Client-Server]", func() {
}
})
- Describe("TLS with custom certificate and specified server name", func() {
+ ginkgo.Describe("TLS with custom certificate and specified server name", func() {
var (
caCrtPath string
serverCrtPath, serverKeyPath string
clientCrtPath, clientKeyPath string
)
- JustBeforeEach(func() {
+ ginkgo.JustBeforeEach(func() {
generator := &cert.SelfSignedCertGenerator{}
artifacts, err := generator.Generate("example.com")
framework.ExpectNoError(err)
@@ -191,12 +197,13 @@ var _ = Describe("[Feature: Client-Server]", func() {
serverCrtPath = f.WriteTempFile("server.crt", string(artifacts.Cert))
serverKeyPath = f.WriteTempFile("server.key", string(artifacts.Key))
generator.SetCA(artifacts.CACert, artifacts.CAKey)
- generator.Generate("example.com")
+ _, err = generator.Generate("example.com")
+ framework.ExpectNoError(err)
clientCrtPath = f.WriteTempFile("client.crt", string(artifacts.Cert))
clientKeyPath = f.WriteTempFile("client.key", string(artifacts.Key))
})
- It("mutual authentication", func() {
+ ginkgo.It("mutual authentication", func() {
runClientServerTest(f, &generalTestConfigures{
server: fmt.Sprintf(`
tls_cert_file = %s
@@ -213,7 +220,7 @@ var _ = Describe("[Feature: Client-Server]", func() {
})
})
- It("mutual authentication with incorrect server name", func() {
+ ginkgo.It("mutual authentication with incorrect server name", func() {
runClientServerTest(f, &generalTestConfigures{
server: fmt.Sprintf(`
tls_cert_file = %s
@@ -232,15 +239,14 @@ var _ = Describe("[Feature: Client-Server]", func() {
})
})
- Describe("TLS with disable_custom_tls_first_byte", func() {
- supportProtocols := []string{"tcp", "kcp", "websocket"}
+ ginkgo.Describe("TLS with disable_custom_tls_first_byte", func() {
+ supportProtocols := []string{"tcp", "kcp", "quic", "websocket"}
for _, protocol := range supportProtocols {
tmp := protocol
defineClientServerTest("TLS over "+strings.ToUpper(tmp), f, &generalTestConfigures{
server: fmt.Sprintf(`
- kcp_bind_port = {{ .%s }}
- protocol = %s
- `, consts.PortServerName, protocol),
+ %s
+ `, renderBindPortConfig(protocol)),
client: fmt.Sprintf(`
tls_enable = true
protocol = %s
@@ -250,16 +256,15 @@ var _ = Describe("[Feature: Client-Server]", func() {
}
})
- Describe("IPv6 bind address", func() {
- supportProtocols := []string{"tcp", "kcp", "websocket"}
+ ginkgo.Describe("IPv6 bind address", func() {
+ supportProtocols := []string{"tcp", "kcp", "quic", "websocket"}
for _, protocol := range supportProtocols {
tmp := protocol
defineClientServerTest("IPv6 bind address: "+strings.ToUpper(tmp), f, &generalTestConfigures{
server: fmt.Sprintf(`
bind_addr = ::
- kcp_bind_port = {{ .%s }}
- protocol = %s
- `, consts.PortServerName, protocol),
+ %s
+ `, renderBindPortConfig(protocol)),
client: fmt.Sprintf(`
tls_enable = true
protocol = %s
diff --git a/test/e2e/basic/cmd.go b/test/e2e/basic/cmd.go
index 562310fdf0e..bf8f2467cbe 100644
--- a/test/e2e/basic/cmd.go
+++ b/test/e2e/basic/cmd.go
@@ -5,21 +5,21 @@ import (
"strconv"
"strings"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/pkg/request"
-
- . "github.com/onsi/ginkgo"
)
const (
ConfigValidStr = "syntax is ok"
)
-var _ = Describe("[Feature: Cmd]", func() {
+var _ = ginkgo.Describe("[Feature: Cmd]", func() {
f := framework.NewDefaultFramework()
- Describe("Verify", func() {
- It("frps valid", func() {
+ ginkgo.Describe("Verify", func() {
+ ginkgo.It("frps valid", func() {
path := f.GenerateConfigFile(`
[common]
bind_addr = 0.0.0.0
@@ -29,7 +29,7 @@ var _ = Describe("[Feature: Cmd]", func() {
framework.ExpectNoError(err)
framework.ExpectTrue(strings.Contains(output, ConfigValidStr), "output: %s", output)
})
- It("frps invalid", func() {
+ ginkgo.It("frps invalid", func() {
path := f.GenerateConfigFile(`
[common]
bind_addr = 0.0.0.0
@@ -39,7 +39,7 @@ var _ = Describe("[Feature: Cmd]", func() {
framework.ExpectNoError(err)
framework.ExpectTrue(!strings.Contains(output, ConfigValidStr), "output: %s", output)
})
- It("frpc valid", func() {
+ ginkgo.It("frpc valid", func() {
path := f.GenerateConfigFile(`
[common]
server_addr = 0.0.0.0
@@ -49,7 +49,7 @@ var _ = Describe("[Feature: Cmd]", func() {
framework.ExpectNoError(err)
framework.ExpectTrue(strings.Contains(output, ConfigValidStr), "output: %s", output)
})
- It("frpc invalid", func() {
+ ginkgo.It("frpc invalid", func() {
path := f.GenerateConfigFile(`
[common]
server_addr = 0.0.0.0
@@ -62,8 +62,8 @@ var _ = Describe("[Feature: Cmd]", func() {
})
})
- Describe("Single proxy", func() {
- It("TCP", func() {
+ ginkgo.Describe("Single proxy", func() {
+ ginkgo.It("TCP", func() {
serverPort := f.AllocPort()
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort))
framework.ExpectNoError(err)
@@ -77,7 +77,7 @@ var _ = Describe("[Feature: Cmd]", func() {
framework.NewRequestExpect(f).Port(remotePort).Ensure()
})
- It("UDP", func() {
+ ginkgo.It("UDP", func() {
serverPort := f.AllocPort()
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort))
framework.ExpectNoError(err)
@@ -92,7 +92,7 @@ var _ = Describe("[Feature: Cmd]", func() {
Port(remotePort).Ensure()
})
- It("HTTP", func() {
+ ginkgo.It("HTTP", func() {
serverPort := f.AllocPort()
vhostHTTPPort := f.AllocPort()
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort), "--vhost_http_port", strconv.Itoa(vhostHTTPPort))
diff --git a/test/e2e/basic/config.go b/test/e2e/basic/config.go
index d21bc57c9e2..3ea07b306b1 100644
--- a/test/e2e/basic/config.go
+++ b/test/e2e/basic/config.go
@@ -3,18 +3,18 @@ package basic
import (
"fmt"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/pkg/port"
-
- . "github.com/onsi/ginkgo"
)
-var _ = Describe("[Feature: Config]", func() {
+var _ = ginkgo.Describe("[Feature: Config]", func() {
f := framework.NewDefaultFramework()
- Describe("Template", func() {
- It("render by env", func() {
+ ginkgo.Describe("Template", func() {
+ ginkgo.It("render by env", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -39,8 +39,8 @@ var _ = Describe("[Feature: Config]", func() {
})
})
- Describe("Includes", func() {
- It("split tcp proxies into different files", func() {
+ ginkgo.Describe("Includes", func() {
+ ginkgo.It("split tcp proxies into different files", func() {
serverPort := f.AllocPort()
serverConfigPath := f.GenerateConfigFile(fmt.Sprintf(`
[common]
diff --git a/test/e2e/basic/http.go b/test/e2e/basic/http.go
index 8fe73594958..0de24abb80e 100644
--- a/test/e2e/basic/http.go
+++ b/test/e2e/basic/http.go
@@ -6,16 +6,16 @@ import (
"net/url"
"strconv"
+ "github.com/gorilla/websocket"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/mock/server/httpserver"
"github.com/fatedier/frp/test/e2e/pkg/request"
-
- "github.com/gorilla/websocket"
- . "github.com/onsi/ginkgo"
)
-var _ = Describe("[Feature: HTTP]", func() {
+var _ = ginkgo.Describe("[Feature: HTTP]", func() {
f := framework.NewDefaultFramework()
getDefaultServerConf := func(vhostHTTPPort int) string {
@@ -31,7 +31,7 @@ var _ = Describe("[Feature: HTTP]", func() {
)
}
- It("HTTP route by locations", func() {
+ ginkgo.It("HTTP route by locations", func() {
vhostHTTPPort := f.AllocPort()
serverConf := getDefaultServerConf(vhostHTTPPort)
@@ -78,7 +78,7 @@ var _ = Describe("[Feature: HTTP]", func() {
}
})
- It("HTTP route by HTTP user", func() {
+ ginkgo.It("HTTP route by HTTP user", func() {
vhostHTTPPort := f.AllocPort()
serverConf := getDefaultServerConf(vhostHTTPPort)
@@ -138,7 +138,7 @@ var _ = Describe("[Feature: HTTP]", func() {
Ensure()
})
- It("HTTP Basic Auth", func() {
+ ginkgo.It("HTTP Basic Auth", func() {
vhostHTTPPort := f.AllocPort()
serverConf := getDefaultServerConf(vhostHTTPPort)
@@ -176,7 +176,7 @@ var _ = Describe("[Feature: HTTP]", func() {
Ensure()
})
- It("Wildcard domain", func() {
+ ginkgo.It("Wildcard domain", func() {
vhostHTTPPort := f.AllocPort()
serverConf := getDefaultServerConf(vhostHTTPPort)
@@ -212,7 +212,7 @@ var _ = Describe("[Feature: HTTP]", func() {
Ensure()
})
- It("Subdomain", func() {
+ ginkgo.It("Subdomain", func() {
vhostHTTPPort := f.AllocPort()
serverConf := getDefaultServerConf(vhostHTTPPort)
serverConf += `
@@ -257,7 +257,7 @@ var _ = Describe("[Feature: HTTP]", func() {
Ensure()
})
- It("Modify headers", func() {
+ ginkgo.It("Modify headers", func() {
vhostHTTPPort := f.AllocPort()
serverConf := getDefaultServerConf(vhostHTTPPort)
@@ -265,7 +265,7 @@ var _ = Describe("[Feature: HTTP]", func() {
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- w.Write([]byte(req.Header.Get("X-From-Where")))
+ _, _ = w.Write([]byte(req.Header.Get("X-From-Where")))
})),
)
f.RunServer("", localServer)
@@ -290,7 +290,7 @@ var _ = Describe("[Feature: HTTP]", func() {
Ensure()
})
- It("Host Header Rewrite", func() {
+ ginkgo.It("Host Header Rewrite", func() {
vhostHTTPPort := f.AllocPort()
serverConf := getDefaultServerConf(vhostHTTPPort)
@@ -298,7 +298,7 @@ var _ = Describe("[Feature: HTTP]", func() {
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- w.Write([]byte(req.Host))
+ _, _ = w.Write([]byte(req.Host))
})),
)
f.RunServer("", localServer)
@@ -322,7 +322,7 @@ var _ = Describe("[Feature: HTTP]", func() {
Ensure()
})
- It("Websocket protocol", func() {
+ ginkgo.It("Websocket protocol", func() {
vhostHTTPPort := f.AllocPort()
serverConf := getDefaultServerConf(vhostHTTPPort)
diff --git a/test/e2e/basic/server.go b/test/e2e/basic/server.go
index 74b421be5b1..a06f6d13d00 100644
--- a/test/e2e/basic/server.go
+++ b/test/e2e/basic/server.go
@@ -5,19 +5,19 @@ import (
"net"
"strconv"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/pkg/port"
"github.com/fatedier/frp/test/e2e/pkg/request"
clientsdk "github.com/fatedier/frp/test/e2e/pkg/sdk/client"
-
- . "github.com/onsi/ginkgo"
)
-var _ = Describe("[Feature: Server Manager]", func() {
+var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
f := framework.NewDefaultFramework()
- It("Ports Whitelist", func() {
+ ginkgo.It("Ports Whitelist", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -80,7 +80,7 @@ var _ = Describe("[Feature: Server Manager]", func() {
}).ExpectError(true).Ensure()
})
- It("Alloc Random Port", func() {
+ ginkgo.It("Alloc Random Port", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -124,7 +124,7 @@ var _ = Describe("[Feature: Server Manager]", func() {
framework.NewRequestExpect(f).Protocol("udp").Port(port).Ensure()
})
- It("Port Reuse", func() {
+ ginkgo.It("Port Reuse", func() {
serverConf := consts.DefaultServerConfig
// Use same port as PortServer
serverConf += fmt.Sprintf(`
@@ -145,7 +145,7 @@ var _ = Describe("[Feature: Server Manager]", func() {
}).PortName(consts.PortServerName).Ensure()
})
- It("healthz", func() {
+ ginkgo.It("healthz", func() {
serverConf := consts.DefaultServerConfig
dashboardPort := f.AllocPort()
diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go
index b392954bf09..6b0d3e01c7d 100644
--- a/test/e2e/e2e.go
+++ b/test/e2e/e2e.go
@@ -3,12 +3,12 @@ package e2e
import (
"testing"
- "github.com/fatedier/frp/pkg/util/log"
- "github.com/fatedier/frp/test/e2e/framework"
-
"github.com/onsi/ginkgo"
"github.com/onsi/ginkgo/config"
"github.com/onsi/gomega"
+
+ "github.com/fatedier/frp/pkg/util/log"
+ "github.com/fatedier/frp/test/e2e/framework"
)
var _ = ginkgo.SynchronizedBeforeSuite(func() []byte {
diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go
index 2dddb95234c..d1cc6396895 100644
--- a/test/e2e/e2e_test.go
+++ b/test/e2e/e2e_test.go
@@ -6,15 +6,14 @@ import (
"os"
"testing"
- "github.com/fatedier/frp/pkg/util/log"
- "github.com/fatedier/frp/test/e2e/framework"
+ _ "github.com/onsi/ginkgo"
+ "github.com/fatedier/frp/pkg/util/log"
// test source
_ "github.com/fatedier/frp/test/e2e/basic"
_ "github.com/fatedier/frp/test/e2e/features"
+ "github.com/fatedier/frp/test/e2e/framework"
_ "github.com/fatedier/frp/test/e2e/plugin"
-
- _ "github.com/onsi/ginkgo"
)
// handleFlags sets up all flags and parses the command line.
diff --git a/test/e2e/examples.go b/test/e2e/examples.go
index 6423aec1ede..26eca20b5a9 100644
--- a/test/e2e/examples.go
+++ b/test/e2e/examples.go
@@ -3,17 +3,17 @@ package e2e
import (
"fmt"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
-
- . "github.com/onsi/ginkgo"
)
-var _ = Describe("[Feature: Example]", func() {
+var _ = ginkgo.Describe("[Feature: Example]", func() {
f := framework.NewDefaultFramework()
- Describe("TCP", func() {
- It("Expose a TCP echo server", func() {
+ ginkgo.Describe("TCP", func() {
+ ginkgo.It("Expose a TCP echo server", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
diff --git a/test/e2e/features/bandwidth_limit.go b/test/e2e/features/bandwidth_limit.go
index f984fdb9fe3..a912b06a76e 100644
--- a/test/e2e/features/bandwidth_limit.go
+++ b/test/e2e/features/bandwidth_limit.go
@@ -5,18 +5,18 @@ import (
"strings"
"time"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
"github.com/fatedier/frp/test/e2e/pkg/request"
-
- . "github.com/onsi/ginkgo"
)
-var _ = Describe("[Feature: Bandwidth Limit]", func() {
+var _ = ginkgo.Describe("[Feature: Bandwidth Limit]", func() {
f := framework.NewDefaultFramework()
- It("Proxy Bandwidth Limit", func() {
+ ginkgo.It("Proxy Bandwidth Limit", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -40,7 +40,7 @@ var _ = Describe("[Feature: Bandwidth Limit]", func() {
framework.NewRequestExpect(f).Port(remotePort).RequestModify(func(r *request.Request) {
r.Body([]byte(content)).Timeout(30 * time.Second)
}).ExpectResp([]byte(content)).Ensure()
- duration := time.Now().Sub(start)
+ duration := time.Since(start)
framework.ExpectTrue(duration.Seconds() > 7, "100Kb with 10KB limit, want > 7 seconds, but got %d seconds", duration.Seconds())
})
diff --git a/test/e2e/features/chaos.go b/test/e2e/features/chaos.go
index 2049fc77965..bae6eb7de44 100644
--- a/test/e2e/features/chaos.go
+++ b/test/e2e/features/chaos.go
@@ -4,15 +4,15 @@ import (
"fmt"
"time"
- "github.com/fatedier/frp/test/e2e/framework"
+ "github.com/onsi/ginkgo"
- . "github.com/onsi/ginkgo"
+ "github.com/fatedier/frp/test/e2e/framework"
)
-var _ = Describe("[Feature: Chaos]", func() {
+var _ = ginkgo.Describe("[Feature: Chaos]", func() {
f := framework.NewDefaultFramework()
- It("reconnect after frps restart", func() {
+ ginkgo.It("reconnect after frps restart", func() {
serverPort := f.AllocPort()
serverConfigPath := f.GenerateConfigFile(fmt.Sprintf(`
[common]
@@ -41,7 +41,7 @@ var _ = Describe("[Feature: Chaos]", func() {
framework.NewRequestExpect(f).Port(remotePort).Ensure()
// 2. stop frps, expect request failed
- ps.Stop()
+ _ = ps.Stop()
time.Sleep(200 * time.Millisecond)
framework.NewRequestExpect(f).Port(remotePort).ExpectError(true).Ensure()
@@ -52,7 +52,7 @@ var _ = Describe("[Feature: Chaos]", func() {
framework.NewRequestExpect(f).Port(remotePort).Ensure()
// 4. stop frpc, expect request failed
- pc.Stop()
+ _ = pc.Stop()
time.Sleep(200 * time.Millisecond)
framework.NewRequestExpect(f).Port(remotePort).ExpectError(true).Ensure()
diff --git a/test/e2e/features/group.go b/test/e2e/features/group.go
index ea6b781fd89..f36e75b26b4 100644
--- a/test/e2e/features/group.go
+++ b/test/e2e/features/group.go
@@ -6,16 +6,16 @@ import (
"sync"
"time"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/mock/server/httpserver"
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
"github.com/fatedier/frp/test/e2e/pkg/request"
-
- . "github.com/onsi/ginkgo"
)
-var _ = Describe("[Feature: Group]", func() {
+var _ = ginkgo.Describe("[Feature: Group]", func() {
f := framework.NewDefaultFramework()
newHTTPServer := func(port int, respContent string) *httpserver.Server {
@@ -60,8 +60,8 @@ var _ = Describe("[Feature: Group]", func() {
return results
}
- Describe("Load Balancing", func() {
- It("TCP", func() {
+ ginkgo.Describe("Load Balancing", func() {
+ ginkgo.It("TCP", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -112,8 +112,8 @@ var _ = Describe("[Feature: Group]", func() {
})
})
- Describe("Health Check", func() {
- It("TCP", func() {
+ ginkgo.Describe("Health Check", func() {
+ ginkgo.It("TCP", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -178,7 +178,7 @@ var _ = Describe("[Feature: Group]", func() {
framework.ExpectContainElements(results, []string{"foo", "bar"})
})
- It("HTTP", func() {
+ ginkgo.It("HTTP", func() {
vhostPort := f.AllocPort()
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
vhost_http_port = %d
@@ -217,6 +217,29 @@ var _ = Describe("[Feature: Group]", func() {
f.RunProcesses([]string{serverConf}, []string{clientConf})
+ // send first HTTP request
+ var contents []string
+ framework.NewRequestExpect(f).Port(vhostPort).
+ RequestModify(func(r *request.Request) {
+ r.HTTP().HTTPHost("example.com")
+ }).
+ Ensure(func(resp *request.Response) bool {
+ contents = append(contents, string(resp.Content))
+ return true
+ })
+
+ // send second HTTP request, should be forwarded to another service
+ framework.NewRequestExpect(f).Port(vhostPort).
+ RequestModify(func(r *request.Request) {
+ r.HTTP().HTTPHost("example.com")
+ }).
+ Ensure(func(resp *request.Response) bool {
+ contents = append(contents, string(resp.Content))
+ return true
+ })
+
+ framework.ExpectContainElements(contents, []string{"foo", "bar"})
+
// check foo and bar is ok
results := doFooBarHTTPRequest(vhostPort, "example.com")
framework.ExpectContainElements(results, []string{"foo", "bar"})
diff --git a/test/e2e/features/heartbeat.go b/test/e2e/features/heartbeat.go
index b0732c37f00..3ffbd83466b 100644
--- a/test/e2e/features/heartbeat.go
+++ b/test/e2e/features/heartbeat.go
@@ -4,15 +4,15 @@ import (
"fmt"
"time"
- "github.com/fatedier/frp/test/e2e/framework"
+ "github.com/onsi/ginkgo"
- . "github.com/onsi/ginkgo"
+ "github.com/fatedier/frp/test/e2e/framework"
)
-var _ = Describe("[Feature: Heartbeat]", func() {
+var _ = ginkgo.Describe("[Feature: Heartbeat]", func() {
f := framework.NewDefaultFramework()
- It("disable application layer heartbeat", func() {
+ ginkgo.It("disable application layer heartbeat", func() {
serverPort := f.AllocPort()
serverConf := fmt.Sprintf(`
[common]
diff --git a/test/e2e/features/monitor.go b/test/e2e/features/monitor.go
index d8b656a87d0..bf074e66041 100644
--- a/test/e2e/features/monitor.go
+++ b/test/e2e/features/monitor.go
@@ -5,18 +5,18 @@ import (
"strings"
"time"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/pkg/util/log"
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/pkg/request"
-
- . "github.com/onsi/ginkgo"
)
-var _ = Describe("[Feature: Monitor]", func() {
+var _ = ginkgo.Describe("[Feature: Monitor]", func() {
f := framework.NewDefaultFramework()
- It("Prometheus metrics", func() {
+ ginkgo.It("Prometheus metrics", func() {
dashboardPort := f.AllocPort()
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
enable_prometheus = true
diff --git a/test/e2e/features/real_ip.go b/test/e2e/features/real_ip.go
index 424d4049eb1..3a2a7e40bfd 100644
--- a/test/e2e/features/real_ip.go
+++ b/test/e2e/features/real_ip.go
@@ -6,6 +6,9 @@ import (
"net"
"net/http"
+ "github.com/onsi/ginkgo"
+ pp "github.com/pires/go-proxyproto"
+
"github.com/fatedier/frp/pkg/util/log"
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
@@ -13,15 +16,12 @@ import (
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
"github.com/fatedier/frp/test/e2e/pkg/request"
"github.com/fatedier/frp/test/e2e/pkg/rpc"
-
- . "github.com/onsi/ginkgo"
- pp "github.com/pires/go-proxyproto"
)
-var _ = Describe("[Feature: Real IP]", func() {
+var _ = ginkgo.Describe("[Feature: Real IP]", func() {
f := framework.NewDefaultFramework()
- It("HTTP X-Forwarded-For", func() {
+ ginkgo.It("HTTP X-Forwarded-For", func() {
vhostHTTPPort := f.AllocPort()
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
vhost_http_port = %d
@@ -31,7 +31,7 @@ var _ = Describe("[Feature: Real IP]", func() {
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- w.Write([]byte(req.Header.Get("X-Forwarded-For")))
+ _, _ = w.Write([]byte(req.Header.Get("X-Forwarded-For")))
})),
)
f.RunServer("", localServer)
@@ -52,11 +52,10 @@ var _ = Describe("[Feature: Real IP]", func() {
}).
ExpectResp([]byte("127.0.0.1")).
Ensure()
-
})
- Describe("Proxy Protocol", func() {
- It("TCP", func() {
+ ginkgo.Describe("Proxy Protocol", func() {
+ ginkgo.It("TCP", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -77,7 +76,7 @@ var _ = Describe("[Feature: Real IP]", func() {
}
buf := []byte(ppHeader.SourceAddr.String())
- rpc.WriteBytes(c, buf)
+ _, _ = rpc.WriteBytes(c, buf)
}
}))
f.RunServer("", localServer)
@@ -106,7 +105,7 @@ var _ = Describe("[Feature: Real IP]", func() {
})
})
- It("HTTP", func() {
+ ginkgo.It("HTTP", func() {
vhostHTTPPort := f.AllocPort()
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
vhost_http_port = %d
diff --git a/test/e2e/framework/cleanup.go b/test/e2e/framework/cleanup.go
index d2d1c5a6ce3..15e1a9dd4b9 100644
--- a/test/e2e/framework/cleanup.go
+++ b/test/e2e/framework/cleanup.go
@@ -6,13 +6,16 @@ import (
// CleanupActionHandle is an integer pointer type for handling cleanup action
type CleanupActionHandle *int
+
type cleanupFuncHandle struct {
actionHandle CleanupActionHandle
actionHook func()
}
-var cleanupActionsLock sync.Mutex
-var cleanupHookList = []cleanupFuncHandle{}
+var (
+ cleanupActionsLock sync.Mutex
+ cleanupHookList = []cleanupFuncHandle{}
+)
// AddCleanupAction installs a function that will be called in the event of the
// whole test being terminated. This allows arbitrary pieces of the overall
diff --git a/test/e2e/framework/consts/consts.go b/test/e2e/framework/consts/consts.go
index d38e183daed..622eba924b0 100644
--- a/test/e2e/framework/consts/consts.go
+++ b/test/e2e/framework/consts/consts.go
@@ -25,6 +25,7 @@ var (
DefaultClientConfig = `
[common]
+ server_addr = 127.0.0.1
server_port = {{ .%s }}
log_level = trace
`
diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go
index 344f64c3ab9..c22c6af75f6 100644
--- a/test/e2e/framework/framework.go
+++ b/test/e2e/framework/framework.go
@@ -9,12 +9,12 @@ import (
"strings"
"text/template"
+ "github.com/onsi/ginkgo"
+ "github.com/onsi/ginkgo/config"
+
"github.com/fatedier/frp/test/e2e/mock/server"
"github.com/fatedier/frp/test/e2e/pkg/port"
"github.com/fatedier/frp/test/e2e/pkg/process"
-
- "github.com/onsi/ginkgo"
- "github.com/onsi/ginkgo/config"
)
type Options struct {
@@ -102,7 +102,8 @@ func (f *Framework) BeforeEach() {
for k, v := range params {
switch t := v.(type) {
case int:
- f.usedPorts[k] = int(t)
+ f.usedPorts[k] = t
+ default:
}
}
}
@@ -116,14 +117,14 @@ func (f *Framework) AfterEach() {
// stop processor
for _, p := range f.serverProcesses {
- p.Stop()
+ _ = p.Stop()
if TestContext.Debug {
fmt.Println(p.ErrorOutput())
fmt.Println(p.StdOutput())
}
}
for _, p := range f.clientProcesses {
- p.Stop()
+ _ = p.Stop()
if TestContext.Debug {
fmt.Println(p.ErrorOutput())
fmt.Println(p.StdOutput())
@@ -259,7 +260,7 @@ func (f *Framework) SetEnvs(envs []string) {
func (f *Framework) WriteTempFile(name string, content string) string {
filePath := filepath.Join(f.TempDirectory, name)
- err := os.WriteFile(filePath, []byte(content), 0766)
+ err := os.WriteFile(filePath, []byte(content), 0o766)
ExpectNoError(err)
return filePath
}
diff --git a/test/e2e/framework/log.go b/test/e2e/framework/log.go
index ff33f41dbe0..34ba2936b36 100644
--- a/test/e2e/framework/log.go
+++ b/test/e2e/framework/log.go
@@ -58,16 +58,17 @@ var codeFilterRE = regexp.MustCompile(`/github.com/onsi/ginkgo/`)
// From the remaining entries it automatically filters out useless ones like
// entries coming from Ginkgo.
//
-// This is a modified copy of PruneStack in https://github.com/onsi/ginkgo/blob/f90f37d87fa6b1dd9625e2b1e83c23ffae3de228/internal/codelocation/code_location.go#L25:
-// - simplified API and thus renamed (calls debug.Stack() instead of taking a parameter)
-// - source code filtering updated to be specific to Kubernetes
-// - optimized to use bytes and in-place slice filtering from
-// https://github.com/golang/go/wiki/SliceTricks#filter-in-place
+// This is a modified copy of PruneStack in
+// https://github.com/onsi/ginkgo/blob/f90f37d87fa6b1dd9625e2b1e83c23ffae3de228/internal/codelocation/code_location.go#L25:
+// - simplified API and thus renamed (calls debug.Stack() instead of taking a parameter)
+// - source code filtering updated to be specific to Kubernetes
+// - optimized to use bytes and in-place slice filtering from
+// https://github.com/golang/go/wiki/SliceTricks#filter-in-place
func PrunedStack(skip int) []byte {
fullStackTrace := debug.Stack()
stack := bytes.Split(fullStackTrace, []byte("\n"))
// Ensure that the even entries are the method names and the
- // the odd entries the source code information.
+ // odd entries the source code information.
if len(stack) > 0 && bytes.HasPrefix(stack[0], []byte("goroutine ")) {
// Ignore "goroutine 29 [running]:" line.
stack = stack[1:]
@@ -82,7 +83,7 @@ func PrunedStack(skip int) []byte {
n := 0
for i := 0; i < len(stack)/2; i++ {
// We filter out based on the source code file name.
- if !codeFilterRE.Match([]byte(stack[i*2+1])) {
+ if !codeFilterRE.Match(stack[i*2+1]) {
stack[n] = stack[i*2]
stack[n+1] = stack[i*2+1]
n += 2
diff --git a/test/e2e/framework/mockservers.go b/test/e2e/framework/mockservers.go
index af41ab90baf..32f7ac38b69 100644
--- a/test/e2e/framework/mockservers.go
+++ b/test/e2e/framework/mockservers.go
@@ -33,9 +33,11 @@ func NewMockServers(portAllocator *port.Allocator) *MockServers {
httpPort := portAllocator.Get()
s.tcpEchoServer = streamserver.New(streamserver.TCP, streamserver.WithBindPort(tcpPort))
s.udpEchoServer = streamserver.New(streamserver.UDP, streamserver.WithBindPort(udpPort))
- s.httpSimpleServer = httpserver.New(httpserver.WithBindPort(httpPort), httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- w.Write([]byte(consts.TestString))
- })))
+ s.httpSimpleServer = httpserver.New(httpserver.WithBindPort(httpPort),
+ httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ _, _ = w.Write([]byte(consts.TestString))
+ })),
+ )
udsIndex := portAllocator.Get()
udsAddr := fmt.Sprintf("%s/frp_echo_server_%d.sock", os.TempDir(), udsIndex)
diff --git a/test/e2e/framework/process.go b/test/e2e/framework/process.go
index 32ef2f8424c..7c328dd4725 100644
--- a/test/e2e/framework/process.go
+++ b/test/e2e/framework/process.go
@@ -14,12 +14,8 @@ import (
// The first template should always be frps.
func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []string) ([]*process.Process, []*process.Process) {
templates := make([]string, 0, len(serverTemplates)+len(clientTemplates))
- for _, t := range serverTemplates {
- templates = append(templates, t)
- }
- for _, t := range clientTemplates {
- templates = append(templates, t)
- }
+ templates = append(templates, serverTemplates...)
+ templates = append(templates, clientTemplates...)
outs, ports, err := f.RenderTemplates(templates)
ExpectNoError(err)
ExpectTrue(len(templates) > 0)
@@ -31,7 +27,7 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
currentServerProcesses := make([]*process.Process, 0, len(serverTemplates))
for i := range serverTemplates {
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-server-%d", i))
- err = os.WriteFile(path, []byte(outs[i]), 0666)
+ err = os.WriteFile(path, []byte(outs[i]), 0o666)
ExpectNoError(err)
flog.Trace("[%s] %s", path, outs[i])
@@ -48,7 +44,7 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
for i := range clientTemplates {
index := i + len(serverTemplates)
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-client-%d", i))
- err = os.WriteFile(path, []byte(outs[index]), 0666)
+ err = os.WriteFile(path, []byte(outs[index]), 0o666)
ExpectNoError(err)
flog.Trace("[%s] %s", path, outs[index])
@@ -60,7 +56,7 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
ExpectNoError(err)
time.Sleep(500 * time.Millisecond)
}
- time.Sleep(time.Second)
+ time.Sleep(2 * time.Second)
return currentServerProcesses, currentClientProcesses
}
@@ -91,7 +87,7 @@ func (f *Framework) RunFrpc(args ...string) (*process.Process, string, error) {
func (f *Framework) GenerateConfigFile(content string) string {
f.configFileIndex++
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-config-%d", f.configFileIndex))
- err := os.WriteFile(path, []byte(content), 0666)
+ err := os.WriteFile(path, []byte(content), 0o666)
ExpectNoError(err)
return path
}
diff --git a/test/e2e/framework/request.go b/test/e2e/framework/request.go
index 5dccd661e4c..6b75a2593ad 100644
--- a/test/e2e/framework/request.go
+++ b/test/e2e/framework/request.go
@@ -11,7 +11,7 @@ import (
func SpecifiedHTTPBodyHandler(body []byte) http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
- w.Write(body)
+ _, _ = w.Write(body)
}
}
diff --git a/test/e2e/framework/test_context.go b/test/e2e/framework/test_context.go
index 958c78f8d7b..42a66445dd9 100644
--- a/test/e2e/framework/test_context.go
+++ b/test/e2e/framework/test_context.go
@@ -24,7 +24,6 @@ var TestContext TestContextType
// The other Register*Flags methods below can be used to add more
// test-specific flags. However, those settings then get added
// regardless whether the test is actually in the test suite.
-//
func RegisterCommonFlags(flags *flag.FlagSet) {
// Turn on EmitSpecProgress to get spec progress (especially on interrupt)
config.GinkgoConfig.EmitSpecProgress = true
diff --git a/test/e2e/mock/server/httpserver/server.go b/test/e2e/mock/server/httpserver/server.go
index a811ac2700a..f9818a0db80 100644
--- a/test/e2e/mock/server/httpserver/server.go
+++ b/test/e2e/mock/server/httpserver/server.go
@@ -5,6 +5,7 @@ import (
"net"
"net/http"
"strconv"
+ "time"
)
type Server struct {
@@ -44,7 +45,7 @@ func WithBindPort(port int) Option {
}
}
-func WithTlsConfig(tlsConfig *tls.Config) Option {
+func WithTLSConfig(tlsConfig *tls.Config) Option {
return func(s *Server) *Server {
s.tlsConfig = tlsConfig
return s
@@ -61,7 +62,7 @@ func WithHandler(h http.Handler) Option {
func WithResponse(resp []byte) Option {
return func(s *Server) *Server {
s.handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write(resp)
+ _, _ = w.Write(resp)
})
return s
}
@@ -74,16 +75,21 @@ func (s *Server) Run() error {
addr := net.JoinHostPort(s.bindAddr, strconv.Itoa(s.bindPort))
hs := &http.Server{
- Addr: addr,
- Handler: s.handler,
- TLSConfig: s.tlsConfig,
+ Addr: addr,
+ Handler: s.handler,
+ TLSConfig: s.tlsConfig,
+ ReadHeaderTimeout: time.Minute,
}
s.hs = hs
if s.tlsConfig == nil {
- go hs.Serve(s.l)
+ go func() {
+ _ = hs.Serve(s.l)
+ }()
} else {
- go hs.ServeTLS(s.l, "", "")
+ go func() {
+ _ = hs.ServeTLS(s.l, "", "")
+ }()
}
return nil
}
diff --git a/test/e2e/mock/server/streamserver/server.go b/test/e2e/mock/server/streamserver/server.go
index 1dde353a9db..9e237d96fba 100644
--- a/test/e2e/mock/server/streamserver/server.go
+++ b/test/e2e/mock/server/streamserver/server.go
@@ -127,7 +127,7 @@ func (s *Server) handle(c net.Conn) {
if len(s.respContent) > 0 {
buf = s.respContent
}
- rpc.WriteBytes(c, buf)
+ _, _ = rpc.WriteBytes(c, buf)
}
}
diff --git a/test/e2e/pkg/cert/generator.go b/test/e2e/pkg/cert/generator.go
index 5c11b226d1e..fb22522bec0 100644
--- a/test/e2e/pkg/cert/generator.go
+++ b/test/e2e/pkg/cert/generator.go
@@ -22,8 +22,8 @@ type Artifacts struct {
ResourceVersion string
}
-// CertGenerator is an interface to provision the serving certificate.
-type CertGenerator interface {
+// Generator is an interface to provision the serving certificate.
+type Generator interface {
// Generate returns a Artifacts struct.
Generate(CommonName string) (*Artifacts, error)
// SetCA sets the PEM-encoded CA private key and CA cert for signing the generated serving cert.
diff --git a/test/e2e/pkg/cert/selfsigned.go b/test/e2e/pkg/cert/selfsigned.go
index 4f9ed57378a..82762d0990c 100644
--- a/test/e2e/pkg/cert/selfsigned.go
+++ b/test/e2e/pkg/cert/selfsigned.go
@@ -23,7 +23,7 @@ type SelfSignedCertGenerator struct {
caCert []byte
}
-var _ CertGenerator = &SelfSignedCertGenerator{}
+var _ Generator = &SelfSignedCertGenerator{}
// SetCA sets the PEM-encoded CA private key and CA cert for signing the generated serving cert.
func (cp *SelfSignedCertGenerator) SetCA(caKey, caCert []byte) {
diff --git a/test/e2e/pkg/port/util.go b/test/e2e/pkg/port/util.go
index 9cf1204f5e7..073bf3c7787 100644
--- a/test/e2e/pkg/port/util.go
+++ b/test/e2e/pkg/port/util.go
@@ -26,16 +26,17 @@ func unmarshalFromName(name string) (*nameBuilder, error) {
builder.name = arrs[1]
case 4:
builder.name = arrs[1]
- if fromPort, err := strconv.Atoi(arrs[2]); err != nil {
+ fromPort, err := strconv.Atoi(arrs[2])
+ if err != nil {
return nil, fmt.Errorf("error range port from")
- } else {
- builder.rangePortFrom = fromPort
}
- if toPort, err := strconv.Atoi(arrs[3]); err != nil {
+ builder.rangePortFrom = fromPort
+
+ toPort, err := strconv.Atoi(arrs[3])
+ if err != nil {
return nil, fmt.Errorf("error range port to")
- } else {
- builder.rangePortTo = toPort
}
+ builder.rangePortTo = toPort
default:
return nil, fmt.Errorf("error port name format")
}
diff --git a/test/e2e/pkg/request/request.go b/test/e2e/pkg/request/request.go
index cf6352f3828..96e714f9e26 100644
--- a/test/e2e/pkg/request/request.go
+++ b/test/e2e/pkg/request/request.go
@@ -12,9 +12,10 @@ import (
"strconv"
"time"
+ libdial "github.com/fatedier/golib/net/dial"
+
"github.com/fatedier/frp/test/e2e/pkg/rpc"
"github.com/fatedier/frp/test/e2e/pkg/utils"
- libdial "github.com/fatedier/golib/net/dial"
)
type Request struct {
@@ -181,7 +182,7 @@ func (r *Request) Do() (*Response, error) {
defer conn.Close()
if r.timeout > 0 {
- conn.SetDeadline(time.Now().Add(r.timeout))
+ _ = conn.SetDeadline(time.Now().Add(r.timeout))
}
buf, err := r.sendRequestByConn(conn, r.body)
if err != nil {
@@ -199,7 +200,6 @@ type Response struct {
func (r *Request) sendHTTPRequest(method, urlstr string, host string, headers map[string]string,
proxy string, body []byte, tlsConfig *tls.Config,
) (*Response, error) {
-
var inBody io.Reader
if len(body) != 0 {
inBody = bytes.NewReader(body)
@@ -240,6 +240,7 @@ func (r *Request) sendHTTPRequest(method, urlstr string, host string, headers ma
if err != nil {
return nil, err
}
+ defer resp.Body.Close()
ret := &Response{Code: resp.StatusCode, Header: resp.Header}
buf, err := io.ReadAll(resp.Body)
diff --git a/test/e2e/pkg/rpc/rpc.go b/test/e2e/pkg/rpc/rpc.go
index ee3aef56f22..d6026449d55 100644
--- a/test/e2e/pkg/rpc/rpc.go
+++ b/test/e2e/pkg/rpc/rpc.go
@@ -9,7 +9,10 @@ import (
func WriteBytes(w io.Writer, buf []byte) (int, error) {
out := bytes.NewBuffer(nil)
- binary.Write(out, binary.BigEndian, int64(len(buf)))
+ if err := binary.Write(out, binary.BigEndian, int64(len(buf))); err != nil {
+ return 0, err
+ }
+
out.Write(buf)
return w.Write(out.Bytes())
}
diff --git a/test/e2e/plugin/client.go b/test/e2e/plugin/client.go
index afbd0a2c7fd..081c88ff541 100644
--- a/test/e2e/plugin/client.go
+++ b/test/e2e/plugin/client.go
@@ -5,6 +5,8 @@ import (
"fmt"
"strconv"
+ "github.com/onsi/ginkgo"
+
"github.com/fatedier/frp/pkg/transport"
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
@@ -12,15 +14,13 @@ import (
"github.com/fatedier/frp/test/e2e/pkg/cert"
"github.com/fatedier/frp/test/e2e/pkg/port"
"github.com/fatedier/frp/test/e2e/pkg/request"
-
- . "github.com/onsi/ginkgo"
)
-var _ = Describe("[Feature: Client-Plugins]", func() {
+var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
f := framework.NewDefaultFramework()
- Describe("UnixDomainSocket", func() {
- It("Expose a unix domain socket echo server", func() {
+ ginkgo.Describe("UnixDomainSocket", func() {
+ ginkgo.It("Expose a unix domain socket echo server", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -76,7 +76,7 @@ var _ = Describe("[Feature: Client-Plugins]", func() {
})
})
- It("http_proxy", func() {
+ ginkgo.It("http_proxy", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -108,7 +108,7 @@ var _ = Describe("[Feature: Client-Plugins]", func() {
})
})
- It("socks5 proxy", func() {
+ ginkgo.It("socks5 proxy", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
@@ -135,7 +135,7 @@ var _ = Describe("[Feature: Client-Plugins]", func() {
}).Ensure()
})
- It("static_file", func() {
+ ginkgo.It("static_file", func() {
vhostPort := f.AllocPort()
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
vhost_http_port = %d
@@ -184,7 +184,7 @@ var _ = Describe("[Feature: Client-Plugins]", func() {
).ExpectResp([]byte("foo")).Ensure()
})
- It("http2https", func() {
+ ginkgo.It("http2https", func() {
serverConf := consts.DefaultServerConfig
vhostHTTPPort := f.AllocPort()
serverConf += fmt.Sprintf(`
@@ -206,7 +206,7 @@ var _ = Describe("[Feature: Client-Plugins]", func() {
framework.ExpectNoError(err)
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
- httpserver.WithTlsConfig(tlsConfig),
+ httpserver.WithTLSConfig(tlsConfig),
httpserver.WithResponse([]byte("test")),
)
f.RunServer("", localServer)
@@ -220,7 +220,7 @@ var _ = Describe("[Feature: Client-Plugins]", func() {
Ensure()
})
- It("https2http", func() {
+ ginkgo.It("https2http", func() {
generator := &cert.SelfSignedCertGenerator{}
artifacts, err := generator.Generate("example.com")
framework.ExpectNoError(err)
@@ -264,7 +264,7 @@ var _ = Describe("[Feature: Client-Plugins]", func() {
Ensure()
})
- It("https2https", func() {
+ ginkgo.It("https2https", func() {
generator := &cert.SelfSignedCertGenerator{}
artifacts, err := generator.Generate("example.com")
framework.ExpectNoError(err)
@@ -295,7 +295,7 @@ var _ = Describe("[Feature: Client-Plugins]", func() {
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
httpserver.WithResponse([]byte("test")),
- httpserver.WithTlsConfig(tlsConfig),
+ httpserver.WithTLSConfig(tlsConfig),
)
f.RunServer("", localServer)
diff --git a/test/e2e/plugin/server.go b/test/e2e/plugin/server.go
index 2af1eba8496..e4619573a7e 100644
--- a/test/e2e/plugin/server.go
+++ b/test/e2e/plugin/server.go
@@ -4,25 +4,25 @@ import (
"fmt"
"time"
+ "github.com/onsi/ginkgo"
+
plugin "github.com/fatedier/frp/pkg/plugin/server"
"github.com/fatedier/frp/pkg/transport"
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
-
- . "github.com/onsi/ginkgo"
)
-var _ = Describe("[Feature: Server-Plugins]", func() {
+var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
f := framework.NewDefaultFramework()
- Describe("Login", func() {
+ ginkgo.Describe("Login", func() {
newFunc := func() *plugin.Request {
var r plugin.Request
r.Content = &plugin.LoginContent{}
return &r
}
- It("Auth for custom meta token", func() {
+ ginkgo.It("Auth for custom meta token", func() {
localPort := f.AllocPort()
clientAddressGot := false
@@ -79,14 +79,14 @@ var _ = Describe("[Feature: Server-Plugins]", func() {
})
})
- Describe("NewProxy", func() {
+ ginkgo.Describe("NewProxy", func() {
newFunc := func() *plugin.Request {
var r plugin.Request
r.Content = &plugin.NewProxyContent{}
return &r
}
- It("Validate Info", func() {
+ ginkgo.It("Validate Info", func() {
localPort := f.AllocPort()
handler := func(req *plugin.Request) *plugin.Response {
var ret plugin.Response
@@ -123,7 +123,7 @@ var _ = Describe("[Feature: Server-Plugins]", func() {
framework.NewRequestExpect(f).Port(remotePort).Ensure()
})
- It("Mofify RemotePort", func() {
+ ginkgo.It("Mofify RemotePort", func() {
localPort := f.AllocPort()
remotePort := f.AllocPort()
handler := func(req *plugin.Request) *plugin.Response {
@@ -158,14 +158,14 @@ var _ = Describe("[Feature: Server-Plugins]", func() {
})
})
- Describe("CloseProxy", func() {
+ ginkgo.Describe("CloseProxy", func() {
newFunc := func() *plugin.Request {
var r plugin.Request
r.Content = &plugin.CloseProxyContent{}
return &r
}
- It("Validate Info", func() {
+ ginkgo.It("Validate Info", func() {
localPort := f.AllocPort()
var recordProxyName string
handler := func(req *plugin.Request) *plugin.Response {
@@ -199,7 +199,7 @@ var _ = Describe("[Feature: Server-Plugins]", func() {
framework.NewRequestExpect(f).Port(remotePort).Ensure()
for _, c := range clients {
- c.Stop()
+ _ = c.Stop()
}
time.Sleep(1 * time.Second)
@@ -208,14 +208,14 @@ var _ = Describe("[Feature: Server-Plugins]", func() {
})
})
- Describe("Ping", func() {
+ ginkgo.Describe("Ping", func() {
newFunc := func() *plugin.Request {
var r plugin.Request
r.Content = &plugin.PingContent{}
return &r
}
- It("Validate Info", func() {
+ ginkgo.It("Validate Info", func() {
localPort := f.AllocPort()
var record string
@@ -258,14 +258,14 @@ var _ = Describe("[Feature: Server-Plugins]", func() {
})
})
- Describe("NewWorkConn", func() {
+ ginkgo.Describe("NewWorkConn", func() {
newFunc := func() *plugin.Request {
var r plugin.Request
r.Content = &plugin.NewWorkConnContent{}
return &r
}
- It("Validate Info", func() {
+ ginkgo.It("Validate Info", func() {
localPort := f.AllocPort()
var record string
@@ -304,13 +304,13 @@ var _ = Describe("[Feature: Server-Plugins]", func() {
})
})
- Describe("NewUserConn", func() {
+ ginkgo.Describe("NewUserConn", func() {
newFunc := func() *plugin.Request {
var r plugin.Request
r.Content = &plugin.NewUserConnContent{}
return &r
}
- It("Validate Info", func() {
+ ginkgo.It("Validate Info", func() {
localPort := f.AllocPort()
var record string
@@ -349,13 +349,13 @@ var _ = Describe("[Feature: Server-Plugins]", func() {
})
})
- Describe("HTTPS Protocol", func() {
+ ginkgo.Describe("HTTPS Protocol", func() {
newFunc := func() *plugin.Request {
var r plugin.Request
r.Content = &plugin.NewUserConnContent{}
return &r
}
- It("Validate Login Info, disable tls verify", func() {
+ ginkgo.It("Validate Login Info, disable tls verify", func() {
localPort := f.AllocPort()
var record string
diff --git a/test/e2e/plugin/utils.go b/test/e2e/plugin/utils.go
index c0d7db3d3db..51de01d9383 100644
--- a/test/e2e/plugin/utils.go
+++ b/test/e2e/plugin/utils.go
@@ -11,14 +11,14 @@ import (
"github.com/fatedier/frp/test/e2e/mock/server/httpserver"
)
-type PluginHandler func(req *plugin.Request) *plugin.Response
+type Handler func(req *plugin.Request) *plugin.Response
type NewPluginRequest func() *plugin.Request
-func NewHTTPPluginServer(port int, newFunc NewPluginRequest, handler PluginHandler, tlsConfig *tls.Config) *httpserver.Server {
+func NewHTTPPluginServer(port int, newFunc NewPluginRequest, handler Handler, tlsConfig *tls.Config) *httpserver.Server {
return httpserver.New(
httpserver.WithBindPort(port),
- httpserver.WithTlsConfig(tlsConfig),
+ httpserver.WithTLSConfig(tlsConfig),
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
r := newFunc()
buf, err := io.ReadAll(req.Body)
@@ -35,7 +35,7 @@ func NewHTTPPluginServer(port int, newFunc NewPluginRequest, handler PluginHandl
resp := handler(r)
buf, _ = json.Marshal(resp)
log.Trace("plugin response: %s", string(buf))
- w.Write(buf)
+ _, _ = w.Write(buf)
})),
)
}