client.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package client
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "net"
  8. "net/http"
  9. "net/url"
  10. "strconv"
  11. "strings"
  12. "github.com/fatedier/frp/client"
  13. httppkg "github.com/fatedier/frp/pkg/util/http"
  14. )
  15. type Client struct {
  16. address string
  17. authUser string
  18. authPwd string
  19. }
  20. func New(host string, port int) *Client {
  21. return &Client{
  22. address: net.JoinHostPort(host, strconv.Itoa(port)),
  23. }
  24. }
  25. func (c *Client) SetAuth(user, pwd string) {
  26. c.authUser = user
  27. c.authPwd = pwd
  28. }
  29. func (c *Client) GetProxyStatus(ctx context.Context, name string) (*client.ProxyStatusResp, error) {
  30. req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/status", nil)
  31. if err != nil {
  32. return nil, err
  33. }
  34. content, err := c.do(req)
  35. if err != nil {
  36. return nil, err
  37. }
  38. allStatus := make(client.StatusResp)
  39. if err = json.Unmarshal([]byte(content), &allStatus); err != nil {
  40. return nil, fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(content))
  41. }
  42. for _, pss := range allStatus {
  43. for _, ps := range pss {
  44. if ps.Name == name {
  45. return &ps, nil
  46. }
  47. }
  48. }
  49. return nil, fmt.Errorf("no proxy status found")
  50. }
  51. func (c *Client) GetAllProxyStatus(ctx context.Context) (client.StatusResp, error) {
  52. req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/status", nil)
  53. if err != nil {
  54. return nil, err
  55. }
  56. content, err := c.do(req)
  57. if err != nil {
  58. return nil, err
  59. }
  60. allStatus := make(client.StatusResp)
  61. if err = json.Unmarshal([]byte(content), &allStatus); err != nil {
  62. return nil, fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(content))
  63. }
  64. return allStatus, nil
  65. }
  66. func (c *Client) Reload(ctx context.Context, strictMode bool) error {
  67. v := url.Values{}
  68. if strictMode {
  69. v.Set("strictConfig", "true")
  70. }
  71. queryStr := ""
  72. if len(v) > 0 {
  73. queryStr = "?" + v.Encode()
  74. }
  75. req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/reload"+queryStr, nil)
  76. if err != nil {
  77. return err
  78. }
  79. _, err = c.do(req)
  80. return err
  81. }
  82. func (c *Client) Stop(ctx context.Context) error {
  83. req, err := http.NewRequestWithContext(ctx, "POST", "http://"+c.address+"/api/stop", nil)
  84. if err != nil {
  85. return err
  86. }
  87. _, err = c.do(req)
  88. return err
  89. }
  90. func (c *Client) GetConfig(ctx context.Context) (string, error) {
  91. req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/config", nil)
  92. if err != nil {
  93. return "", err
  94. }
  95. return c.do(req)
  96. }
  97. func (c *Client) UpdateConfig(ctx context.Context, content string) error {
  98. req, err := http.NewRequestWithContext(ctx, "PUT", "http://"+c.address+"/api/config", strings.NewReader(content))
  99. if err != nil {
  100. return err
  101. }
  102. _, err = c.do(req)
  103. return err
  104. }
  105. func (c *Client) setAuthHeader(req *http.Request) {
  106. if c.authUser != "" || c.authPwd != "" {
  107. req.Header.Set("Authorization", httppkg.BasicAuth(c.authUser, c.authPwd))
  108. }
  109. }
  110. func (c *Client) do(req *http.Request) (string, error) {
  111. c.setAuthHeader(req)
  112. resp, err := http.DefaultClient.Do(req)
  113. if err != nil {
  114. return "", err
  115. }
  116. defer resp.Body.Close()
  117. if resp.StatusCode != 200 {
  118. return "", fmt.Errorf("api status code [%d]", resp.StatusCode)
  119. }
  120. buf, err := io.ReadAll(resp.Body)
  121. if err != nil {
  122. return "", err
  123. }
  124. return string(buf), nil
  125. }