dashboard_api.go 8.9 KB

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