forked from Script-Hub-Org/Script-Hub
-
Notifications
You must be signed in to change notification settings - Fork 0
/
service.js
111 lines (98 loc) · 3.17 KB
/
service.js
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
const _ = require('lodash')
const fs = require('fs')
const path = require('path')
const Koa = require('koa')
const { scriptMap, scriptMapBeta } = require('./scriptMap.js')
const workspace = path.join(__dirname, './tmp')
fs.mkdirSync(workspace, { recursive: true })
const PORT = process.env.PORT || 9100
const BETA_PORT = process.env.BETA_PORT || 9101
const HOST = process.env.HOST || '0.0.0.0'
const BASE_URL = process.env.BASE_URL || `http://127.0.0.1:${PORT}`
const BETA_BASE_URL = process.env.BETA_BASE_URL || `http://127.0.0.1:${BETA_PORT}`
const { NodeVM } = require('vm2')
const vmconfigs = {
console: 'inherit',
require: {
builtin: ['fs'],
mock: {
fs: {
readFileSync(path) {
try {
const data = fs.readFileSync(path.join(workspace, path))
return data
} catch (err) {
console.error(err)
}
},
writeFileSync(path, data) {
try {
fs.writeFileSync(path.join(workspace, path), data)
} catch (err) {
console.error(err)
}
},
existsSync(path) {
return fs.existsSync(path.join(workspace, path))
},
},
},
},
}
const evalFn = async ({ $request, scriptFilePath }) => {
let content = fs.readFileSync(scriptFilePath, { encoding: 'utf8' })
content = content.replace(/\$\.?done\(/g, '$eval_env.resolve(')
if (content.indexOf('$eval_env.resolve(') === -1) throw new Error('脚本文件内容不包含 $done 的逻辑')
console.log('ℹ️ 执行脚本')
return await new Promise(resolve => {
const $eval_env = {
resolve: async result => {
// console.log('ℹ️ 执行结果')
// console.log(result)
console.log('ℹ️ 执行完毕')
resolve(result)
},
}
eval(content)
})
}
const reqFn = async ({ ctx, scriptMap, baseUrl }) => {
let scriptFilePath
let url = `http://script.hub${ctx.req.url}`
for (const [k, v] of Object.entries(scriptMap)) {
if (v.test(url)) {
scriptFilePath = k
}
}
console.log(`url`, url)
console.log(`scriptFilePath`, scriptFilePath)
let $request = {
method: ctx.req.method,
headers: ctx.req.headers,
url,
}
const result = await evalFn({ $request, scriptFilePath })
// console.log(`result`, result)
ctx.response.status = Number(result?.response?.status || 200)
for (const [k, v] of Object.entries(result?.response?.headers)) {
// if (!/^content-length|content-encoding$/i.test(k)) {
ctx.set(k, v)
// }
}
let body = result?.response?.body
ctx.body = typeof body === 'string' ? body.replace(/https?:\/\/script.hub\//g, `${baseUrl}/`) : body
}
const app = new Koa()
app.use(async ctx => {
await reqFn({ ctx, scriptMap, baseUrl: BASE_URL })
})
app.listen(PORT, HOST, async ctx => {
console.log(`listening on port ${HOST}:${PORT}, http://127.0.0.1:${PORT}, BASE URL: ${BASE_URL}`)
})
const appBeta = new Koa()
appBeta.use(async ctx => {
await reqFn({ ctx, scriptMap: scriptMapBeta, baseUrl: BETA_BASE_URL })
})
appBeta.listen(BETA_PORT, HOST, async ctx => {
console.log(`β listening on port ${HOST}:${BETA_PORT}, http://127.0.0.1:${BETA_PORT}, BASE URL: ${BETA_BASE_URL}`)
})