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