-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathserver-common.js
59 lines (53 loc) · 1.94 KB
/
server-common.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
// CommonJS SRPC Server
// https://github.com/yzITI/srpc
const http = require('http')
const functions = {}
let _hooks = {}
async function handle (raw, IP) {
let body = {}, F = functions
try { body = JSON.parse(raw) }
catch { return ['Body Error', 400] }
if (!(body.N instanceof Array) || !(body.A instanceof Array)) return ['Arguments Error', 400]
try { // find function
for (const n of body.N) {
if (!F.hasOwnProperty(n)) throw 1
F = F[n]
}
if (typeof F !== 'function') throw 1
} catch { return ['Function Not Found', 404] }
try { // call function
const ctx = { N: body.N, A: body.A || [], IP, F }
if (_hooks.before) await _hooks.before(ctx)
if (typeof ctx.R !== 'undefined') return [JSON.stringify({ R: ctx.R }), 200]
ctx.R = await F(...ctx.A)
if (_hooks.after) await _hooks.after(ctx)
return [JSON.stringify({ R: ctx.R }), 200]
} catch (e) { return ['Internal Error', 500] }
}
const cors = {
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS, POST'
}
function listener (req, resp) {
if (req.method === 'OPTIONS') return resp.writeHead(204, cors).end()
if (req.method !== 'POST') return resp.writeHead(400).end('Method Error')
let raw = ''
req.on('data', chunk => { raw += chunk })
req.on('end', async () => {
const [body, status] = await handle(raw, req.headers['x-forwarded-for']?.split(',')[0] || req.headers['x-real-ip'] || req.socket.address().address)
resp.writeHead(status, {
...cors,
'Content-Length': Buffer.byteLength(body),
'Content-Type': status === 200 ? 'application/json' : 'text/plain'
}).end(body)
})
}
module.exports = new Proxy((hooks = {}, port = 11111) => {
_hooks = hooks
const server = http.createServer(listener)
return new Promise(r => { server.listen(port, r) })
}, {
get: (target, prop) => functions[prop],
set: (target, prop, value) => functions[prop] = value
})