-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
163 lines (156 loc) · 4.74 KB
/
index.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import { NextApiRequest, NextApiResponse } from "next";
import { lookup } from "mime-types";
import * as fs from "fs";
interface ValidateRequest extends NextApiRequest {}
interface ValidateResponse<T> extends NextApiResponse {
sendStatus?: (code: number, message?: string) => void;
sendFile?: (url?: string) => void;
}
/** Request handler */
type RequestValidatorHandlerType = (
/** Request object */
Req: ValidateRequest,
/** Response object */
Res: ValidateResponse<any>
) => void;
type SingleHandler = (
/** Handle only requests using one request method */
Req: RequestValidatorHandlerType
) => void;
interface IValidator {
/** Handles a GET request */
get?: SingleHandler;
/** Handles a POST request */
post?: SingleHandler;
/** Handles a PUT request */
put?: SingleHandler;
/** Handles a DELETE request */
delete?: SingleHandler;
/** Handles a HEAD request */
head?: SingleHandler;
/** Handles a CONNECT request */
connect?: SingleHandler;
/** Handles an OPTIONS request */
options?: SingleHandler;
/** Handles a TRACE request */
trace?: SingleHandler;
/** Handles a PATCH request */
patch?: SingleHandler;
}
interface IValidatorProps {
/** Handles a GET request */
get?: RequestValidatorHandlerType;
/** Handles a POST request */
post?: RequestValidatorHandlerType;
/** Handles a PUT request */
put?: RequestValidatorHandlerType;
/** Handles a DELETE request */
delete?: RequestValidatorHandlerType;
/** Handles a HEAD request */
head?: RequestValidatorHandlerType;
/** Handles a CONNECT request */
connect?: RequestValidatorHandlerType;
/** Handles an OPTIONS request */
options?: RequestValidatorHandlerType;
/** Handles a TRACE request */
trace?: RequestValidatorHandlerType;
/** Handles a PATCH request */
patch?: RequestValidatorHandlerType;
}
/** Specify callbacks for different methods made to an endpoint */
type ValidateType = (handlers: IValidatorProps) => Function;
interface IValidate extends IValidator, ValidateType {}
const RequestMethods = [
"get",
"post",
"put",
"delete",
"head",
"connect",
"options",
"trace",
"patch",
];
const Validate: IValidate = (handlers: IValidatorProps) => {
const validateResponseCallback: RequestValidatorHandlerType = function (
req,
res
) {
const _handlers = { ...handlers };
const vResponse = {
...res,
sendStatus: (code, message = "") => {
res.status(code).send(message);
},
sendFile: (url = "") => {
try {
const fileHeadType = lookup(url);
if (typeof fileHeadType === "string") {
res.writeHead(200, {
"Content-Type": fileHeadType.toString(),
});
const rs = fs.createReadStream(url);
rs.pipe(res);
} else {
res.status(404).send("File not found");
}
} catch (err) {
throw err;
}
},
} as ValidateResponse<any>;
try {
RequestMethods.forEach((requestMethod: string) => {
if (!handlers[requestMethod]) {
const invalidMethodCb: RequestValidatorHandlerType = (req, res) => {
res
.status(405)
.send(`Cannot ${requestMethod.toUpperCase()} ${req.url}`);
};
_handlers[requestMethod] = invalidMethodCb;
}
});
return _handlers[req.method.toLowerCase()](req, vResponse);
} catch (err) {
res.send("An error ocurred");
throw err;
}
};
return validateResponseCallback;
};
RequestMethods.forEach((requestMethod) => {
Validate[requestMethod] = (handler: RequestValidatorHandlerType) => {
const responseCb: RequestValidatorHandlerType = (req, res) => {
const { method } = req;
const vResponse = {
...res,
sendStatus: (code, message = "") => {
res.status(code).send(message);
},
sendFile: (url = "") => {
try {
const fileHeadType = lookup(url);
if (typeof fileHeadType === "string") {
res.writeHead(200, {
"Content-Type": fileHeadType.toString(),
});
const rs = fs.createReadStream(url);
rs.pipe(res);
} else {
res.status(404).send("File not found");
}
} catch (err) {
throw err;
}
},
} as ValidateResponse<any>;
if (method.toLowerCase() === requestMethod) {
handler(req, vResponse);
} else {
vResponse.sendStatus(405, `Cannot ${method} ${req.url}`);
}
};
return responseCb;
};
});
export default Validate;