admin_api.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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. "io/ioutil"
  19. "net/http"
  20. "sort"
  21. "strings"
  22. "github.com/julienschmidt/httprouter"
  23. ini "github.com/vaughan0/go-ini"
  24. "github.com/fatedier/frp/g"
  25. "github.com/fatedier/frp/models/config"
  26. "github.com/fatedier/frp/utils/log"
  27. )
  28. type GeneralResponse struct {
  29. Code int64 `json:"code"`
  30. Msg string `json:"msg"`
  31. }
  32. // api/reload
  33. type ReloadResp struct {
  34. GeneralResponse
  35. }
  36. func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
  37. var (
  38. buf []byte
  39. res ReloadResp
  40. )
  41. defer func() {
  42. log.Info("Http response [/api/reload]: code [%d]", res.Code)
  43. buf, _ = json.Marshal(&res)
  44. w.Write(buf)
  45. }()
  46. log.Info("Http request: [/api/reload]")
  47. b, err := ioutil.ReadFile(g.GlbClientCfg.CfgFile)
  48. if err != nil {
  49. res.Code = 1
  50. res.Msg = err.Error()
  51. log.Error("reload frpc config file error: %v", err)
  52. return
  53. }
  54. content := string(b)
  55. newCommonCfg, err := config.UnmarshalClientConfFromIni(nil, content)
  56. if err != nil {
  57. res.Code = 2
  58. res.Msg = err.Error()
  59. log.Error("reload frpc common section error: %v", err)
  60. return
  61. }
  62. conf, err := ini.LoadFile(g.GlbClientCfg.CfgFile)
  63. if err != nil {
  64. res.Code = 1
  65. res.Msg = err.Error()
  66. log.Error("reload frpc config file error: %v", err)
  67. return
  68. }
  69. pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromIni(g.GlbClientCfg.User, conf, newCommonCfg.Start)
  70. if err != nil {
  71. res.Code = 3
  72. res.Msg = err.Error()
  73. log.Error("reload frpc proxy config error: %v", err)
  74. return
  75. }
  76. err = svr.ctl.reloadConf(pxyCfgs, visitorCfgs)
  77. if err != nil {
  78. res.Code = 4
  79. res.Msg = err.Error()
  80. log.Error("reload frpc proxy config error: %v", err)
  81. return
  82. }
  83. log.Info("success reload conf")
  84. return
  85. }
  86. type StatusResp struct {
  87. Tcp []ProxyStatusResp `json:"tcp"`
  88. Udp []ProxyStatusResp `json:"udp"`
  89. Http []ProxyStatusResp `json:"http"`
  90. Https []ProxyStatusResp `json:"https"`
  91. Stcp []ProxyStatusResp `json:"stcp"`
  92. Xtcp []ProxyStatusResp `json:"xtcp"`
  93. }
  94. type ProxyStatusResp struct {
  95. Name string `json:"name"`
  96. Type string `json:"type"`
  97. Status string `json:"status"`
  98. Err string `json:"err"`
  99. LocalAddr string `json:"local_addr"`
  100. Plugin string `json:"plugin"`
  101. RemoteAddr string `json:"remote_addr"`
  102. }
  103. type ByProxyStatusResp []ProxyStatusResp
  104. func (a ByProxyStatusResp) Len() int { return len(a) }
  105. func (a ByProxyStatusResp) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  106. func (a ByProxyStatusResp) Less(i, j int) bool { return strings.Compare(a[i].Name, a[j].Name) < 0 }
  107. func NewProxyStatusResp(status *ProxyStatus) ProxyStatusResp {
  108. psr := ProxyStatusResp{
  109. Name: status.Name,
  110. Type: status.Type,
  111. Status: status.Status,
  112. Err: status.Err,
  113. }
  114. switch cfg := status.Cfg.(type) {
  115. case *config.TcpProxyConf:
  116. if cfg.LocalPort != 0 {
  117. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  118. }
  119. psr.Plugin = cfg.Plugin
  120. if status.Err != "" {
  121. psr.RemoteAddr = fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, cfg.RemotePort)
  122. } else {
  123. psr.RemoteAddr = g.GlbClientCfg.ServerAddr + status.RemoteAddr
  124. }
  125. case *config.UdpProxyConf:
  126. if cfg.LocalPort != 0 {
  127. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  128. }
  129. if status.Err != "" {
  130. psr.RemoteAddr = fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, cfg.RemotePort)
  131. } else {
  132. psr.RemoteAddr = g.GlbClientCfg.ServerAddr + status.RemoteAddr
  133. }
  134. case *config.HttpProxyConf:
  135. if cfg.LocalPort != 0 {
  136. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  137. }
  138. psr.Plugin = cfg.Plugin
  139. psr.RemoteAddr = status.RemoteAddr
  140. case *config.HttpsProxyConf:
  141. if cfg.LocalPort != 0 {
  142. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  143. }
  144. psr.Plugin = cfg.Plugin
  145. psr.RemoteAddr = status.RemoteAddr
  146. case *config.StcpProxyConf:
  147. if cfg.LocalPort != 0 {
  148. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  149. }
  150. psr.Plugin = cfg.Plugin
  151. case *config.XtcpProxyConf:
  152. if cfg.LocalPort != 0 {
  153. psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
  154. }
  155. psr.Plugin = cfg.Plugin
  156. }
  157. return psr
  158. }
  159. // api/status
  160. func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
  161. var (
  162. buf []byte
  163. res StatusResp
  164. )
  165. res.Tcp = make([]ProxyStatusResp, 0)
  166. res.Udp = make([]ProxyStatusResp, 0)
  167. res.Http = make([]ProxyStatusResp, 0)
  168. res.Https = make([]ProxyStatusResp, 0)
  169. res.Stcp = make([]ProxyStatusResp, 0)
  170. res.Xtcp = make([]ProxyStatusResp, 0)
  171. defer func() {
  172. log.Info("Http response [/api/status]")
  173. buf, _ = json.Marshal(&res)
  174. w.Write(buf)
  175. }()
  176. log.Info("Http request: [/api/status]")
  177. ps := svr.ctl.pm.GetAllProxyStatus()
  178. for _, status := range ps {
  179. switch status.Type {
  180. case "tcp":
  181. res.Tcp = append(res.Tcp, NewProxyStatusResp(status))
  182. case "udp":
  183. res.Udp = append(res.Udp, NewProxyStatusResp(status))
  184. case "http":
  185. res.Http = append(res.Http, NewProxyStatusResp(status))
  186. case "https":
  187. res.Https = append(res.Https, NewProxyStatusResp(status))
  188. case "stcp":
  189. res.Stcp = append(res.Stcp, NewProxyStatusResp(status))
  190. case "xtcp":
  191. res.Xtcp = append(res.Xtcp, NewProxyStatusResp(status))
  192. }
  193. }
  194. sort.Sort(ByProxyStatusResp(res.Tcp))
  195. sort.Sort(ByProxyStatusResp(res.Udp))
  196. sort.Sort(ByProxyStatusResp(res.Http))
  197. sort.Sort(ByProxyStatusResp(res.Https))
  198. sort.Sort(ByProxyStatusResp(res.Stcp))
  199. sort.Sort(ByProxyStatusResp(res.Xtcp))
  200. return
  201. }