-
Notifications
You must be signed in to change notification settings - Fork 0
/
r3x.ts
140 lines (121 loc) · 4.29 KB
/
r3x.ts
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import { ServerResponse, IncomingMessage } from "http";
import { JSONHandler } from './src/handlers/JSONhandler';
import { ErrorHandler } from './src/error/ErrorHandler';
import { FuncSchema } from './src/schema/schemaHandler';
import { Context } from './src/context/Context';
import { join } from "path";
let http = require('http')
let errorRes = new ErrorHandler()
let schema = new FuncSchema()
const exceptionMessage = 'Function Exception'
const fs = require('fs');
/**
* Function user is visible too
* Triggers SDK
* @param r3x {Function}
*/
export function execute(r3x: Function) {
HTTPStream(r3x)
}
/**
* Takes users function and handles requests and responses
* @param r3x {Function}
*/
function HTTPStream(r3x: Function){
let port = 8080
if (port == null) {
console.log("Error Configuration. Missing Port")
process.exit(2)
}
/**
* Handles function request and responses
* @param req {IncomingMessage}
* @param res {ServerResponse}
*/
let functionHandler = (req: IncomingMessage, res: ServerResponse) => {
//declare schema path and get if cors is to be enabled
let schemaPath = join(__dirname, "schema.json")
try {
if (fs.existsSync(schemaPath)) {
let cors = schema.getSchema(schemaPath).cors
if (cors) {
//set cors headers
setCORS(res)
}
}
} catch(err) {
errorRes.sendJSONError(res, 502, {message: "No `schema.json` detected" , detail: err.message.toString()})
}
// declare JSON Handler
let input = new JSONHandler()
// Check only POST and OPTIONS request. OPTIONS is allowed for preflight requests
if (req.method !== 'POST' && req.method !== 'OPTIONS'){
errorRes.sendJSONError(res, 400, {message: "Invalid method", detail: `${req.method} ${req.url}`})
return
}
// Handle request
req.on('error', (err) => {
errorRes.sendJSONError(res, 502, {message: exceptionMessage , detail: err.message.toString()})
}).on('data', chunk => {
// parse request body
input.pushData(chunk)
}).on('end', () => {
let headers = {}
let body = input.getBody()
let cont = new Context(body, headers)
cont.responseContentType = 'application/json'
// handle user function execution
new Promise(function (res, rej) {
try {
return res(r3x(body))
} catch (err) {
rej(err)
}
}).then((result) => {
return sendResponse(cont, res, result)
}, (error) => {
errorRes.sendJSONError(res, 502, {message: exceptionMessage , detail: error.message.toString()})
}).then(() => {
res.end()
res.on('error', (err) => {
errorRes.sendJSONError(res, 502, {message: exceptionMessage , detail: err.message.toString()})
})
}).catch(err => errorRes.sendJSONError(res, 502, {message: exceptionMessage , detail: err.message.toString()}))
})
}
/**
* Creates HTTP server
*/
http.createServer(functionHandler).listen(port)
.on('error', (error : any) => {
console.log(`Connection failed to port ${port}`, error)
process.exit(2)
})
}
// handle response
function sendResponse(cont: Context, resp : ServerResponse, result : any){
let headers = cont._responseHeaders
for (let key in headers) {
if (headers.hasOwnPropery(key)){
resp.setHeader(key, headers[key])
}
}
resp.removeHeader('Content-length')
resp.writeHead(200, 'OK')
console.log(result)
let pro : Promise<any> | undefined
if(result != null) {
pro = Promise.resolve(resp.write(JSON.stringify(result)))
}
return pro
}
/**
* Sets CORS headers
* @param res {ServerResponse}
*/
function setCORS(res: ServerResponse) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Request-Method', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', '*');
}