File size: 2,427 Bytes
6d0ad0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import WebSocket from 'ws'
import { logger, puppeteer } from '#karin'
import VueCache from './VueFileCache.js'
import { Config } from '#karin'

export const store = new Map()
export default class WebSocketClient {
  constructor (url, headerId) {
    this.url = url
    this.headerId = headerId
    this.ws = null
    this.statr = false
    this.vueCache = VueCache
  }

  /** 创建 WebSocket 连接 */
  createWebSocket () {
    this.ws = new WebSocket(this.url, {
      headers: {
        'renderer-id': this.headerId,
        'renderer-type': 'image'
      }
    })

    this.ws.on('open', () => {
      this.statr = true
      logger.mark('[反向WS][连接成功]', this.url)

      /** 每5秒发一次心跳 中断就重连 */
      this.timer = setInterval(() => {
        try {
          this.ws.send(JSON.stringify({ action: 'heartbeat', data: { status: 'ok' } }))
        } catch (e) {
          logger.error('[反向WS]心跳异常:', this.url)
          logger.error(e)
          /** 关闭连接 */
          this.ws.close()
          clearInterval(this.timer)
        }
      }, 5000)
    })

    /** 反向ws暂时只考虑渲染本地文件或http */
    this.ws.on('message', async message => {
      message = JSON.parse(message)
      logger.debug(`[反向WS][渲染] URL: ${this.url} html:${message.data.file}`)
      const action = 'renderRes'
      const { echo, data } = message
      let res
      if (data.vue && Config.Config.server.http) {
        const cacheId = this.vueCache.addCache(data.file, data.name, data.props)
        res = await puppeteer.screenshot({...data, ...{file: `http://localhost:${Config.Config.http.port}/vue/${data.vueTemplate || 'default'}/?id=${cacheId}`}})
        this.vueCache.deleteCache(cacheId)
      } else {
        res = await puppeteer.screenshot(data)
      }
      res.echo = echo
      res.action = action
      return this.ws.send(JSON.stringify(res))
    })

    /** 连接断开 */
    this.ws.on('close', () => {
      this.statr = false
      logger.error('[反向WS][连接错误]:', this.url)
      try { clearInterval(this.timer) } catch { }
      this.reconnect()
    })

    /** 连接错误 */
    this.ws.on('error', error => {
      logger.debug(error)
    })
  }

  /** 重连函数 */
  reconnect () {
    setTimeout(this.createWebSocket.bind(this), 5000)
  }
}