admin_api.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. if status.Err != "" {
  111. psr.RemoteAddr = fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, cfg.RemotePort)
  112. } else {
  113. psr.RemoteAddr = config.ClientCommonCfg.ServerAddr + status.RemoteAddr
  114. }
  115. case *config.UdpProxyConf:
  116. if cfg.LocalPort != 0 {
  117. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  118. }
  119. if status.Err != "" {
  120. psr.RemoteAddr = fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, cfg.RemotePort)
  121. } else {
  122. psr.RemoteAddr = config.ClientCommonCfg.ServerAddr + status.RemoteAddr
  123. }
  124. case *config.HttpProxyConf:
  125. if cfg.LocalPort != 0 {
  126. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  127. }
  128. psr.Plugin = cfg.Plugin
  129. psr.RemoteAddr = status.RemoteAddr
  130. case *config.HttpsProxyConf:
  131. if cfg.LocalPort != 0 {
  132. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  133. }
  134. psr.Plugin = cfg.Plugin
  135. psr.RemoteAddr = status.RemoteAddr
  136. case *config.StcpProxyConf:
  137. if cfg.LocalPort != 0 {
  138. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  139. }
  140. psr.Plugin = cfg.Plugin
  141. case *config.XtcpProxyConf:
  142. if cfg.LocalPort != 0 {
  143. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  144. }
  145. psr.Plugin = cfg.Plugin
  146. }
  147. return psr
  148. }
  149. // api/status
  150. func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
  151. var (
  152. buf []byte
  153. res StatusResp
  154. )
  155. res.Tcp = make([]ProxyStatusResp, 0)
  156. res.Udp = make([]ProxyStatusResp, 0)
  157. res.Http = make([]ProxyStatusResp, 0)
  158. res.Https = make([]ProxyStatusResp, 0)
  159. res.Stcp = make([]ProxyStatusResp, 0)
  160. res.Xtcp = make([]ProxyStatusResp, 0)
  161. defer func() {
  162. log.Info("Http response [/api/status]")
  163. buf, _ = json.Marshal(&res)
  164. w.Write(buf)
  165. }()
  166. log.Info("Http request: [/api/status]")
  167. ps := svr.ctl.pm.GetAllProxyStatus()
  168. for _, status := range ps {
  169. switch status.Type {
  170. case "tcp":
  171. res.Tcp = append(res.Tcp, NewProxyStatusResp(status))
  172. case "udp":
  173. res.Udp = append(res.Udp, NewProxyStatusResp(status))
  174. case "http":
  175. res.Http = append(res.Http, NewProxyStatusResp(status))
  176. case "https":
  177. res.Https = append(res.Https, NewProxyStatusResp(status))
  178. case "stcp":
  179. res.Stcp = append(res.Stcp, NewProxyStatusResp(status))
  180. case "xtcp":
  181. res.Xtcp = append(res.Xtcp, NewProxyStatusResp(status))
  182. }
  183. }
  184. sort.Sort(ByProxyStatusResp(res.Tcp))
  185. sort.Sort(ByProxyStatusResp(res.Udp))
  186. sort.Sort(ByProxyStatusResp(res.Http))
  187. sort.Sort(ByProxyStatusResp(res.Https))
  188. sort.Sort(ByProxyStatusResp(res.Stcp))
  189. sort.Sort(ByProxyStatusResp(res.Xtcp))
  190. return
  191. }