api.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. package core
  2. import (
  3. "JsRpc/config"
  4. "JsRpc/utils"
  5. "encoding/json"
  6. "github.com/gin-gonic/gin"
  7. "github.com/gorilla/websocket"
  8. log "github.com/sirupsen/logrus"
  9. "github.com/unrolled/secure"
  10. "net/http"
  11. "strconv"
  12. "strings"
  13. "sync"
  14. )
  15. var (
  16. upGrader = websocket.Upgrader{
  17. CheckOrigin: func(r *http.Request) bool { return true },
  18. }
  19. gm = &sync.Mutex{}
  20. hlSyncMap sync.Map
  21. )
  22. // Message 请求和传递请求
  23. type Message struct {
  24. Action string `json:"action"`
  25. MessageId string `json:"message_id"`
  26. Param string `json:"param"`
  27. }
  28. type MessageResponse struct {
  29. Action string `json:"action"`
  30. MessageId string `json:"message_id"`
  31. ResponseData string `json:"response_data"`
  32. }
  33. type ApiParam struct {
  34. GroupName string `form:"group" json:"group"`
  35. ClientId string `form:"clientId" json:"clientId"`
  36. Action string `form:"action" json:"action"`
  37. Param string `form:"param" json:"param"`
  38. Code string `form:"code" json:"code"` // 直接eval的代码
  39. }
  40. // Clients 客户端信息
  41. type Clients struct {
  42. clientGroup string
  43. clientId string
  44. actionData map[string]map[string]chan string // {"action":{"消息id":消息管道}}
  45. clientWs *websocket.Conn
  46. }
  47. // NewClient initializes a new Clients instance
  48. func NewClient(group string, uid string, ws *websocket.Conn) *Clients {
  49. return &Clients{
  50. clientGroup: group,
  51. clientId: uid,
  52. actionData: make(map[string]map[string]chan string), // action有消息后就保存到chan里
  53. clientWs: ws,
  54. }
  55. }
  56. func GinJsonMsg(c *gin.Context, code int, msg string) {
  57. c.JSON(code, gin.H{"status": code, "data": msg})
  58. return
  59. }
  60. // ws, provides inject function for a job
  61. func ws(c *gin.Context) {
  62. group, clientId := c.Query("group"), c.Query("clientId")
  63. //必须要group名字,不然不让它连接ws
  64. if group == "" {
  65. return
  66. }
  67. //没有给客户端id的话 就用uuid给他生成一个
  68. if clientId == "" {
  69. clientId = utils.GetUUID()
  70. }
  71. wsClient, err := upGrader.Upgrade(c.Writer, c.Request, nil)
  72. if err != nil {
  73. log.Error("websocket err:", err)
  74. return
  75. }
  76. client := NewClient(group, clientId, wsClient)
  77. hlSyncMap.Store(group+"->"+clientId, client)
  78. utils.LogPrint("新上线group:" + group + ",clientId:->" + clientId)
  79. clientNameJson := `{"registerId":"` + clientId + `"}`
  80. err = wsClient.WriteMessage(1, []byte(clientNameJson))
  81. if err != nil {
  82. log.Warning("注册成功,但发送回执信息失败")
  83. }
  84. for {
  85. //等待数据
  86. _, message, err := wsClient.ReadMessage()
  87. if err != nil {
  88. break
  89. }
  90. // 将得到的数据转成结构体
  91. messageStruct := MessageResponse{}
  92. err = json.Unmarshal(message, &messageStruct)
  93. if err != nil {
  94. log.Error("接收到的消息不是设定的格式 不做处理", err)
  95. }
  96. action := messageStruct.Action
  97. messageId := messageStruct.MessageId
  98. msg := messageStruct.ResponseData
  99. // 这里直接给管道塞数据,那么之前发送的时候要初始化好
  100. if client.actionData[action][messageId] == nil {
  101. log.Warning("当前消息id:", messageId, " 已被超时释放,回调的数据不做处理")
  102. } else {
  103. client.actionData[action][messageId] <- msg
  104. }
  105. if len(msg) > 100 {
  106. utils.LogPrint("id", messageId, "get_message:", msg[:101]+"......")
  107. } else {
  108. utils.LogPrint("id", messageId, "get_message:", msg)
  109. }
  110. }
  111. defer func(ws *websocket.Conn) {
  112. _ = ws.Close()
  113. utils.LogPrint(group+"->"+clientId, "下线了")
  114. hlSyncMap.Range(func(key, value interface{}) bool {
  115. //client, _ := value.(*Clients)
  116. if key == group+"->"+clientId {
  117. hlSyncMap.Delete(key)
  118. }
  119. return true
  120. })
  121. }(wsClient)
  122. }
  123. func wsTest(c *gin.Context) {
  124. testClient, _ := upGrader.Upgrade(c.Writer, c.Request, nil)
  125. for {
  126. //等待数据
  127. _, message, err := testClient.ReadMessage()
  128. if err != nil {
  129. break
  130. }
  131. msg := string(message)
  132. utils.LogPrint("接收到测试消息", msg)
  133. _ = testClient.WriteMessage(websocket.BinaryMessage, []byte(msg))
  134. }
  135. defer func(ws *websocket.Conn) {
  136. _ = ws.Close()
  137. }(testClient)
  138. }
  139. func checkRequestParam(c *gin.Context) (*Clients, string) {
  140. var RequestParam ApiParam
  141. if err := c.ShouldBind(&RequestParam); err != nil {
  142. return &Clients{}, err.Error()
  143. }
  144. group := c.Query("group")
  145. if group == "" {
  146. return &Clients{}, "需要传入group"
  147. }
  148. clientId := RequestParam.ClientId
  149. client := getRandomClient(group, clientId)
  150. if client == nil {
  151. return &Clients{}, "没有找到对应的group或clientId,请通过list接口查看现有的注入"
  152. }
  153. return client, ""
  154. }
  155. func GetCookie(c *gin.Context) {
  156. client, errorStr := checkRequestParam(c)
  157. if errorStr != "" {
  158. GinJsonMsg(c, http.StatusBadRequest, errorStr)
  159. return
  160. }
  161. c3 := make(chan string, 1)
  162. go client.GQueryFunc("_execjs", utils.ConcatCode("document.cookie"), c3)
  163. c.JSON(http.StatusOK, gin.H{"status": 200, "group": client.clientGroup, "clientId": client.clientId, "data": <-c3})
  164. }
  165. func GetHtml(c *gin.Context) {
  166. client, errorStr := checkRequestParam(c)
  167. if errorStr != "" {
  168. GinJsonMsg(c, http.StatusBadRequest, errorStr)
  169. return
  170. }
  171. c3 := make(chan string, 1)
  172. go client.GQueryFunc("_execjs", utils.ConcatCode("document.documentElement.outerHTML"), c3)
  173. c.JSON(http.StatusOK, gin.H{"status": 200, "group": client.clientGroup, "clientId": client.clientId, "data": <-c3})
  174. }
  175. // GetResult 接收web请求参数,并发给客户端获取结果
  176. func getResult(c *gin.Context) {
  177. var RequestParam ApiParam
  178. if err := c.ShouldBind(&RequestParam); err != nil {
  179. GinJsonMsg(c, http.StatusBadRequest, err.Error())
  180. return
  181. }
  182. action := RequestParam.Action
  183. if action == "" {
  184. GinJsonMsg(c, http.StatusOK, "请传入action来调用客户端方法")
  185. return
  186. }
  187. client, errorStr := checkRequestParam(c)
  188. if errorStr != "" {
  189. GinJsonMsg(c, http.StatusBadRequest, errorStr)
  190. return
  191. }
  192. c2 := make(chan string, 1)
  193. go client.GQueryFunc(action, RequestParam.Param, c2)
  194. //把管道传过去,获得值就返回了
  195. c.JSON(http.StatusOK, gin.H{"status": 200, "group": client.clientGroup, "clientId": client.clientId, "data": <-c2})
  196. }
  197. func execjs(c *gin.Context) {
  198. var RequestParam ApiParam
  199. if err := c.ShouldBind(&RequestParam); err != nil {
  200. GinJsonMsg(c, http.StatusBadRequest, err.Error())
  201. return
  202. }
  203. Action := "_execjs"
  204. //获取参数
  205. JsCode := RequestParam.Code
  206. if JsCode == "" {
  207. GinJsonMsg(c, http.StatusBadRequest, "请传入代码")
  208. return
  209. }
  210. client, errorStr := checkRequestParam(c)
  211. if errorStr != "" {
  212. GinJsonMsg(c, http.StatusBadRequest, errorStr)
  213. return
  214. }
  215. c2 := make(chan string)
  216. go client.GQueryFunc(Action, JsCode, c2)
  217. c.JSON(200, gin.H{"status": "200", "group": client.clientGroup, "name": client.clientId, "data": <-c2})
  218. }
  219. func getList(c *gin.Context) {
  220. var data = make(map[string][]string)
  221. hlSyncMap.Range(func(_, value interface{}) bool {
  222. client, ok := value.(*Clients)
  223. if !ok {
  224. return true // 继续遍历
  225. }
  226. group := client.clientGroup
  227. data[group] = append(data[group], client.clientId)
  228. return true
  229. })
  230. c.JSON(http.StatusOK, gin.H{"status": 200, "data": data})
  231. }
  232. func index(c *gin.Context) {
  233. //c.String(200, "你好,我是黑脸怪~")
  234. htmlContent := `
  235. <!DOCTYPE html>
  236. <html>
  237. <head><title>欢迎使用JsRpc</title></head>
  238. <body>
  239. 你好,我是黑脸怪~
  240. <p>微信:hl98_cn</p>
  241. </body>
  242. </html>
  243. `
  244. // 返回 HTML 页面
  245. c.Data(200, "text/html; charset=utf-8", []byte(htmlContent))
  246. }
  247. func tlsHandler(HttpsHost string) gin.HandlerFunc {
  248. return func(c *gin.Context) {
  249. secureMiddleware := secure.New(secure.Options{
  250. SSLRedirect: true,
  251. SSLHost: HttpsHost,
  252. })
  253. err := secureMiddleware.Process(c.Writer, c.Request)
  254. if err != nil {
  255. c.Abort()
  256. return
  257. }
  258. c.Next()
  259. }
  260. }
  261. func getGinMode(mode string) string {
  262. switch mode {
  263. case "release":
  264. return gin.ReleaseMode
  265. case "debug":
  266. return gin.DebugMode
  267. case "test":
  268. return gin.TestMode
  269. }
  270. return gin.ReleaseMode // 默认就是release模式
  271. }
  272. func setupRouters(conf config.ConfStruct) *gin.Engine {
  273. router := gin.Default()
  274. if conf.Cors { // 是否开启cors中间件
  275. router.Use(CorsMiddleWare())
  276. }
  277. return router
  278. }
  279. func InitAPI(conf config.ConfStruct) {
  280. if conf.CloseWebLog {
  281. // 将默认的日志输出器设置为空
  282. gin.DefaultWriter = utils.LogWriter{}
  283. }
  284. gin.SetMode(getGinMode(conf.Mode))
  285. router := setupRouters(conf)
  286. setJsRpcRouters(router) // 核心路由
  287. var sb strings.Builder
  288. sb.WriteString("当前监听地址:")
  289. sb.WriteString(conf.BasicListen)
  290. sb.WriteString(" ssl启用状态:")
  291. sb.WriteString(strconv.FormatBool(conf.HttpsServices.IsEnable))
  292. if conf.HttpsServices.IsEnable {
  293. sb.WriteString(" https监听地址:")
  294. sb.WriteString(conf.HttpsServices.HttpsListen)
  295. router.Use(tlsHandler(conf.HttpsServices.HttpsListen))
  296. go func() {
  297. err := router.RunTLS(
  298. conf.HttpsServices.HttpsListen,
  299. conf.HttpsServices.PemPath,
  300. conf.HttpsServices.KeyPath,
  301. )
  302. if err != nil {
  303. log.Error(err)
  304. }
  305. }()
  306. }
  307. log.Infoln(sb.String())
  308. err := router.Run(conf.BasicListen)
  309. if err != nil {
  310. log.Errorln("服务启动失败..")
  311. }
  312. }