api.go 9.2 KB

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