api.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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的话 就用时间戳给他生成一个
  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. for {
  80. //等待数据
  81. _, message, err := wsClient.ReadMessage()
  82. if err != nil {
  83. break
  84. }
  85. // 将得到的数据转成结构体
  86. messageStruct := MessageResponse{}
  87. err = json.Unmarshal(message, &messageStruct)
  88. if err != nil {
  89. log.Error("接收到的消息不是设定的格式 不做处理", err)
  90. }
  91. action := messageStruct.Action
  92. messageId := messageStruct.MessageId
  93. msg := messageStruct.ResponseData
  94. // 这里直接给管道塞数据,那么之前发送的时候要初始化好
  95. if client.actionData[action][messageId] == nil {
  96. log.Warning("当前消息id:", messageId, " 已被超时释放,回调的数据不做处理")
  97. } else {
  98. client.actionData[action][messageId] <- msg
  99. }
  100. if len(msg) > 100 {
  101. utils.LogPrint("id", messageId, "get_message:", msg[:101]+"......")
  102. } else {
  103. utils.LogPrint("id", messageId, "get_message:", msg)
  104. }
  105. }
  106. defer func(ws *websocket.Conn) {
  107. _ = ws.Close()
  108. utils.LogPrint(group+"->"+clientId, "下线了")
  109. hlSyncMap.Range(func(key, value interface{}) bool {
  110. //client, _ := value.(*Clients)
  111. if key == group+"->"+clientId {
  112. hlSyncMap.Delete(key)
  113. }
  114. return true
  115. })
  116. }(wsClient)
  117. }
  118. func wsTest(c *gin.Context) {
  119. testClient, _ := upGrader.Upgrade(c.Writer, c.Request, nil)
  120. for {
  121. //等待数据
  122. _, message, err := testClient.ReadMessage()
  123. if err != nil {
  124. break
  125. }
  126. msg := string(message)
  127. utils.LogPrint("接收到测试消息", msg)
  128. _ = testClient.WriteMessage(websocket.BinaryMessage, []byte(msg))
  129. }
  130. defer func(ws *websocket.Conn) {
  131. _ = ws.Close()
  132. }(testClient)
  133. }
  134. func GetCookie(c *gin.Context) {
  135. var RequestParam ApiParam
  136. if err := c.ShouldBind(&RequestParam); err != nil {
  137. GinJsonMsg(c, http.StatusBadRequest, err.Error())
  138. return
  139. }
  140. group := c.Query("group")
  141. if group == "" {
  142. GinJsonMsg(c, http.StatusBadRequest, "需要传入group")
  143. return
  144. }
  145. clientId := RequestParam.ClientId
  146. client := getRandomClient(group, clientId)
  147. if client == nil {
  148. GinJsonMsg(c, http.StatusBadRequest, "没有找到对应的group或clientId,请通过list接口查看现有的注入")
  149. return
  150. }
  151. c3 := make(chan string, 1)
  152. go client.GQueryFunc("_execjs", utils.ConcatCode("document.cookie"), c3)
  153. c.JSON(http.StatusOK, gin.H{"status": 200, "group": client.clientGroup, "clientId": client.clientId, "data": <-c3})
  154. }
  155. func GetHtml(c *gin.Context) {
  156. var RequestParam ApiParam
  157. if err := c.ShouldBind(&RequestParam); err != nil {
  158. GinJsonMsg(c, http.StatusBadRequest, err.Error())
  159. return
  160. }
  161. group := c.Query("group")
  162. if group == "" {
  163. GinJsonMsg(c, http.StatusBadRequest, "需要传入group")
  164. return
  165. }
  166. clientId := RequestParam.ClientId
  167. client := getRandomClient(group, clientId)
  168. if client == nil {
  169. GinJsonMsg(c, http.StatusBadRequest, "没有找到对应的group或clientId,请通过list接口查看现有的注入")
  170. return
  171. }
  172. c3 := make(chan string, 1)
  173. go client.GQueryFunc("_execjs", utils.ConcatCode("document.documentElement.outerHTML"), c3)
  174. c.JSON(http.StatusOK, gin.H{"status": 200, "group": client.clientGroup, "clientId": client.clientId, "data": <-c3})
  175. }
  176. // GetResult 接收web请求参数,并发给客户端获取结果
  177. func getResult(c *gin.Context) {
  178. var RequestParam ApiParam
  179. if err := c.ShouldBind(&RequestParam); err != nil {
  180. GinJsonMsg(c, http.StatusBadRequest, err.Error())
  181. return
  182. }
  183. group := RequestParam.GroupName
  184. if group == "" {
  185. GinJsonMsg(c, http.StatusBadRequest, "需要传入group")
  186. return
  187. }
  188. action := RequestParam.Action
  189. if action == "" {
  190. GinJsonMsg(c, http.StatusOK, "请传入action来调用客户端方法")
  191. return
  192. }
  193. clientId := RequestParam.ClientId
  194. client := getRandomClient(group, clientId)
  195. if client == nil {
  196. GinJsonMsg(c, http.StatusBadRequest, "没有找到对应的group或clientId,请通过list接口查看现有的注入")
  197. return
  198. }
  199. c2 := make(chan string, 1)
  200. go client.GQueryFunc(action, RequestParam.Param, c2)
  201. //把管道传过去,获得值就返回了
  202. c.JSON(http.StatusOK, gin.H{"status": 200, "group": client.clientGroup, "clientId": client.clientId, "data": <-c2})
  203. }
  204. func execjs(c *gin.Context) {
  205. var RequestParam ApiParam
  206. if err := c.ShouldBind(&RequestParam); err != nil {
  207. GinJsonMsg(c, http.StatusBadRequest, err.Error())
  208. return
  209. }
  210. Action := "_execjs"
  211. //获取参数
  212. group := RequestParam.GroupName
  213. if group == "" {
  214. GinJsonMsg(c, http.StatusBadRequest, "需要传入group")
  215. return
  216. }
  217. JsCode := RequestParam.Code
  218. if JsCode == "" {
  219. GinJsonMsg(c, http.StatusBadRequest, "请传入代码")
  220. return
  221. }
  222. clientId := RequestParam.ClientId
  223. client := getRandomClient(group, clientId)
  224. if client == nil {
  225. GinJsonMsg(c, http.StatusBadRequest, "没有找到对应的group或clientId,请通过list接口查看现有的注入")
  226. return
  227. }
  228. c2 := make(chan string)
  229. go client.GQueryFunc(Action, JsCode, c2)
  230. c.JSON(200, gin.H{"status": "200", "group": client.clientGroup, "name": client.clientId, "data": <-c2})
  231. }
  232. func getList(c *gin.Context) {
  233. var data = make(map[string][]string)
  234. hlSyncMap.Range(func(_, value interface{}) bool {
  235. client, ok := value.(*Clients)
  236. if !ok {
  237. return true // 继续遍历
  238. }
  239. group := client.clientGroup
  240. data[group] = append(data[group], client.clientId)
  241. return true
  242. })
  243. c.JSON(http.StatusOK, gin.H{"status": 200, "data": data})
  244. }
  245. func index(c *gin.Context) {
  246. //c.String(200, "你好,我是黑脸怪~")
  247. htmlContent := `
  248. <!DOCTYPE html>
  249. <html>
  250. <head><title>欢迎使用JsRpc</title></head>
  251. <body>
  252. 你好,我是黑脸怪~
  253. <p>微信:hl98_cn</p>
  254. </body>
  255. </html>
  256. `
  257. // 返回 HTML 页面
  258. c.Data(200, "text/html; charset=utf-8", []byte(htmlContent))
  259. }
  260. func tlsHandler(HttpsHost string) gin.HandlerFunc {
  261. return func(c *gin.Context) {
  262. secureMiddleware := secure.New(secure.Options{
  263. SSLRedirect: true,
  264. SSLHost: HttpsHost,
  265. })
  266. err := secureMiddleware.Process(c.Writer, c.Request)
  267. if err != nil {
  268. c.Abort()
  269. return
  270. }
  271. c.Next()
  272. }
  273. }
  274. func getGinMode(mode string) string {
  275. switch mode {
  276. case "release":
  277. return gin.ReleaseMode
  278. case "debug":
  279. return gin.DebugMode
  280. case "test":
  281. return gin.TestMode
  282. }
  283. return gin.ReleaseMode // 默认就是release模式
  284. }
  285. func setupRouters(conf config.ConfStruct) *gin.Engine {
  286. router := gin.Default()
  287. if conf.Cors { // 是否开启cors中间件
  288. router.Use(CorsMiddleWare())
  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. }