mirror of
https://github.com/fatedier/frp.git
synced 2024-12-22 17:04:48 +07:00
added a 30s timeout for frpc subcommands to avoid long delays (#4359)
This commit is contained in:
parent
e8045194cd
commit
ae73ec2fed
@ -9,11 +9,6 @@
|
|||||||
|
|
||||||
<h3 align="center">Gold Sponsors</h3>
|
<h3 align="center">Gold Sponsors</h3>
|
||||||
<!--gold sponsors start-->
|
<!--gold sponsors start-->
|
||||||
<p align="center">
|
|
||||||
<a href="https://lokal.so/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
|
|
||||||
<img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_lokal.png">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
|
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
|
||||||
<img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
|
<img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
|
||||||
|
@ -11,11 +11,6 @@ frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP
|
|||||||
|
|
||||||
<h3 align="center">Gold Sponsors</h3>
|
<h3 align="center">Gold Sponsors</h3>
|
||||||
<!--gold sponsors start-->
|
<!--gold sponsors start-->
|
||||||
<p align="center">
|
|
||||||
<a href="https://lokal.so/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
|
|
||||||
<img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_lokal.png">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
|
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
|
||||||
<img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
|
<img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
### Features
|
### Features
|
||||||
|
|
||||||
* Added a new plugin `tls2raw`: Enables TLS termination and forwarding of decrypted raw traffic to local service.
|
* Added a new plugin `tls2raw`: Enables TLS termination and forwarding of decrypted raw traffic to local service.
|
||||||
|
* Added a default timeout of 30 seconds for the frpc subcommands to prevent commands from being stuck for a long time due to network issues.
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
* Fixed the issue that when `loginFailExit = false`, the frpc stop command cannot be stopped correctly if the server is not successfully connected after startup.
|
* Fixed the issue that when `loginFailExit = false`, the frpc stop command cannot be stopped correctly if the server is not successfully connected after startup.
|
||||||
|
@ -15,9 +15,11 @@
|
|||||||
package sub
|
package sub
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/rodaine/table"
|
"github.com/rodaine/table"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -27,24 +29,24 @@ import (
|
|||||||
clientsdk "github.com/fatedier/frp/pkg/sdk/client"
|
clientsdk "github.com/fatedier/frp/pkg/sdk/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var adminAPITimeout = 30 * time.Second
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(NewAdminCommand(
|
commands := []struct {
|
||||||
"reload",
|
name string
|
||||||
"Hot-Reload frpc configuration",
|
description string
|
||||||
ReloadHandler,
|
handler func(*v1.ClientCommonConfig) error
|
||||||
))
|
}{
|
||||||
|
{"reload", "Hot-Reload frpc configuration", ReloadHandler},
|
||||||
|
{"status", "Overview of all proxies status", StatusHandler},
|
||||||
|
{"stop", "Stop the running frpc", StopHandler},
|
||||||
|
}
|
||||||
|
|
||||||
rootCmd.AddCommand(NewAdminCommand(
|
for _, cmdConfig := range commands {
|
||||||
"status",
|
cmd := NewAdminCommand(cmdConfig.name, cmdConfig.description, cmdConfig.handler)
|
||||||
"Overview of all proxies status",
|
cmd.Flags().DurationVar(&adminAPITimeout, "api-timeout", adminAPITimeout, "Timeout for admin API calls")
|
||||||
StatusHandler,
|
rootCmd.AddCommand(cmd)
|
||||||
))
|
}
|
||||||
|
|
||||||
rootCmd.AddCommand(NewAdminCommand(
|
|
||||||
"stop",
|
|
||||||
"Stop the running frpc",
|
|
||||||
StopHandler,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAdminCommand(name, short string, handler func(*v1.ClientCommonConfig) error) *cobra.Command {
|
func NewAdminCommand(name, short string, handler func(*v1.ClientCommonConfig) error) *cobra.Command {
|
||||||
@ -73,7 +75,9 @@ func NewAdminCommand(name, short string, handler func(*v1.ClientCommonConfig) er
|
|||||||
func ReloadHandler(clientCfg *v1.ClientCommonConfig) error {
|
func ReloadHandler(clientCfg *v1.ClientCommonConfig) error {
|
||||||
client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port)
|
client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port)
|
||||||
client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password)
|
client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password)
|
||||||
if err := client.Reload(strictConfigMode); err != nil {
|
ctx, cancel := context.WithTimeout(context.Background(), adminAPITimeout)
|
||||||
|
defer cancel()
|
||||||
|
if err := client.Reload(ctx, strictConfigMode); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("reload success")
|
fmt.Println("reload success")
|
||||||
@ -83,7 +87,9 @@ func ReloadHandler(clientCfg *v1.ClientCommonConfig) error {
|
|||||||
func StatusHandler(clientCfg *v1.ClientCommonConfig) error {
|
func StatusHandler(clientCfg *v1.ClientCommonConfig) error {
|
||||||
client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port)
|
client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port)
|
||||||
client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password)
|
client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password)
|
||||||
res, err := client.GetAllProxyStatus()
|
ctx, cancel := context.WithTimeout(context.Background(), adminAPITimeout)
|
||||||
|
defer cancel()
|
||||||
|
res, err := client.GetAllProxyStatus(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -109,7 +115,9 @@ func StatusHandler(clientCfg *v1.ClientCommonConfig) error {
|
|||||||
func StopHandler(clientCfg *v1.ClientCommonConfig) error {
|
func StopHandler(clientCfg *v1.ClientCommonConfig) error {
|
||||||
client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port)
|
client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port)
|
||||||
client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password)
|
client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password)
|
||||||
if err := client.Stop(); err != nil {
|
ctx, cancel := context.WithTimeout(context.Background(), adminAPITimeout)
|
||||||
|
defer cancel()
|
||||||
|
if err := client.Stop(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("stop success")
|
fmt.Println("stop success")
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -31,8 +32,8 @@ func (c *Client) SetAuth(user, pwd string) {
|
|||||||
c.authPwd = pwd
|
c.authPwd = pwd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetProxyStatus(name string) (*client.ProxyStatusResp, error) {
|
func (c *Client) GetProxyStatus(ctx context.Context, name string) (*client.ProxyStatusResp, error) {
|
||||||
req, err := http.NewRequest("GET", "http://"+c.address+"/api/status", nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/status", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -54,8 +55,8 @@ func (c *Client) GetProxyStatus(name string) (*client.ProxyStatusResp, error) {
|
|||||||
return nil, fmt.Errorf("no proxy status found")
|
return nil, fmt.Errorf("no proxy status found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetAllProxyStatus() (client.StatusResp, error) {
|
func (c *Client) GetAllProxyStatus(ctx context.Context) (client.StatusResp, error) {
|
||||||
req, err := http.NewRequest("GET", "http://"+c.address+"/api/status", nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/status", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -70,7 +71,7 @@ func (c *Client) GetAllProxyStatus() (client.StatusResp, error) {
|
|||||||
return allStatus, nil
|
return allStatus, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Reload(strictMode bool) error {
|
func (c *Client) Reload(ctx context.Context, strictMode bool) error {
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
if strictMode {
|
if strictMode {
|
||||||
v.Set("strictConfig", "true")
|
v.Set("strictConfig", "true")
|
||||||
@ -79,7 +80,7 @@ func (c *Client) Reload(strictMode bool) error {
|
|||||||
if len(v) > 0 {
|
if len(v) > 0 {
|
||||||
queryStr = "?" + v.Encode()
|
queryStr = "?" + v.Encode()
|
||||||
}
|
}
|
||||||
req, err := http.NewRequest("GET", "http://"+c.address+"/api/reload"+queryStr, nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/reload"+queryStr, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -87,8 +88,8 @@ func (c *Client) Reload(strictMode bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Stop() error {
|
func (c *Client) Stop(ctx context.Context) error {
|
||||||
req, err := http.NewRequest("POST", "http://"+c.address+"/api/stop", nil)
|
req, err := http.NewRequestWithContext(ctx, "POST", "http://"+c.address+"/api/stop", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -96,16 +97,16 @@ func (c *Client) Stop() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetConfig() (string, error) {
|
func (c *Client) GetConfig(ctx context.Context) (string, error) {
|
||||||
req, err := http.NewRequest("GET", "http://"+c.address+"/api/config", nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/config", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return c.do(req)
|
return c.do(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) UpdateConfig(content string) error {
|
func (c *Client) UpdateConfig(ctx context.Context, content string) error {
|
||||||
req, err := http.NewRequest("PUT", "http://"+c.address+"/api/config", strings.NewReader(content))
|
req, err := http.NewRequestWithContext(ctx, "PUT", "http://"+c.address+"/api/config", strings.NewReader(content))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
package version
|
package version
|
||||||
|
|
||||||
var version = "0.59.0"
|
var version = "0.60.0"
|
||||||
|
|
||||||
func Full() string {
|
func Full() string {
|
||||||
return version
|
return version
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package basic
|
package basic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -54,7 +55,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
|||||||
framework.NewRequestExpect(f).Port(p3Port).Ensure()
|
framework.NewRequestExpect(f).Port(p3Port).Ensure()
|
||||||
|
|
||||||
client := f.APIClientForFrpc(adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
conf, err := client.GetConfig()
|
conf, err := client.GetConfig(context.Background())
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
newP2Port := f.AllocPort()
|
newP2Port := f.AllocPort()
|
||||||
@ -65,10 +66,10 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
|||||||
newClientConf = newClientConf[:p3Index]
|
newClientConf = newClientConf[:p3Index]
|
||||||
}
|
}
|
||||||
|
|
||||||
err = client.UpdateConfig(newClientConf)
|
err = client.UpdateConfig(context.Background(), newClientConf)
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
err = client.Reload(true)
|
err = client.Reload(context.Background(), true)
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
@ -120,7 +121,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
|||||||
framework.NewRequestExpect(f).Port(testPort).Ensure()
|
framework.NewRequestExpect(f).Port(testPort).Ensure()
|
||||||
|
|
||||||
client := f.APIClientForFrpc(adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
err := client.Stop()
|
err := client.Stop(context.Background())
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package basic
|
package basic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -101,7 +102,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
client := f.APIClientForFrpc(adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
|
|
||||||
// tcp random port
|
// tcp random port
|
||||||
status, err := client.GetProxyStatus("tcp")
|
status, err := client.GetProxyStatus(context.Background(), "tcp")
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
_, portStr, err := net.SplitHostPort(status.RemoteAddr)
|
_, portStr, err := net.SplitHostPort(status.RemoteAddr)
|
||||||
@ -112,7 +113,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
framework.NewRequestExpect(f).Port(port).Ensure()
|
framework.NewRequestExpect(f).Port(port).Ensure()
|
||||||
|
|
||||||
// udp random port
|
// udp random port
|
||||||
status, err = client.GetProxyStatus("udp")
|
status, err = client.GetProxyStatus(context.Background(), "udp")
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
_, portStr, err = net.SplitHostPort(status.RemoteAddr)
|
_, portStr, err = net.SplitHostPort(status.RemoteAddr)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package basic
|
package basic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -57,7 +58,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
|||||||
framework.NewRequestExpect(f).Port(p3Port).Ensure()
|
framework.NewRequestExpect(f).Port(p3Port).Ensure()
|
||||||
|
|
||||||
client := f.APIClientForFrpc(adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
conf, err := client.GetConfig()
|
conf, err := client.GetConfig(context.Background())
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
newP2Port := f.AllocPort()
|
newP2Port := f.AllocPort()
|
||||||
@ -68,10 +69,10 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
|||||||
newClientConf = newClientConf[:p3Index]
|
newClientConf = newClientConf[:p3Index]
|
||||||
}
|
}
|
||||||
|
|
||||||
err = client.UpdateConfig(newClientConf)
|
err = client.UpdateConfig(context.Background(), newClientConf)
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
err = client.Reload(true)
|
err = client.Reload(context.Background(), true)
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
@ -124,7 +125,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
|||||||
framework.NewRequestExpect(f).Port(testPort).Ensure()
|
framework.NewRequestExpect(f).Port(testPort).Ensure()
|
||||||
|
|
||||||
client := f.APIClientForFrpc(adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
err := client.Stop()
|
err := client.Stop(context.Background())
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package basic
|
package basic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/onsi/ginkgo/v2"
|
"github.com/onsi/ginkgo/v2"
|
||||||
@ -72,7 +73,7 @@ var _ = ginkgo.Describe("[Feature: Config]", func() {
|
|||||||
|
|
||||||
client := f.APIClientForFrpc(adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
checkProxyFn := func(name string, localPort, remotePort int) {
|
checkProxyFn := func(name string, localPort, remotePort int) {
|
||||||
status, err := client.GetProxyStatus(name)
|
status, err := client.GetProxyStatus(context.Background(), name)
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
framework.ExpectContainSubstring(status.LocalAddr, fmt.Sprintf(":%d", localPort))
|
framework.ExpectContainSubstring(status.LocalAddr, fmt.Sprintf(":%d", localPort))
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package basic
|
package basic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -112,7 +113,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
client := f.APIClientForFrpc(adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
|
|
||||||
// tcp random port
|
// tcp random port
|
||||||
status, err := client.GetProxyStatus("tcp")
|
status, err := client.GetProxyStatus(context.Background(), "tcp")
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
_, portStr, err := net.SplitHostPort(status.RemoteAddr)
|
_, portStr, err := net.SplitHostPort(status.RemoteAddr)
|
||||||
@ -123,7 +124,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
framework.NewRequestExpect(f).Port(port).Ensure()
|
framework.NewRequestExpect(f).Port(port).Ensure()
|
||||||
|
|
||||||
// udp random port
|
// udp random port
|
||||||
status, err = client.GetProxyStatus("udp")
|
status, err = client.GetProxyStatus(context.Background(), "udp")
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
_, portStr, err = net.SplitHostPort(status.RemoteAddr)
|
_, portStr, err = net.SplitHostPort(status.RemoteAddr)
|
||||||
|
Loading…
Reference in New Issue
Block a user