dashboard_api.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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 server
  15. import (
  16. "encoding/json"
  17. "net/http"
  18. "github.com/fatedier/frp/pkg/config"
  19. "github.com/fatedier/frp/pkg/consts"
  20. "github.com/fatedier/frp/pkg/metrics/mem"
  21. "github.com/fatedier/frp/pkg/util/log"
  22. "github.com/fatedier/frp/pkg/util/version"
  23. "github.com/gorilla/mux"
  24. )
  25. type GeneralResponse struct {
  26. Code int
  27. Msg string
  28. }
  29. type serverInfoResp struct {
  30. Version string `json:"version"`
  31. BindPort int `json:"bind_port"`
  32. BindUDPPort int `json:"bind_udp_port"`
  33. VhostHTTPPort int `json:"vhost_http_port"`
  34. VhostHTTPSPort int `json:"vhost_https_port"`
  35. KCPBindPort int `json:"kcp_bind_port"`
  36. SubdomainHost string `json:"subdomain_host"`
  37. MaxPoolCount int64 `json:"max_pool_count"`
  38. MaxPortsPerClient int64 `json:"max_ports_per_client"`
  39. HeartBeatTimeout int64 `json:"heart_beat_timeout"`
  40. TotalTrafficIn int64 `json:"total_traffic_in"`
  41. TotalTrafficOut int64 `json:"total_traffic_out"`
  42. CurConns int64 `json:"cur_conns"`
  43. ClientCounts int64 `json:"client_counts"`
  44. ProxyTypeCounts map[string]int64 `json:"proxy_type_count"`
  45. }
  46. // api/serverinfo
  47. func (svr *Service) APIServerInfo(w http.ResponseWriter, r *http.Request) {
  48. res := GeneralResponse{Code: 200}
  49. defer func() {
  50. log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
  51. w.WriteHeader(res.Code)
  52. if len(res.Msg) > 0 {
  53. w.Write([]byte(res.Msg))
  54. }
  55. }()
  56. log.Info("Http request: [%s]", r.URL.Path)
  57. serverStats := mem.StatsCollector.GetServer()
  58. svrResp := serverInfoResp{
  59. Version: version.Full(),
  60. BindPort: svr.cfg.BindPort,
  61. BindUDPPort: svr.cfg.BindUDPPort,
  62. VhostHTTPPort: svr.cfg.VhostHTTPPort,
  63. VhostHTTPSPort: svr.cfg.VhostHTTPSPort,
  64. KCPBindPort: svr.cfg.KCPBindPort,
  65. SubdomainHost: svr.cfg.SubDomainHost,
  66. MaxPoolCount: svr.cfg.MaxPoolCount,
  67. MaxPortsPerClient: svr.cfg.MaxPortsPerClient,
  68. HeartBeatTimeout: svr.cfg.HeartbeatTimeout,
  69. TotalTrafficIn: serverStats.TotalTrafficIn,
  70. TotalTrafficOut: serverStats.TotalTrafficOut,
  71. CurConns: serverStats.CurConns,
  72. ClientCounts: serverStats.ClientCounts,
  73. ProxyTypeCounts: serverStats.ProxyTypeCounts,
  74. }
  75. buf, _ := json.Marshal(&svrResp)
  76. res.Msg = string(buf)
  77. }
  78. type BaseOutConf struct {
  79. config.BaseProxyConf
  80. }
  81. type TCPOutConf struct {
  82. BaseOutConf
  83. RemotePort int `json:"remote_port"`
  84. }
  85. type TCPMuxOutConf struct {
  86. BaseOutConf
  87. config.DomainConf
  88. Multiplexer string `json:"multiplexer"`
  89. }
  90. type UDPOutConf struct {
  91. BaseOutConf
  92. RemotePort int `json:"remote_port"`
  93. }
  94. type HTTPOutConf struct {
  95. BaseOutConf
  96. config.DomainConf
  97. Locations []string `json:"locations"`
  98. HostHeaderRewrite string `json:"host_header_rewrite"`
  99. }
  100. type HTTPSOutConf struct {
  101. BaseOutConf
  102. config.DomainConf
  103. }
  104. type STCPOutConf struct {
  105. BaseOutConf
  106. }
  107. type XTCPOutConf struct {
  108. BaseOutConf
  109. }
  110. func getConfByType(proxyType string) interface{} {
  111. switch proxyType {
  112. case consts.TCPProxy:
  113. return &TCPOutConf{}
  114. case consts.TCPMuxProxy:
  115. return &TCPMuxOutConf{}
  116. case consts.UDPProxy:
  117. return &UDPOutConf{}
  118. case consts.HTTPProxy:
  119. return &HTTPOutConf{}
  120. case consts.HTTPSProxy:
  121. return &HTTPSOutConf{}
  122. case consts.STCPProxy:
  123. return &STCPOutConf{}
  124. case consts.XTCPProxy:
  125. return &XTCPOutConf{}
  126. default:
  127. return nil
  128. }
  129. }
  130. // Get proxy info.
  131. type ProxyStatsInfo struct {
  132. Name string `json:"name"`
  133. Conf interface{} `json:"conf"`
  134. TodayTrafficIn int64 `json:"today_traffic_in"`
  135. TodayTrafficOut int64 `json:"today_traffic_out"`
  136. CurConns int64 `json:"cur_conns"`
  137. LastStartTime string `json:"last_start_time"`
  138. LastCloseTime string `json:"last_close_time"`
  139. Status string `json:"status"`
  140. }
  141. type GetProxyInfoResp struct {
  142. Proxies []*ProxyStatsInfo `json:"proxies"`
  143. }
  144. // api/proxy/:type
  145. func (svr *Service) APIProxyByType(w http.ResponseWriter, r *http.Request) {
  146. res := GeneralResponse{Code: 200}
  147. params := mux.Vars(r)
  148. proxyType := params["type"]
  149. defer func() {
  150. log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
  151. w.WriteHeader(res.Code)
  152. if len(res.Msg) > 0 {
  153. w.Write([]byte(res.Msg))
  154. }
  155. }()
  156. log.Info("Http request: [%s]", r.URL.Path)
  157. proxyInfoResp := GetProxyInfoResp{}
  158. proxyInfoResp.Proxies = svr.getProxyStatsByType(proxyType)
  159. buf, _ := json.Marshal(&proxyInfoResp)
  160. res.Msg = string(buf)
  161. }
  162. func (svr *Service) getProxyStatsByType(proxyType string) (proxyInfos []*ProxyStatsInfo) {
  163. proxyStats := mem.StatsCollector.GetProxiesByType(proxyType)
  164. proxyInfos = make([]*ProxyStatsInfo, 0, len(proxyStats))
  165. for _, ps := range proxyStats {
  166. proxyInfo := &ProxyStatsInfo{}
  167. if pxy, ok := svr.pxyManager.GetByName(ps.Name); ok {
  168. content, err := json.Marshal(pxy.GetConf())
  169. if err != nil {
  170. log.Warn("marshal proxy [%s] conf info error: %v", ps.Name, err)
  171. continue
  172. }
  173. proxyInfo.Conf = getConfByType(ps.Type)
  174. if err = json.Unmarshal(content, &proxyInfo.Conf); err != nil {
  175. log.Warn("unmarshal proxy [%s] conf info error: %v", ps.Name, err)
  176. continue
  177. }
  178. proxyInfo.Status = consts.Online
  179. } else {
  180. proxyInfo.Status = consts.Offline
  181. }
  182. proxyInfo.Name = ps.Name
  183. proxyInfo.TodayTrafficIn = ps.TodayTrafficIn
  184. proxyInfo.TodayTrafficOut = ps.TodayTrafficOut
  185. proxyInfo.CurConns = ps.CurConns
  186. proxyInfo.LastStartTime = ps.LastStartTime
  187. proxyInfo.LastCloseTime = ps.LastCloseTime
  188. proxyInfos = append(proxyInfos, proxyInfo)
  189. }
  190. return
  191. }
  192. // Get proxy info by name.
  193. type GetProxyStatsResp struct {
  194. Name string `json:"name"`
  195. Conf interface{} `json:"conf"`
  196. TodayTrafficIn int64 `json:"today_traffic_in"`
  197. TodayTrafficOut int64 `json:"today_traffic_out"`
  198. CurConns int64 `json:"cur_conns"`
  199. LastStartTime string `json:"last_start_time"`
  200. LastCloseTime string `json:"last_close_time"`
  201. Status string `json:"status"`
  202. }
  203. // api/proxy/:type/:name
  204. func (svr *Service) APIProxyByTypeAndName(w http.ResponseWriter, r *http.Request) {
  205. res := GeneralResponse{Code: 200}
  206. params := mux.Vars(r)
  207. proxyType := params["type"]
  208. name := params["name"]
  209. defer func() {
  210. log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
  211. w.WriteHeader(res.Code)
  212. if len(res.Msg) > 0 {
  213. w.Write([]byte(res.Msg))
  214. }
  215. }()
  216. log.Info("Http request: [%s]", r.URL.Path)
  217. proxyStatsResp := GetProxyStatsResp{}
  218. proxyStatsResp, res.Code, res.Msg = svr.getProxyStatsByTypeAndName(proxyType, name)
  219. if res.Code != 200 {
  220. return
  221. }
  222. buf, _ := json.Marshal(&proxyStatsResp)
  223. res.Msg = string(buf)
  224. }
  225. func (svr *Service) getProxyStatsByTypeAndName(proxyType string, proxyName string) (proxyInfo GetProxyStatsResp, code int, msg string) {
  226. proxyInfo.Name = proxyName
  227. ps := mem.StatsCollector.GetProxiesByTypeAndName(proxyType, proxyName)
  228. if ps == nil {
  229. code = 404
  230. msg = "no proxy info found"
  231. } else {
  232. if pxy, ok := svr.pxyManager.GetByName(proxyName); ok {
  233. content, err := json.Marshal(pxy.GetConf())
  234. if err != nil {
  235. log.Warn("marshal proxy [%s] conf info error: %v", ps.Name, err)
  236. code = 400
  237. msg = "parse conf error"
  238. return
  239. }
  240. proxyInfo.Conf = getConfByType(ps.Type)
  241. if err = json.Unmarshal(content, &proxyInfo.Conf); err != nil {
  242. log.Warn("unmarshal proxy [%s] conf info error: %v", ps.Name, err)
  243. code = 400
  244. msg = "parse conf error"
  245. return
  246. }
  247. proxyInfo.Status = consts.Online
  248. } else {
  249. proxyInfo.Status = consts.Offline
  250. }
  251. proxyInfo.TodayTrafficIn = ps.TodayTrafficIn
  252. proxyInfo.TodayTrafficOut = ps.TodayTrafficOut
  253. proxyInfo.CurConns = ps.CurConns
  254. proxyInfo.LastStartTime = ps.LastStartTime
  255. proxyInfo.LastCloseTime = ps.LastCloseTime
  256. code = 200
  257. }
  258. return
  259. }
  260. // api/traffic/:name
  261. type GetProxyTrafficResp struct {
  262. Name string `json:"name"`
  263. TrafficIn []int64 `json:"traffic_in"`
  264. TrafficOut []int64 `json:"traffic_out"`
  265. }
  266. func (svr *Service) APIProxyTraffic(w http.ResponseWriter, r *http.Request) {
  267. res := GeneralResponse{Code: 200}
  268. params := mux.Vars(r)
  269. name := params["name"]
  270. defer func() {
  271. log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
  272. w.WriteHeader(res.Code)
  273. if len(res.Msg) > 0 {
  274. w.Write([]byte(res.Msg))
  275. }
  276. }()
  277. log.Info("Http request: [%s]", r.URL.Path)
  278. trafficResp := GetProxyTrafficResp{}
  279. trafficResp.Name = name
  280. proxyTrafficInfo := mem.StatsCollector.GetProxyTraffic(name)
  281. if proxyTrafficInfo == nil {
  282. res.Code = 404
  283. res.Msg = "no proxy info found"
  284. return
  285. }
  286. trafficResp.TrafficIn = proxyTrafficInfo.TrafficIn
  287. trafficResp.TrafficOut = proxyTrafficInfo.TrafficOut
  288. buf, _ := json.Marshal(&trafficResp)
  289. res.Msg = string(buf)
  290. }