admin_api.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright 2017 fatedier, fatedier@gmail.com
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package client
  15. import (
  16. "encoding/json"
  17. "fmt"
  18. "net/http"
  19. "sort"
  20. "strings"
  21. "github.com/julienschmidt/httprouter"
  22. ini "github.com/vaughan0/go-ini"
  23. "github.com/fatedier/frp/models/config"
  24. "github.com/fatedier/frp/utils/log"
  25. )
  26. type GeneralResponse struct {
  27. Code int64 `json:"code"`
  28. Msg string `json:"msg"`
  29. }
  30. // api/reload
  31. type ReloadResp struct {
  32. GeneralResponse
  33. }
  34. func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
  35. var (
  36. buf []byte
  37. res ReloadResp
  38. )
  39. defer func() {
  40. log.Info("Http response [/api/reload]: code [%d]", res.Code)
  41. buf, _ = json.Marshal(&res)
  42. w.Write(buf)
  43. }()
  44. log.Info("Http request: [/api/reload]")
  45. conf, err := ini.LoadFile(config.ClientCommonCfg.ConfigFile)
  46. if err != nil {
  47. res.Code = 1
  48. res.Msg = err.Error()
  49. log.Error("reload frpc config file error: %v", err)
  50. return
  51. }
  52. newCommonCfg, err := config.LoadClientCommonConf(conf)
  53. if err != nil {
  54. res.Code = 2
  55. res.Msg = err.Error()
  56. log.Error("reload frpc common section error: %v", err)
  57. return
  58. }
  59. pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromFile(config.ClientCommonCfg.User, conf, newCommonCfg.Start)
  60. if err != nil {
  61. res.Code = 3
  62. res.Msg = err.Error()
  63. log.Error("reload frpc proxy config error: %v", err)
  64. return
  65. }
  66. err = svr.ctl.reloadConf(pxyCfgs, visitorCfgs)
  67. if err != nil {
  68. res.Code = 4
  69. res.Msg = err.Error()
  70. log.Error("reload frpc proxy config error: %v", err)
  71. return
  72. }
  73. log.Info("success reload conf")
  74. return
  75. }
  76. type StatusResp struct {
  77. Tcp []ProxyStatusResp `json:"tcp"`
  78. Udp []ProxyStatusResp `json:"udp"`
  79. Http []ProxyStatusResp `json:"http"`
  80. Https []ProxyStatusResp `json:"https"`
  81. Stcp []ProxyStatusResp `json:"stcp"`
  82. Xtcp []ProxyStatusResp `json:"xtcp"`
  83. }
  84. type ProxyStatusResp struct {
  85. Name string `json:"name"`
  86. Type string `json:"type"`
  87. Status string `json:"status"`
  88. Err string `json:"err"`
  89. LocalAddr string `json:"local_addr"`
  90. Plugin string `json:"plugin"`
  91. RemoteAddr string `json:"remote_addr"`
  92. }
  93. type ByProxyStatusResp []ProxyStatusResp
  94. func (a ByProxyStatusResp) Len() int { return len(a) }
  95. func (a ByProxyStatusResp) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  96. func (a ByProxyStatusResp) Less(i, j int) bool { return strings.Compare(a[i].Name, a[j].Name) < 0 }
  97. func NewProxyStatusResp(status *ProxyStatus) ProxyStatusResp {
  98. psr := ProxyStatusResp{
  99. Name: status.Name,
  100. Type: status.Type,
  101. Status: status.Status,
  102. Err: status.Err,
  103. }
  104. switch cfg := status.Cfg.(type) {
  105. case *config.TcpProxyConf:
  106. if cfg.LocalPort != 0 {
  107. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  108. }
  109. psr.Plugin = cfg.Plugin
  110. psr.RemoteAddr = fmt.Sprintf(":%d", cfg.RemotePort)
  111. case *config.UdpProxyConf:
  112. if cfg.LocalPort != 0 {
  113. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  114. }
  115. psr.RemoteAddr = fmt.Sprintf(":%d", cfg.RemotePort)
  116. case *config.HttpProxyConf:
  117. if cfg.LocalPort != 0 {
  118. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  119. }
  120. psr.Plugin = cfg.Plugin
  121. case *config.HttpsProxyConf:
  122. if cfg.LocalPort != 0 {
  123. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  124. }
  125. psr.Plugin = cfg.Plugin
  126. case *config.StcpProxyConf:
  127. if cfg.LocalPort != 0 {
  128. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  129. }
  130. psr.Plugin = cfg.Plugin
  131. case *config.XtcpProxyConf:
  132. if cfg.LocalPort != 0 {
  133. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  134. }
  135. psr.Plugin = cfg.Plugin
  136. }
  137. return psr
  138. }
  139. // api/status
  140. func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
  141. var (
  142. buf []byte
  143. res StatusResp
  144. )
  145. res.Tcp = make([]ProxyStatusResp, 0)
  146. res.Udp = make([]ProxyStatusResp, 0)
  147. res.Http = make([]ProxyStatusResp, 0)
  148. res.Https = make([]ProxyStatusResp, 0)
  149. res.Stcp = make([]ProxyStatusResp, 0)
  150. res.Xtcp = make([]ProxyStatusResp, 0)
  151. defer func() {
  152. log.Info("Http response [/api/status]")
  153. buf, _ = json.Marshal(&res)
  154. w.Write(buf)
  155. }()
  156. log.Info("Http request: [/api/status]")
  157. ps := svr.ctl.pm.GetAllProxyStatus()
  158. for _, status := range ps {
  159. switch status.Type {
  160. case "tcp":
  161. res.Tcp = append(res.Tcp, NewProxyStatusResp(status))
  162. case "udp":
  163. res.Udp = append(res.Udp, NewProxyStatusResp(status))
  164. case "http":
  165. res.Http = append(res.Http, NewProxyStatusResp(status))
  166. case "https":
  167. res.Https = append(res.Https, NewProxyStatusResp(status))
  168. case "stcp":
  169. res.Stcp = append(res.Stcp, NewProxyStatusResp(status))
  170. case "xtcp":
  171. res.Xtcp = append(res.Xtcp, NewProxyStatusResp(status))
  172. }
  173. }
  174. sort.Sort(ByProxyStatusResp(res.Tcp))
  175. sort.Sort(ByProxyStatusResp(res.Udp))
  176. sort.Sort(ByProxyStatusResp(res.Http))
  177. sort.Sort(ByProxyStatusResp(res.Https))
  178. sort.Sort(ByProxyStatusResp(res.Stcp))
  179. sort.Sort(ByProxyStatusResp(res.Xtcp))
  180. return
  181. }