123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- package core
- import (
- "JsRpc/config"
- "JsRpc/utils"
- "encoding/json"
- "github.com/gin-gonic/gin"
- "github.com/gorilla/websocket"
- log "github.com/sirupsen/logrus"
- "github.com/unrolled/secure"
- "net/http"
- "strconv"
- "strings"
- "sync"
- )
- var (
- upGrader = websocket.Upgrader{
- CheckOrigin: func(r *http.Request) bool { return true },
- }
- rwMu sync.RWMutex
- hlSyncMap sync.Map
- )
- // Message 请求和传递请求
- type Message struct {
- Action string `json:"action"`
- MessageId string `json:"message_id"`
- Param string `json:"param"`
- }
- type MessageResponse struct {
- Action string `json:"action"`
- MessageId string `json:"message_id"`
- ResponseData string `json:"response_data"`
- }
- type ApiParam struct {
- GroupName string `form:"group" json:"group"`
- ClientId string `form:"clientId" json:"clientId"`
- Action string `form:"action" json:"action"`
- Param string `form:"param" json:"param"`
- Code string `form:"code" json:"code"` // 直接eval的代码
- }
- // Clients 客户端信息
- type Clients struct {
- clientGroup string
- clientId string
- actionData map[string]map[string]chan string // {"action":{"消息id":消息管道}}
- clientWs *websocket.Conn
- }
- func (c *Clients) readFromMap(funcName string, MessageId string) chan string {
- rwMu.RLock()
- defer rwMu.RUnlock()
- return c.actionData[funcName][MessageId]
- }
- func (c *Clients) writeToMap(funcName string, MessageId string, msg string) {
- rwMu.Lock()
- defer rwMu.Unlock()
- c.actionData[funcName][MessageId] <- msg
- }
- // NewClient initializes a new Clients instance
- func NewClient(group string, uid string, ws *websocket.Conn) *Clients {
- return &Clients{
- clientGroup: group,
- clientId: uid,
- actionData: make(map[string]map[string]chan string), // action有消息后就保存到chan里
- clientWs: ws,
- }
- }
- func GinJsonMsg(c *gin.Context, code int, msg string) {
- c.JSON(code, gin.H{"status": code, "data": msg})
- return
- }
- // ws, provides inject function for a job
- func ws(c *gin.Context) {
- group, clientId := c.Query("group"), c.Query("clientId")
- //必须要group名字,不然不让它连接ws
- if group == "" {
- return
- }
- //没有给客户端id的话 就用uuid给他生成一个
- if clientId == "" {
- clientId = utils.GetUUID()
- }
- wsClient, err := upGrader.Upgrade(c.Writer, c.Request, nil)
- if err != nil {
- log.Error("websocket err:", err)
- return
- }
- client := NewClient(group, clientId, wsClient)
- hlSyncMap.Store(group+"->"+clientId, client)
- utils.LogPrint("新上线group:" + group + ",clientId:->" + clientId)
- clientNameJson := `{"registerId":"` + clientId + `"}`
- err = wsClient.WriteMessage(1, []byte(clientNameJson))
- if err != nil {
- log.Warning("注册成功,但发送回执信息失败")
- }
- for {
- //等待数据
- _, message, err := wsClient.ReadMessage()
- if err != nil {
- break
- }
- // 将得到的数据转成结构体
- messageStruct := MessageResponse{}
- err = json.Unmarshal(message, &messageStruct)
- if err != nil {
- log.Error("接收到的消息不是设定的格式 不做处理", err)
- }
- action := messageStruct.Action
- messageId := messageStruct.MessageId
- msg := messageStruct.ResponseData
- // 这里直接给管道塞数据,那么之前发送的时候要初始化好
- if client.readFromMap(action, messageId) == nil {
- log.Warning("当前消息id:", messageId, " 已被超时释放,回调的数据不做处理")
- } else {
- client.writeToMap(action, messageId, msg)
- }
- if len(msg) > 100 {
- utils.LogPrint("id", messageId, "get_message:", msg[:101]+"......")
- } else {
- utils.LogPrint("id", messageId, "get_message:", msg)
- }
- }
- defer func(ws *websocket.Conn) {
- _ = ws.Close()
- utils.LogPrint(group+"->"+clientId, "下线了")
- hlSyncMap.Range(func(key, value interface{}) bool {
- //client, _ := value.(*Clients)
- if key == group+"->"+clientId {
- hlSyncMap.Delete(key)
- }
- return true
- })
- }(wsClient)
- }
- func wsTest(c *gin.Context) {
- testClient, _ := upGrader.Upgrade(c.Writer, c.Request, nil)
- for {
- //等待数据
- _, message, err := testClient.ReadMessage()
- if err != nil {
- break
- }
- msg := string(message)
- utils.LogPrint("接收到测试消息", msg)
- _ = testClient.WriteMessage(websocket.BinaryMessage, []byte(msg))
- }
- defer func(ws *websocket.Conn) {
- _ = ws.Close()
- }(testClient)
- }
- func checkRequestParam(c *gin.Context) (*Clients, string) {
- var RequestParam ApiParam
- if err := c.ShouldBind(&RequestParam); err != nil {
- return &Clients{}, err.Error()
- }
- group := RequestParam.GroupName
- if group == "" {
- return &Clients{}, "需要传入group"
- }
- clientId := RequestParam.ClientId
- client := getRandomClient(group, clientId)
- if client == nil {
- return &Clients{}, "没有找到对应的group或clientId,请通过list接口查看现有的注入"
- }
- return client, ""
- }
- func GetCookie(c *gin.Context) {
- client, errorStr := checkRequestParam(c)
- if errorStr != "" {
- GinJsonMsg(c, http.StatusBadRequest, errorStr)
- return
- }
- c3 := make(chan string, 1)
- go client.GQueryFunc("_execjs", utils.ConcatCode("document.cookie"), c3)
- c.JSON(http.StatusOK, gin.H{"status": 200, "group": client.clientGroup, "clientId": client.clientId, "data": <-c3})
- }
- func GetHtml(c *gin.Context) {
- client, errorStr := checkRequestParam(c)
- if errorStr != "" {
- GinJsonMsg(c, http.StatusBadRequest, errorStr)
- return
- }
- c3 := make(chan string, 1)
- go client.GQueryFunc("_execjs", utils.ConcatCode("document.documentElement.outerHTML"), c3)
- c.JSON(http.StatusOK, gin.H{"status": 200, "group": client.clientGroup, "clientId": client.clientId, "data": <-c3})
- }
- // GetResult 接收web请求参数,并发给客户端获取结果
- func getResult(c *gin.Context) {
- var RequestParam ApiParam
- if err := c.ShouldBind(&RequestParam); err != nil {
- GinJsonMsg(c, http.StatusBadRequest, err.Error())
- return
- }
- action := RequestParam.Action
- if action == "" {
- GinJsonMsg(c, http.StatusOK, "请传入action来调用客户端方法")
- return
- }
- client, errorStr := checkRequestParam(c)
- if errorStr != "" {
- GinJsonMsg(c, http.StatusBadRequest, errorStr)
- return
- }
- c2 := make(chan string, 1)
- go client.GQueryFunc(action, RequestParam.Param, c2)
- //把管道传过去,获得值就返回了
- c.JSON(http.StatusOK, gin.H{"status": 200, "group": client.clientGroup, "clientId": client.clientId, "data": <-c2})
- }
- func execjs(c *gin.Context) {
- var RequestParam ApiParam
- if err := c.ShouldBind(&RequestParam); err != nil {
- GinJsonMsg(c, http.StatusBadRequest, err.Error())
- return
- }
- Action := "_execjs"
- //获取参数
- JsCode := RequestParam.Code
- if JsCode == "" {
- GinJsonMsg(c, http.StatusBadRequest, "请传入代码")
- return
- }
- client, errorStr := checkRequestParam(c)
- if errorStr != "" {
- GinJsonMsg(c, http.StatusBadRequest, errorStr)
- return
- }
- c2 := make(chan string)
- go client.GQueryFunc(Action, JsCode, c2)
- c.JSON(200, gin.H{"status": "200", "group": client.clientGroup, "name": client.clientId, "data": <-c2})
- }
- func getList(c *gin.Context) {
- var data = make(map[string][]string)
- hlSyncMap.Range(func(_, value interface{}) bool {
- client, ok := value.(*Clients)
- if !ok {
- return true // 继续遍历
- }
- group := client.clientGroup
- data[group] = append(data[group], client.clientId)
- return true
- })
- c.JSON(http.StatusOK, gin.H{"status": 200, "data": data})
- }
- func index(c *gin.Context) {
- //c.String(200, "你好,我是黑脸怪~")
- htmlContent := `
- <!DOCTYPE html>
- <html>
- <head><title>欢迎使用JsRpc</title></head>
- <body>
- 你好,我是黑脸怪~
- <p>微信:hl98_cn</p>
- </body>
- </html>
- `
- // 返回 HTML 页面
- c.Data(200, "text/html; charset=utf-8", []byte(htmlContent))
- }
- func tlsHandler(HttpsHost string) gin.HandlerFunc {
- return func(c *gin.Context) {
- secureMiddleware := secure.New(secure.Options{
- SSLRedirect: true,
- SSLHost: HttpsHost,
- })
- err := secureMiddleware.Process(c.Writer, c.Request)
- if err != nil {
- c.Abort()
- return
- }
- c.Next()
- }
- }
- func getGinMode(mode string) string {
- switch mode {
- case "release":
- return gin.ReleaseMode
- case "debug":
- return gin.DebugMode
- case "test":
- return gin.TestMode
- }
- return gin.ReleaseMode // 默认就是release模式
- }
- func setupRouters(conf config.ConfStruct) *gin.Engine {
- router := gin.Default()
- if conf.Cors { // 是否开启cors中间件
- router.Use(CorsMiddleWare())
- }
- if conf.RouterReplace.IsEnable {
- router.Use(RouteReplace(router, conf.RouterReplace.ReplaceRoute))
- }
- return router
- }
- func InitAPI(conf config.ConfStruct) {
- if conf.CloseWebLog {
- // 将默认的日志输出器设置为空
- gin.DefaultWriter = utils.LogWriter{}
- }
- gin.SetMode(getGinMode(conf.Mode))
- router := setupRouters(conf)
- setJsRpcRouters(router) // 核心路由
- var sb strings.Builder
- sb.WriteString("当前监听地址:")
- sb.WriteString(conf.BasicListen)
- sb.WriteString(" ssl启用状态:")
- sb.WriteString(strconv.FormatBool(conf.HttpsServices.IsEnable))
- if conf.HttpsServices.IsEnable {
- sb.WriteString(" https监听地址:")
- sb.WriteString(conf.HttpsServices.HttpsListen)
- router.Use(tlsHandler(conf.HttpsServices.HttpsListen))
- go func() {
- err := router.RunTLS(
- conf.HttpsServices.HttpsListen,
- conf.HttpsServices.PemPath,
- conf.HttpsServices.KeyPath,
- )
- if err != nil {
- log.Error(err)
- }
- }()
- }
- log.Infoln(sb.String())
- err := router.Run(conf.BasicListen)
- if err != nil {
- log.Errorln("服务启动失败..")
- }
- }
|