admin_api.go 5.8 KB

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