| import crypto from 'crypto'
|
| import http from './express.js'
|
| import { Config, puppeteer, logger } from '#karin'
|
| import VueCache from './VueFileCache.js'
|
|
|
| const port = Config.Config.http.port
|
|
|
| export default class Server {
|
| constructor (socket, request) {
|
| this.id = 0
|
| this.socket = socket
|
| this.request = request
|
| this.host = this.getHost()
|
| this.vueCache = VueCache
|
| }
|
|
|
| init () {
|
| this.socket.on('message', data => this.message(data))
|
| this.socket.on('close', () => {
|
| logger.error(`[Server][连接关闭]:${this.request.url}`)
|
| })
|
| }
|
|
|
| getHost () {
|
| const isSecure = this.request.connection.encrypted
|
| const protocol = isSecure ? 'wss' : 'ws'
|
| const host = this.request.headers.host
|
| const path = this.request.url
|
| return `${protocol}://${host}${path}`
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| async message (data) {
|
| data = JSON.parse(data)
|
| switch (data.action) {
|
| case 'heartbeat':
|
| return logger.debug(`[Server][心跳]:${this.request.url}`)
|
| case 'render': {
|
|
|
| data.data.file = decodeURIComponent(data.data.file)
|
| logger.debug(`[正向WS][渲染] URL: ${this.host} html:${data.data.file}`)
|
| let res
|
| if (data.data.vue && Config.Config.server.http) {
|
| const cacheId = this.vueCache.addCache(data.data.file, data.data.name, data.data.props)
|
| data.data.file = `http://localhost:${Config.Config.http.port}/vue/${data.data.vueTemplate || 'default'}/?id=${cacheId}`
|
| res = await puppeteer.screenshot(data.data)
|
| this.vueCache.deleteCache(cacheId)
|
| } else {
|
| res = await puppeteer.screenshot(data.data)
|
| }
|
| res.echo = data.echo
|
| res.action = 'renderRes'
|
| this.socket.send(JSON.stringify(res))
|
| break
|
| }
|
| case 'renderHtml': {
|
|
|
| const file = decodeURIComponent(data.data.file)
|
| logger.debug(`[正向WS][渲染] URL: ${this.host} html:${file}`)
|
|
|
| const hash = `render-${this.id}-${crypto.randomUUID()}`
|
| const host = `http://localhost:${port}/api/render?hash=${hash}`
|
| http.file.set(hash, { ws: this, file })
|
|
|
| data.data.file = host
|
|
|
| data.data.hash = hash
|
| const res = await puppeteer.screenshot(data.data)
|
| res.echo = data.echo
|
| res.action = 'renderRes'
|
| this.socket.send(JSON.stringify(res))
|
| break
|
| }
|
| case 'static': {
|
|
|
| this.socket.emit(data.echo, data)
|
| break
|
| }
|
| default:
|
| break
|
| }
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| async SendApi (action, params, time = 120) {
|
| const echo = crypto.randomUUID()
|
| const request = JSON.stringify({ echo, action, params })
|
| return new Promise((resolve, reject) => {
|
| this.socket.send(request)
|
| this.socket.once(echo, (data) => {
|
| if (data.status === 'ok') {
|
| resolve(data.data)
|
| } else {
|
| logger.error(`[Api请求错误] ${JSON.stringify(data, null, 2)}`)
|
| reject(data)
|
| }
|
| })
|
|
|
| setTimeout(() => {
|
| reject(new Error('API请求超时'))
|
| }, time * 1000)
|
| })
|
| }
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|