dashboard_api.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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/g"
  19. "github.com/fatedier/frp/models/config"
  20. "github.com/fatedier/frp/models/consts"
  21. "github.com/fatedier/frp/utils/log"
  22. "github.com/fatedier/frp/utils/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. cfg := &g.GlbServerCfg.ServerCommonConf
  58. serverStats := svr.statsCollector.GetServer()
  59. svrResp := ServerInfoResp{
  60. Version: version.Full(),
  61. BindPort: cfg.BindPort,
  62. BindUdpPort: cfg.BindUdpPort,
  63. VhostHttpPort: cfg.VhostHttpPort,
  64. VhostHttpsPort: cfg.VhostHttpsPort,
  65. KcpBindPort: cfg.KcpBindPort,
  66. SubdomainHost: cfg.SubDomainHost,
  67. MaxPoolCount: cfg.MaxPoolCount,
  68. MaxPortsPerClient: cfg.MaxPortsPerClient,
  69. HeartBeatTimeout: cfg.HeartBeatTimeout,
  70. TotalTrafficIn: serverStats.TotalTrafficIn,
  71. TotalTrafficOut: serverStats.TotalTrafficOut,
  72. CurConns: serverStats.CurConns,
  73. ClientCounts: serverStats.ClientCounts,
  74. ProxyTypeCounts: serverStats.ProxyTypeCounts,
  75. }
  76. buf, _ := json.Marshal(&svrResp)
  77. res.Msg = string(buf)
  78. }
  79. type BaseOutConf struct {
  80. config.BaseProxyConf
  81. }
  82. type TcpOutConf struct {
  83. BaseOutConf
  84. RemotePort int `json:"remote_port"`
  85. }
  86. type UdpOutConf struct {
  87. BaseOutConf
  88. RemotePort int `json:"remote_port"`
  89. }
  90. type HttpOutConf struct {
  91. BaseOutConf
  92. config.DomainConf
  93. Locations []string `json:"locations"`
  94. HostHeaderRewrite string `json:"host_header_rewrite"`
  95. }
  96. type HttpsOutConf struct {
  97. BaseOutConf
  98. config.DomainConf
  99. }
  100. type StcpOutConf struct {
  101. BaseOutConf
  102. }
  103. type XtcpOutConf struct {
  104. BaseOutConf
  105. }
  106. func getConfByType(proxyType string) interface{} {
  107. switch proxyType {
  108. case consts.TcpProxy:
  109. return &TcpOutConf{}
  110. case consts.UdpProxy:
  111. return &UdpOutConf{}
  112. case consts.HttpProxy:
  113. return &HttpOutConf{}
  114. case consts.HttpsProxy:
  115. return &HttpsOutConf{}
  116. case consts.StcpProxy:
  117. return &StcpOutConf{}
  118. case consts.XtcpProxy:
  119. return &XtcpOutConf{}
  120. default:
  121. return nil
  122. }
  123. }
  124. // Get proxy info.
  125. type ProxyStatsInfo struct {
  126. Name string `json:"name"`
  127. Conf interface{} `json:"conf"`
  128. TodayTrafficIn int64 `json:"today_traffic_in"`
  129. TodayTrafficOut int64 `json:"today_traffic_out"`
  130. CurConns int64 `json:"cur_conns"`
  131. LastStartTime string `json:"last_start_time"`
  132. LastCloseTime string `json:"last_close_time"`
  133. Status string `json:"status"`
  134. }
  135. type GetProxyInfoResp struct {
  136. Proxies []*ProxyStatsInfo `json:"proxies"`
  137. }
  138. // api/proxy/:type
  139. func (svr *Service) ApiProxyByType(w http.ResponseWriter, r *http.Request) {
  140. res := GeneralResponse{Code: 200}
  141. params := mux.Vars(r)
  142. proxyType := params["type"]
  143. defer func() {
  144. log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
  145. w.WriteHeader(res.Code)
  146. if len(res.Msg) > 0 {
  147. w.Write([]byte(res.Msg))
  148. }
  149. }()
  150. log.Info("Http request: [%s]", r.URL.Path)
  151. proxyInfoResp := GetProxyInfoResp{}
  152. proxyInfoResp.Proxies = svr.getProxyStatsByType(proxyType)
  153. buf, _ := json.Marshal(&proxyInfoResp)
  154. res.Msg = string(buf)
  155. }
  156. func (svr *Service) getProxyStatsByType(proxyType string) (proxyInfos []*ProxyStatsInfo) {
  157. proxyStats := svr.statsCollector.GetProxiesByType(proxyType)
  158. proxyInfos = make([]*ProxyStatsInfo, 0, len(proxyStats))
  159. for _, ps := range proxyStats {
  160. proxyInfo := &ProxyStatsInfo{}
  161. if pxy, ok := svr.pxyManager.GetByName(ps.Name); ok {
  162. content, err := json.Marshal(pxy.GetConf())
  163. if err != nil {
  164. log.Warn("marshal proxy [%s] conf info error: %v", ps.Name, err)
  165. continue
  166. }
  167. proxyInfo.Conf = getConfByType(ps.Type)
  168. if err = json.Unmarshal(content, &proxyInfo.Conf); err != nil {
  169. log.Warn("unmarshal proxy [%s] conf info error: %v", ps.Name, err)
  170. continue
  171. }
  172. proxyInfo.Status = consts.Online
  173. } else {
  174. proxyInfo.Status = consts.Offline
  175. }
  176. proxyInfo.Name = ps.Name
  177. proxyInfo.TodayTrafficIn = ps.TodayTrafficIn
  178. proxyInfo.TodayTrafficOut = ps.TodayTrafficOut
  179. proxyInfo.CurConns = ps.CurConns
  180. proxyInfo.LastStartTime = ps.LastStartTime
  181. proxyInfo.LastCloseTime = ps.LastCloseTime
  182. proxyInfos = append(proxyInfos, proxyInfo)
  183. }
  184. return
  185. }
  186. // Get proxy info by name.
  187. type GetProxyStatsResp struct {
  188. Name string `json:"name"`
  189. Conf interface{} `json:"conf"`
  190. TodayTrafficIn int64 `json:"today_traffic_in"`
  191. TodayTrafficOut int64 `json:"today_traffic_out"`
  192. CurConns int64 `json:"cur_conns"`
  193. LastStartTime string `json:"last_start_time"`
  194. LastCloseTime string `json:"last_close_time"`
  195. Status string `json:"status"`
  196. }
  197. // api/proxy/:type/:name
  198. func (svr *Service) ApiProxyByTypeAndName(w http.ResponseWriter, r *http.Request) {
  199. res := GeneralResponse{Code: 200}
  200. params := mux.Vars(r)
  201. proxyType := params["type"]
  202. name := params["name"]
  203. defer func() {
  204. log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
  205. w.WriteHeader(res.Code)
  206. if len(res.Msg) > 0 {
  207. w.Write([]byte(res.Msg))
  208. }
  209. }()
  210. log.Info("Http request: [%s]", r.URL.Path)
  211. proxyStatsResp := GetProxyStatsResp{}
  212. proxyStatsResp, res.Code, res.Msg = svr.getProxyStatsByTypeAndName(proxyType, name)
  213. if res.Code != 200 {
  214. return
  215. }
  216. buf, _ := json.Marshal(&proxyStatsResp)
  217. res.Msg = string(buf)
  218. }
  219. func (svr *Service) getProxyStatsByTypeAndName(proxyType string, proxyName string) (proxyInfo GetProxyStatsResp, code int, msg string) {
  220. proxyInfo.Name = proxyName
  221. ps := svr.statsCollector.GetProxiesByTypeAndName(proxyType, proxyName)
  222. if ps == nil {
  223. code = 404
  224. msg = "no proxy info found"
  225. } else {
  226. if pxy, ok := svr.pxyManager.GetByName(proxyName); ok {
  227. content, err := json.Marshal(pxy.GetConf())
  228. if err != nil {
  229. log.Warn("marshal proxy [%s] conf info error: %v", ps.Name, err)
  230. code = 400
  231. msg = "parse conf error"
  232. return
  233. }
  234. proxyInfo.Conf = getConfByType(ps.Type)
  235. if err = json.Unmarshal(content, &proxyInfo.Conf); err != nil {
  236. log.Warn("unmarshal proxy [%s] conf info error: %v", ps.Name, err)
  237. code = 400
  238. msg = "parse conf error"
  239. return
  240. }
  241. proxyInfo.Status = consts.Online
  242. } else {
  243. proxyInfo.Status = consts.Offline
  244. }
  245. proxyInfo.TodayTrafficIn = ps.TodayTrafficIn
  246. proxyInfo.TodayTrafficOut = ps.TodayTrafficOut
  247. proxyInfo.CurConns = ps.CurConns
  248. proxyInfo.LastStartTime = ps.LastStartTime
  249. proxyInfo.LastCloseTime = ps.LastCloseTime
  250. }
  251. return
  252. }
  253. // api/traffic/:name
  254. type GetProxyTrafficResp struct {
  255. Name string `json:"name"`
  256. TrafficIn []int64 `json:"traffic_in"`
  257. TrafficOut []int64 `json:"traffic_out"`
  258. }
  259. func (svr *Service) ApiProxyTraffic(w http.ResponseWriter, r *http.Request) {
  260. res := GeneralResponse{Code: 200}
  261. params := mux.Vars(r)
  262. name := params["name"]
  263. defer func() {
  264. log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
  265. w.WriteHeader(res.Code)
  266. if len(res.Msg) > 0 {
  267. w.Write([]byte(res.Msg))
  268. }
  269. }()
  270. log.Info("Http request: [%s]", r.URL.Path)
  271. trafficResp := GetProxyTrafficResp{}
  272. trafficResp.Name = name
  273. proxyTrafficInfo := svr.statsCollector.GetProxyTraffic(name)
  274. if proxyTrafficInfo == nil {
  275. res.Code = 404
  276. res.Msg = "no proxy info found"
  277. return
  278. } else {
  279. trafficResp.TrafficIn = proxyTrafficInfo.TrafficIn
  280. trafficResp.TrafficOut = proxyTrafficInfo.TrafficOut
  281. }
  282. buf, _ := json.Marshal(&trafficResp)
  283. res.Msg = string(buf)
  284. }