-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathserver-es.js
More file actions
61 lines (55 loc) · 2.09 KB
/
Copy pathserver-es.js
File metadata and controls
61 lines (55 loc) · 2.09 KB
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
// ES Module SRPC Server
// https://github.com/yzITI/srpc
import http from '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) || (typeof F === 'function' && n === 'prototype')) throw 1
F = F[n]
if (typeof F !== 'object' && typeof F !== 'function') throw 1
}
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) {
const ip = req.headers['x-forwarded-for']?.split(',')[0] || req.headers['x-real-ip'] || req.socket.remoteAddress || req.connection?.remoteAddress
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, ip)
resp.writeHead(status, {
...cors,
'Content-Length': Buffer.byteLength(body),
'Content-Type': status === 200 ? 'application/json' : 'text/plain'
}).end(body)
})
}
export default 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
})