securequ 1.1.19 → 1.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/Base.cjs +146 -146
- package/client/Base.cjs.map +1 -1
- package/client/Base.d.ts +18 -18
- package/client/Base.js +146 -146
- package/client/Base.js.map +1 -1
- package/client/index.cjs +155 -138
- package/client/index.cjs.map +1 -1
- package/client/index.d.ts +10 -10
- package/client/index.js +156 -139
- package/client/index.js.map +1 -1
- package/client/types.d.ts +39 -35
- package/include/compress.cjs +31 -31
- package/include/compress.cjs.map +1 -1
- package/include/compress.d.ts +9 -9
- package/include/compress.js +33 -33
- package/include/compress.js.map +1 -1
- package/include/crypto.cjs +132 -132
- package/include/crypto.cjs.map +1 -1
- package/include/crypto.d.ts +21 -21
- package/include/crypto.js +132 -132
- package/include/crypto.js.map +1 -1
- package/include/file-scaner.cjs +77 -95
- package/include/file-scaner.cjs.map +1 -1
- package/include/file-scaner.d.ts +11 -11
- package/include/file-scaner.js +74 -95
- package/include/file-scaner.js.map +1 -1
- package/include/file.cjs +78 -60
- package/include/file.cjs.map +1 -1
- package/include/file.js +78 -61
- package/include/file.js.map +1 -1
- package/index.cjs +1 -1
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/readme.md +312 -312
- package/server/Base.cjs +105 -105
- package/server/Base.cjs.map +1 -1
- package/server/Base.d.ts +20 -20
- package/server/Base.js +105 -105
- package/server/Base.js.map +1 -1
- package/server/Router.cjs +29 -29
- package/server/Router.cjs.map +1 -1
- package/server/Router.d.ts +7 -7
- package/server/Router.js +29 -29
- package/server/Router.js.map +1 -1
- package/server/index.cjs +185 -187
- package/server/index.cjs.map +1 -1
- package/server/index.d.ts +5 -5
- package/server/index.js +186 -188
- package/server/index.js.map +1 -1
- package/server/types.d.ts +72 -72
package/server/Base.cjs
CHANGED
|
@@ -3,111 +3,111 @@
|
|
|
3
3
|
var crypto = require('../include/crypto.cjs');
|
|
4
4
|
var Router = require('./Router.cjs');
|
|
5
5
|
|
|
6
|
-
class SecurequServerBase extends Router {
|
|
7
|
-
constructor(config) {
|
|
8
|
-
super();
|
|
9
|
-
this.secret = null;
|
|
10
|
-
this.clients = new Map();
|
|
11
|
-
this.uploadMeta = new Map();
|
|
12
|
-
this.CONTENT_TYPE = "application/octet-stream";
|
|
13
|
-
if (!config.basepath)
|
|
14
|
-
throw new Error("Basepath is required");
|
|
15
|
-
if (!config.clients || Object.keys(config.clients).length === 0)
|
|
16
|
-
throw new Error("Atleast one client is required");
|
|
17
|
-
if (!config.basepath.startsWith("/"))
|
|
18
|
-
config.basepath = `/${config.basepath}`;
|
|
19
|
-
if (config.basepath.endsWith("/"))
|
|
20
|
-
config.basepath = config.basepath.substring(0, config.basepath.length - 1);
|
|
21
|
-
if (config.file) {
|
|
22
|
-
config.file.maxFilesize = config.file.maxFilesize || 50 * 1024; // 50MB default
|
|
23
|
-
config.file.checkFileType = config.file.checkFileType || true;
|
|
24
|
-
}
|
|
25
|
-
config.mode = ["production", 'development'].includes(config.mode || "") ? config.mode : "production";
|
|
26
|
-
this.config = config;
|
|
27
|
-
for (let client of this.config.clients) {
|
|
28
|
-
this.clients.set(client.origin, client.secret);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
async getSecret() {
|
|
32
|
-
if (!this.secret) {
|
|
33
|
-
this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15));
|
|
34
|
-
}
|
|
35
|
-
return this.secret;
|
|
36
|
-
}
|
|
37
|
-
async clientInfo(path, origin) {
|
|
38
|
-
const isDev = path !== '/' && this.config.mode === 'development';
|
|
39
|
-
let splitUrl = path.split("?");
|
|
40
|
-
path = splitUrl[0];
|
|
41
|
-
path = path.replace(this.config.basepath + "/", "");
|
|
42
|
-
path = path.endsWith('/') ? path.substring(0, path.length - 1) : path;
|
|
43
|
-
path = path.startsWith('/') ? path.substring(1) : path;
|
|
44
|
-
const split = path.split("/");
|
|
45
|
-
const hash = split.shift();
|
|
46
|
-
let client = this.clients.get(origin);
|
|
47
|
-
if (!client) {
|
|
48
|
-
client = this.clients.get("*");
|
|
49
|
-
}
|
|
50
|
-
if (!(hash === null || hash === void 0 ? void 0 : hash.length) || !client) {
|
|
51
|
-
throw new Response("Invalid client", { status: 403 });
|
|
52
|
-
}
|
|
53
|
-
let secret = client.substring(0, hash.length);
|
|
54
|
-
let searchParams = {};
|
|
55
|
-
if (splitUrl.length > 1) {
|
|
56
|
-
const uparams = new URLSearchParams(decodeURIComponent(splitUrl[1]));
|
|
57
|
-
if (isDev) {
|
|
58
|
-
searchParams = Object.fromEntries(uparams);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
const keys = Array.from(uparams.keys());
|
|
62
|
-
if (keys.length) {
|
|
63
|
-
const key = keys[0];
|
|
64
|
-
const value = uparams.get(key);
|
|
65
|
-
const decrypted = await crypto.decrypt(value, secret);
|
|
66
|
-
if (decrypted && decrypted.key === key) {
|
|
67
|
-
searchParams = decrypted.params || {};
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
path: "/" + split.join('/'),
|
|
74
|
-
secret,
|
|
75
|
-
hash,
|
|
76
|
-
searchParams
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
async isValidSigneture(signeture, hash) {
|
|
80
|
-
const serverSecret = await this.getSecret();
|
|
81
|
-
if (this.secret && signeture) {
|
|
82
|
-
let info = await crypto.decrypt(signeture, serverSecret);
|
|
83
|
-
if (!info)
|
|
84
|
-
throw new Response("Invalid Signeture", { status: 403 });
|
|
85
|
-
let isHashValid = info.hash === hash;
|
|
86
|
-
let isNotExpired = info.expire > Date.now();
|
|
87
|
-
if (!isHashValid)
|
|
88
|
-
throw new Response("Invalid Signeture", { status: 403 });
|
|
89
|
-
if (!isNotExpired)
|
|
90
|
-
throw new Response("Signeture expired", { status: 403 });
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
throw new Response("Invalid Signeture", { status: 403 });
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
async handleRequest(info, metadata) {
|
|
97
|
-
if (this.config.accept) {
|
|
98
|
-
const is = await this.config.accept(info, metadata);
|
|
99
|
-
if (!is)
|
|
100
|
-
throw new Response("Request not accepted", { status: 403 });
|
|
101
|
-
}
|
|
102
|
-
const { path, method } = info;
|
|
103
|
-
let values = Object.values(this.routes[method]);
|
|
104
|
-
for (let { test, handler } of values) {
|
|
105
|
-
const match = test(path);
|
|
106
|
-
if (match) {
|
|
107
|
-
await handler(Object.assign(Object.assign({}, info), { params: match.params }), metadata);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
6
|
+
class SecurequServerBase extends Router {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
super();
|
|
9
|
+
this.secret = null;
|
|
10
|
+
this.clients = new Map();
|
|
11
|
+
this.uploadMeta = new Map();
|
|
12
|
+
this.CONTENT_TYPE = "application/octet-stream";
|
|
13
|
+
if (!config.basepath)
|
|
14
|
+
throw new Error("Basepath is required");
|
|
15
|
+
if (!config.clients || Object.keys(config.clients).length === 0)
|
|
16
|
+
throw new Error("Atleast one client is required");
|
|
17
|
+
if (!config.basepath.startsWith("/"))
|
|
18
|
+
config.basepath = `/${config.basepath}`;
|
|
19
|
+
if (config.basepath.endsWith("/"))
|
|
20
|
+
config.basepath = config.basepath.substring(0, config.basepath.length - 1);
|
|
21
|
+
if (config.file) {
|
|
22
|
+
config.file.maxFilesize = config.file.maxFilesize || 50 * 1024; // 50MB default
|
|
23
|
+
config.file.checkFileType = config.file.checkFileType || true;
|
|
24
|
+
}
|
|
25
|
+
config.mode = ["production", 'development'].includes(config.mode || "") ? config.mode : "production";
|
|
26
|
+
this.config = config;
|
|
27
|
+
for (let client of this.config.clients) {
|
|
28
|
+
this.clients.set(client.origin, client.secret);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async getSecret() {
|
|
32
|
+
if (!this.secret) {
|
|
33
|
+
this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15));
|
|
34
|
+
}
|
|
35
|
+
return this.secret;
|
|
36
|
+
}
|
|
37
|
+
async clientInfo(path, origin) {
|
|
38
|
+
const isDev = path !== '/' && this.config.mode === 'development';
|
|
39
|
+
let splitUrl = path.split("?");
|
|
40
|
+
path = splitUrl[0];
|
|
41
|
+
path = path.replace(this.config.basepath + "/", "");
|
|
42
|
+
path = path.endsWith('/') ? path.substring(0, path.length - 1) : path;
|
|
43
|
+
path = path.startsWith('/') ? path.substring(1) : path;
|
|
44
|
+
const split = path.split("/");
|
|
45
|
+
const hash = split.shift();
|
|
46
|
+
let client = this.clients.get(origin);
|
|
47
|
+
if (!client) {
|
|
48
|
+
client = this.clients.get("*");
|
|
49
|
+
}
|
|
50
|
+
if (!(hash === null || hash === void 0 ? void 0 : hash.length) || !client) {
|
|
51
|
+
throw new Response("Invalid client", { status: 403 });
|
|
52
|
+
}
|
|
53
|
+
let secret = client.substring(0, hash.length);
|
|
54
|
+
let searchParams = {};
|
|
55
|
+
if (splitUrl.length > 1) {
|
|
56
|
+
const uparams = new URLSearchParams(decodeURIComponent(splitUrl[1]));
|
|
57
|
+
if (isDev) {
|
|
58
|
+
searchParams = Object.fromEntries(uparams);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const keys = Array.from(uparams.keys());
|
|
62
|
+
if (keys.length) {
|
|
63
|
+
const key = keys[0];
|
|
64
|
+
const value = uparams.get(key);
|
|
65
|
+
const decrypted = await crypto.decrypt(value, secret);
|
|
66
|
+
if (decrypted && decrypted.key === key) {
|
|
67
|
+
searchParams = decrypted.params || {};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
path: "/" + split.join('/'),
|
|
74
|
+
secret,
|
|
75
|
+
hash,
|
|
76
|
+
searchParams
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
async isValidSigneture(signeture, hash) {
|
|
80
|
+
const serverSecret = await this.getSecret();
|
|
81
|
+
if (this.secret && signeture) {
|
|
82
|
+
let info = await crypto.decrypt(signeture, serverSecret);
|
|
83
|
+
if (!info)
|
|
84
|
+
throw new Response("Invalid Signeture", { status: 403 });
|
|
85
|
+
let isHashValid = info.hash === hash;
|
|
86
|
+
let isNotExpired = info.expire > Date.now();
|
|
87
|
+
if (!isHashValid)
|
|
88
|
+
throw new Response("Invalid Signeture", { status: 403 });
|
|
89
|
+
if (!isNotExpired)
|
|
90
|
+
throw new Response("Signeture expired", { status: 403 });
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
throw new Response("Invalid Signeture", { status: 403 });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async handleRequest(info, metadata) {
|
|
97
|
+
if (this.config.accept) {
|
|
98
|
+
const is = await this.config.accept(info, metadata);
|
|
99
|
+
if (!is)
|
|
100
|
+
throw new Response("Request not accepted", { status: 403 });
|
|
101
|
+
}
|
|
102
|
+
const { path, method } = info;
|
|
103
|
+
let values = Object.values(this.routes[method]);
|
|
104
|
+
for (let { test, handler } of values) {
|
|
105
|
+
const match = test(path);
|
|
106
|
+
if (match) {
|
|
107
|
+
await handler(Object.assign(Object.assign({}, info), { params: match.params }), metadata);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
module.exports = SecurequServerBase;
|
package/server/Base.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Base.cjs","sources":["../../src/server/Base.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\r\nimport Router from \"./Router\";\r\nimport { HandlerInfo, SecurequServerConfig, ServerClientSecret, ServerClientOrigin, UploadFileMeta, Metadata } from \"./types\";\r\n\r\nclass SecurequServerBase extends Router {\r\n protected config: SecurequServerConfig;\r\n protected secret: string | null = null\r\n protected clients = new Map<ServerClientOrigin, ServerClientSecret>();\r\n protected uploadMeta = new Map<string, UploadFileMeta & { expire: number }>();\r\n readonly CONTENT_TYPE = \"application/octet-stream\";\r\n\r\n constructor(config: SecurequServerConfig) {\r\n super()\r\n if (!config.basepath) throw new Error(\"Basepath is required\");\r\n if (!config.clients || Object.keys(config.clients).length === 0) throw new Error(\"Atleast one client is required\");\r\n if (!config.basepath.startsWith(\"/\")) config.basepath = `/${config.basepath}`;\r\n if (config.basepath.endsWith(\"/\")) config.basepath = config.basepath.substring(0, config.basepath.length - 1);\r\n if (config.file) {\r\n config.file.maxFilesize = config.file.maxFilesize || 50 * 1024 // 50MB default\r\n config.file.checkFileType = config.file.checkFileType || true\r\n }\r\n config.mode = [\"production\", 'development'].includes(config.mode || \"\") ? config.mode : \"production\"\r\n this.config = config\r\n for (let client of this.config.clients) {\r\n this.clients.set(client.origin, client.secret)\r\n }\r\n }\r\n\r\n protected async getSecret() {\r\n if (!this.secret) {\r\n this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15))\r\n }\r\n return this.secret\r\n }\r\n\r\n protected async clientInfo(path: string, origin: string) {\r\n const isDev = path !== '/' && this.config.mode === 'development'\r\n let splitUrl = path.split(\"?\")\r\n path = splitUrl[0]\r\n path = path.replace(this.config.basepath + \"/\", \"\")\r\n path = path.endsWith('/') ? path.substring(0, path.length - 1) : path\r\n path = path.startsWith('/') ? path.substring(1) : path\r\n\r\n const split = path.split(\"/\")\r\n const hash = split.shift()\r\n let client = this.clients.get(origin)\r\n if (!client) {\r\n client = this.clients.get(\"*\")\r\n }\r\n\r\n if (!hash?.length || !client) {\r\n throw new Response(\"Invalid client\", { status: 403 });\r\n }\r\n\r\n let secret = client.substring(0, hash.length);\r\n let searchParams: { [key: string]: any } = {}\r\n if (splitUrl.length > 1) {\r\n const uparams = new URLSearchParams(decodeURIComponent(splitUrl[1]))\r\n if (isDev) {\r\n searchParams = Object.fromEntries(uparams)\r\n } else {\r\n const keys = Array.from(uparams.keys());\r\n if (keys.length) {\r\n const key = keys[0]\r\n const value = uparams.get(key) as string;\r\n const decrypted: any = await crypto.decrypt(value, secret)\r\n if (decrypted && decrypted.key === key) {\r\n searchParams = decrypted.params || {}\r\n }\r\n }\r\n }\r\n }\r\n return {\r\n path: \"/\" + split.join('/'),\r\n secret,\r\n hash,\r\n searchParams\r\n }\r\n }\r\n\r\n protected async isValidSigneture(signeture: string | undefined, hash: string) {\r\n const serverSecret = await this.getSecret()\r\n if (this.secret && signeture) {\r\n let info: any = await crypto.decrypt(signeture, serverSecret)\r\n if (!info) throw new Response(\"Invalid Signeture\", { status: 403 });\r\n let isHashValid = info.hash === hash\r\n let isNotExpired = info.expire > Date.now()\r\n if (!isHashValid) throw new Response(\"Invalid Signeture\", { status: 403 });\r\n if (!isNotExpired) throw new Response(\"Signeture expired\", { status: 403 });\r\n } else {\r\n throw new Response(\"Invalid Signeture\", { status: 403 });\r\n }\r\n }\r\n\r\n async handleRequest(info: HandlerInfo, metadata?: Metadata) {\r\n if (this.config.accept) {\r\n const is = await this.config.accept(info, metadata)\r\n if (!is) throw new Response(\"Request not accepted\", { status: 403 })\r\n }\r\n\r\n const { path, method } = info;\r\n let values: any = Object.values(this.routes[method]);\r\n for (let { test, handler } of values) {\r\n const match = test(path)\r\n if (match) {\r\n await handler({ ...info, params: match.params }, metadata)\r\n }\r\n }\r\n }\r\n\r\n}\r\n\r\nexport default SecurequServerBase;"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Base.cjs","sources":["../../src/server/Base.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\nimport Router from \"./Router\";\nimport { HandlerInfo, SecurequServerConfig, ServerClientSecret, ServerClientOrigin, UploadFileMeta, Metadata } from \"./types\";\n\nclass SecurequServerBase extends Router {\n protected config: SecurequServerConfig;\n protected secret: string | null = null\n protected clients = new Map<ServerClientOrigin, ServerClientSecret>();\n protected uploadMeta = new Map<string, UploadFileMeta & { expire: number }>();\n readonly CONTENT_TYPE = \"application/octet-stream\";\n\n constructor(config: SecurequServerConfig) {\n super()\n if (!config.basepath) throw new Error(\"Basepath is required\");\n if (!config.clients || Object.keys(config.clients).length === 0) throw new Error(\"Atleast one client is required\");\n if (!config.basepath.startsWith(\"/\")) config.basepath = `/${config.basepath}`;\n if (config.basepath.endsWith(\"/\")) config.basepath = config.basepath.substring(0, config.basepath.length - 1);\n if (config.file) {\n config.file.maxFilesize = config.file.maxFilesize || 50 * 1024 // 50MB default\n config.file.checkFileType = config.file.checkFileType || true\n }\n config.mode = [\"production\", 'development'].includes(config.mode || \"\") ? config.mode : \"production\"\n this.config = config\n for (let client of this.config.clients) {\n this.clients.set(client.origin, client.secret)\n }\n }\n\n protected async getSecret() {\n if (!this.secret) {\n this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15))\n }\n return this.secret\n }\n\n protected async clientInfo(path: string, origin: string) {\n const isDev = path !== '/' && this.config.mode === 'development'\n let splitUrl = path.split(\"?\")\n path = splitUrl[0]\n path = path.replace(this.config.basepath + \"/\", \"\")\n path = path.endsWith('/') ? path.substring(0, path.length - 1) : path\n path = path.startsWith('/') ? path.substring(1) : path\n\n const split = path.split(\"/\")\n const hash = split.shift()\n let client = this.clients.get(origin)\n if (!client) {\n client = this.clients.get(\"*\")\n }\n\n if (!hash?.length || !client) {\n throw new Response(\"Invalid client\", { status: 403 });\n }\n\n let secret = client.substring(0, hash.length);\n let searchParams: { [key: string]: any } = {}\n if (splitUrl.length > 1) {\n const uparams = new URLSearchParams(decodeURIComponent(splitUrl[1]))\n if (isDev) {\n searchParams = Object.fromEntries(uparams)\n } else {\n const keys = Array.from(uparams.keys());\n if (keys.length) {\n const key = keys[0]\n const value = uparams.get(key) as string;\n const decrypted: any = await crypto.decrypt(value, secret)\n if (decrypted && decrypted.key === key) {\n searchParams = decrypted.params || {}\n }\n }\n }\n }\n return {\n path: \"/\" + split.join('/'),\n secret,\n hash,\n searchParams\n }\n }\n\n protected async isValidSigneture(signeture: string | undefined, hash: string) {\n const serverSecret = await this.getSecret()\n if (this.secret && signeture) {\n let info: any = await crypto.decrypt(signeture, serverSecret)\n if (!info) throw new Response(\"Invalid Signeture\", { status: 403 });\n let isHashValid = info.hash === hash\n let isNotExpired = info.expire > Date.now()\n if (!isHashValid) throw new Response(\"Invalid Signeture\", { status: 403 });\n if (!isNotExpired) throw new Response(\"Signeture expired\", { status: 403 });\n } else {\n throw new Response(\"Invalid Signeture\", { status: 403 });\n }\n }\n\n async handleRequest(info: HandlerInfo, metadata?: Metadata) {\n if (this.config.accept) {\n const is = await this.config.accept(info, metadata)\n if (!is) throw new Response(\"Request not accepted\", { status: 403 })\n }\n\n const { path, method } = info;\n let values: any = Object.values(this.routes[method]);\n for (let { test, handler } of values) {\n const match = test(path)\n if (match) {\n await handler({ ...info, params: match.params }, metadata)\n }\n }\n }\n\n}\n\nexport default SecurequServerBase;"],"names":[],"mappings":"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"}
|
package/server/Base.d.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import Router from './Router.js';
|
|
2
2
|
import { SecurequServerConfig, UploadFileMeta, HandlerInfo, Metadata } from './types.js';
|
|
3
3
|
|
|
4
|
-
declare class SecurequServerBase extends Router {
|
|
5
|
-
protected config: SecurequServerConfig;
|
|
6
|
-
protected secret: string | null;
|
|
7
|
-
protected clients: Map<string, string>;
|
|
8
|
-
protected uploadMeta: Map<string, UploadFileMeta & {
|
|
9
|
-
expire: number;
|
|
10
|
-
}>;
|
|
11
|
-
readonly CONTENT_TYPE = "application/octet-stream";
|
|
12
|
-
constructor(config: SecurequServerConfig);
|
|
13
|
-
protected getSecret(): Promise<string>;
|
|
14
|
-
protected clientInfo(path: string, origin: string): Promise<{
|
|
15
|
-
path: string;
|
|
16
|
-
secret: string;
|
|
17
|
-
hash: string;
|
|
18
|
-
searchParams: {
|
|
19
|
-
[key: string]: any;
|
|
20
|
-
};
|
|
21
|
-
}>;
|
|
22
|
-
protected isValidSigneture(signeture: string | undefined, hash: string): Promise<void>;
|
|
23
|
-
handleRequest(info: HandlerInfo, metadata?: Metadata): Promise<void>;
|
|
4
|
+
declare class SecurequServerBase extends Router {
|
|
5
|
+
protected config: SecurequServerConfig;
|
|
6
|
+
protected secret: string | null;
|
|
7
|
+
protected clients: Map<string, string>;
|
|
8
|
+
protected uploadMeta: Map<string, UploadFileMeta & {
|
|
9
|
+
expire: number;
|
|
10
|
+
}>;
|
|
11
|
+
readonly CONTENT_TYPE = "application/octet-stream";
|
|
12
|
+
constructor(config: SecurequServerConfig);
|
|
13
|
+
protected getSecret(): Promise<string>;
|
|
14
|
+
protected clientInfo(path: string, origin: string): Promise<{
|
|
15
|
+
path: string;
|
|
16
|
+
secret: string;
|
|
17
|
+
hash: string;
|
|
18
|
+
searchParams: {
|
|
19
|
+
[key: string]: any;
|
|
20
|
+
};
|
|
21
|
+
}>;
|
|
22
|
+
protected isValidSigneture(signeture: string | undefined, hash: string): Promise<void>;
|
|
23
|
+
handleRequest(info: HandlerInfo, metadata?: Metadata): Promise<void>;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export { SecurequServerBase as default };
|
package/server/Base.js
CHANGED
|
@@ -1,111 +1,111 @@
|
|
|
1
1
|
import crypto from '../include/crypto.js';
|
|
2
2
|
import Router from './Router.js';
|
|
3
3
|
|
|
4
|
-
class SecurequServerBase extends Router {
|
|
5
|
-
constructor(config) {
|
|
6
|
-
super();
|
|
7
|
-
this.secret = null;
|
|
8
|
-
this.clients = new Map();
|
|
9
|
-
this.uploadMeta = new Map();
|
|
10
|
-
this.CONTENT_TYPE = "application/octet-stream";
|
|
11
|
-
if (!config.basepath)
|
|
12
|
-
throw new Error("Basepath is required");
|
|
13
|
-
if (!config.clients || Object.keys(config.clients).length === 0)
|
|
14
|
-
throw new Error("Atleast one client is required");
|
|
15
|
-
if (!config.basepath.startsWith("/"))
|
|
16
|
-
config.basepath = `/${config.basepath}`;
|
|
17
|
-
if (config.basepath.endsWith("/"))
|
|
18
|
-
config.basepath = config.basepath.substring(0, config.basepath.length - 1);
|
|
19
|
-
if (config.file) {
|
|
20
|
-
config.file.maxFilesize = config.file.maxFilesize || 50 * 1024; // 50MB default
|
|
21
|
-
config.file.checkFileType = config.file.checkFileType || true;
|
|
22
|
-
}
|
|
23
|
-
config.mode = ["production", 'development'].includes(config.mode || "") ? config.mode : "production";
|
|
24
|
-
this.config = config;
|
|
25
|
-
for (let client of this.config.clients) {
|
|
26
|
-
this.clients.set(client.origin, client.secret);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
async getSecret() {
|
|
30
|
-
if (!this.secret) {
|
|
31
|
-
this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15));
|
|
32
|
-
}
|
|
33
|
-
return this.secret;
|
|
34
|
-
}
|
|
35
|
-
async clientInfo(path, origin) {
|
|
36
|
-
const isDev = path !== '/' && this.config.mode === 'development';
|
|
37
|
-
let splitUrl = path.split("?");
|
|
38
|
-
path = splitUrl[0];
|
|
39
|
-
path = path.replace(this.config.basepath + "/", "");
|
|
40
|
-
path = path.endsWith('/') ? path.substring(0, path.length - 1) : path;
|
|
41
|
-
path = path.startsWith('/') ? path.substring(1) : path;
|
|
42
|
-
const split = path.split("/");
|
|
43
|
-
const hash = split.shift();
|
|
44
|
-
let client = this.clients.get(origin);
|
|
45
|
-
if (!client) {
|
|
46
|
-
client = this.clients.get("*");
|
|
47
|
-
}
|
|
48
|
-
if (!(hash === null || hash === void 0 ? void 0 : hash.length) || !client) {
|
|
49
|
-
throw new Response("Invalid client", { status: 403 });
|
|
50
|
-
}
|
|
51
|
-
let secret = client.substring(0, hash.length);
|
|
52
|
-
let searchParams = {};
|
|
53
|
-
if (splitUrl.length > 1) {
|
|
54
|
-
const uparams = new URLSearchParams(decodeURIComponent(splitUrl[1]));
|
|
55
|
-
if (isDev) {
|
|
56
|
-
searchParams = Object.fromEntries(uparams);
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
const keys = Array.from(uparams.keys());
|
|
60
|
-
if (keys.length) {
|
|
61
|
-
const key = keys[0];
|
|
62
|
-
const value = uparams.get(key);
|
|
63
|
-
const decrypted = await crypto.decrypt(value, secret);
|
|
64
|
-
if (decrypted && decrypted.key === key) {
|
|
65
|
-
searchParams = decrypted.params || {};
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return {
|
|
71
|
-
path: "/" + split.join('/'),
|
|
72
|
-
secret,
|
|
73
|
-
hash,
|
|
74
|
-
searchParams
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
async isValidSigneture(signeture, hash) {
|
|
78
|
-
const serverSecret = await this.getSecret();
|
|
79
|
-
if (this.secret && signeture) {
|
|
80
|
-
let info = await crypto.decrypt(signeture, serverSecret);
|
|
81
|
-
if (!info)
|
|
82
|
-
throw new Response("Invalid Signeture", { status: 403 });
|
|
83
|
-
let isHashValid = info.hash === hash;
|
|
84
|
-
let isNotExpired = info.expire > Date.now();
|
|
85
|
-
if (!isHashValid)
|
|
86
|
-
throw new Response("Invalid Signeture", { status: 403 });
|
|
87
|
-
if (!isNotExpired)
|
|
88
|
-
throw new Response("Signeture expired", { status: 403 });
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
throw new Response("Invalid Signeture", { status: 403 });
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
async handleRequest(info, metadata) {
|
|
95
|
-
if (this.config.accept) {
|
|
96
|
-
const is = await this.config.accept(info, metadata);
|
|
97
|
-
if (!is)
|
|
98
|
-
throw new Response("Request not accepted", { status: 403 });
|
|
99
|
-
}
|
|
100
|
-
const { path, method } = info;
|
|
101
|
-
let values = Object.values(this.routes[method]);
|
|
102
|
-
for (let { test, handler } of values) {
|
|
103
|
-
const match = test(path);
|
|
104
|
-
if (match) {
|
|
105
|
-
await handler(Object.assign(Object.assign({}, info), { params: match.params }), metadata);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
4
|
+
class SecurequServerBase extends Router {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
super();
|
|
7
|
+
this.secret = null;
|
|
8
|
+
this.clients = new Map();
|
|
9
|
+
this.uploadMeta = new Map();
|
|
10
|
+
this.CONTENT_TYPE = "application/octet-stream";
|
|
11
|
+
if (!config.basepath)
|
|
12
|
+
throw new Error("Basepath is required");
|
|
13
|
+
if (!config.clients || Object.keys(config.clients).length === 0)
|
|
14
|
+
throw new Error("Atleast one client is required");
|
|
15
|
+
if (!config.basepath.startsWith("/"))
|
|
16
|
+
config.basepath = `/${config.basepath}`;
|
|
17
|
+
if (config.basepath.endsWith("/"))
|
|
18
|
+
config.basepath = config.basepath.substring(0, config.basepath.length - 1);
|
|
19
|
+
if (config.file) {
|
|
20
|
+
config.file.maxFilesize = config.file.maxFilesize || 50 * 1024; // 50MB default
|
|
21
|
+
config.file.checkFileType = config.file.checkFileType || true;
|
|
22
|
+
}
|
|
23
|
+
config.mode = ["production", 'development'].includes(config.mode || "") ? config.mode : "production";
|
|
24
|
+
this.config = config;
|
|
25
|
+
for (let client of this.config.clients) {
|
|
26
|
+
this.clients.set(client.origin, client.secret);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async getSecret() {
|
|
30
|
+
if (!this.secret) {
|
|
31
|
+
this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15));
|
|
32
|
+
}
|
|
33
|
+
return this.secret;
|
|
34
|
+
}
|
|
35
|
+
async clientInfo(path, origin) {
|
|
36
|
+
const isDev = path !== '/' && this.config.mode === 'development';
|
|
37
|
+
let splitUrl = path.split("?");
|
|
38
|
+
path = splitUrl[0];
|
|
39
|
+
path = path.replace(this.config.basepath + "/", "");
|
|
40
|
+
path = path.endsWith('/') ? path.substring(0, path.length - 1) : path;
|
|
41
|
+
path = path.startsWith('/') ? path.substring(1) : path;
|
|
42
|
+
const split = path.split("/");
|
|
43
|
+
const hash = split.shift();
|
|
44
|
+
let client = this.clients.get(origin);
|
|
45
|
+
if (!client) {
|
|
46
|
+
client = this.clients.get("*");
|
|
47
|
+
}
|
|
48
|
+
if (!(hash === null || hash === void 0 ? void 0 : hash.length) || !client) {
|
|
49
|
+
throw new Response("Invalid client", { status: 403 });
|
|
50
|
+
}
|
|
51
|
+
let secret = client.substring(0, hash.length);
|
|
52
|
+
let searchParams = {};
|
|
53
|
+
if (splitUrl.length > 1) {
|
|
54
|
+
const uparams = new URLSearchParams(decodeURIComponent(splitUrl[1]));
|
|
55
|
+
if (isDev) {
|
|
56
|
+
searchParams = Object.fromEntries(uparams);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const keys = Array.from(uparams.keys());
|
|
60
|
+
if (keys.length) {
|
|
61
|
+
const key = keys[0];
|
|
62
|
+
const value = uparams.get(key);
|
|
63
|
+
const decrypted = await crypto.decrypt(value, secret);
|
|
64
|
+
if (decrypted && decrypted.key === key) {
|
|
65
|
+
searchParams = decrypted.params || {};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
path: "/" + split.join('/'),
|
|
72
|
+
secret,
|
|
73
|
+
hash,
|
|
74
|
+
searchParams
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async isValidSigneture(signeture, hash) {
|
|
78
|
+
const serverSecret = await this.getSecret();
|
|
79
|
+
if (this.secret && signeture) {
|
|
80
|
+
let info = await crypto.decrypt(signeture, serverSecret);
|
|
81
|
+
if (!info)
|
|
82
|
+
throw new Response("Invalid Signeture", { status: 403 });
|
|
83
|
+
let isHashValid = info.hash === hash;
|
|
84
|
+
let isNotExpired = info.expire > Date.now();
|
|
85
|
+
if (!isHashValid)
|
|
86
|
+
throw new Response("Invalid Signeture", { status: 403 });
|
|
87
|
+
if (!isNotExpired)
|
|
88
|
+
throw new Response("Signeture expired", { status: 403 });
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
throw new Response("Invalid Signeture", { status: 403 });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async handleRequest(info, metadata) {
|
|
95
|
+
if (this.config.accept) {
|
|
96
|
+
const is = await this.config.accept(info, metadata);
|
|
97
|
+
if (!is)
|
|
98
|
+
throw new Response("Request not accepted", { status: 403 });
|
|
99
|
+
}
|
|
100
|
+
const { path, method } = info;
|
|
101
|
+
let values = Object.values(this.routes[method]);
|
|
102
|
+
for (let { test, handler } of values) {
|
|
103
|
+
const match = test(path);
|
|
104
|
+
if (match) {
|
|
105
|
+
await handler(Object.assign(Object.assign({}, info), { params: match.params }), metadata);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
export { SecurequServerBase as default };
|
package/server/Base.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Base.js","sources":["../../src/server/Base.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\r\nimport Router from \"./Router\";\r\nimport { HandlerInfo, SecurequServerConfig, ServerClientSecret, ServerClientOrigin, UploadFileMeta, Metadata } from \"./types\";\r\n\r\nclass SecurequServerBase extends Router {\r\n protected config: SecurequServerConfig;\r\n protected secret: string | null = null\r\n protected clients = new Map<ServerClientOrigin, ServerClientSecret>();\r\n protected uploadMeta = new Map<string, UploadFileMeta & { expire: number }>();\r\n readonly CONTENT_TYPE = \"application/octet-stream\";\r\n\r\n constructor(config: SecurequServerConfig) {\r\n super()\r\n if (!config.basepath) throw new Error(\"Basepath is required\");\r\n if (!config.clients || Object.keys(config.clients).length === 0) throw new Error(\"Atleast one client is required\");\r\n if (!config.basepath.startsWith(\"/\")) config.basepath = `/${config.basepath}`;\r\n if (config.basepath.endsWith(\"/\")) config.basepath = config.basepath.substring(0, config.basepath.length - 1);\r\n if (config.file) {\r\n config.file.maxFilesize = config.file.maxFilesize || 50 * 1024 // 50MB default\r\n config.file.checkFileType = config.file.checkFileType || true\r\n }\r\n config.mode = [\"production\", 'development'].includes(config.mode || \"\") ? config.mode : \"production\"\r\n this.config = config\r\n for (let client of this.config.clients) {\r\n this.clients.set(client.origin, client.secret)\r\n }\r\n }\r\n\r\n protected async getSecret() {\r\n if (!this.secret) {\r\n this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15))\r\n }\r\n return this.secret\r\n }\r\n\r\n protected async clientInfo(path: string, origin: string) {\r\n const isDev = path !== '/' && this.config.mode === 'development'\r\n let splitUrl = path.split(\"?\")\r\n path = splitUrl[0]\r\n path = path.replace(this.config.basepath + \"/\", \"\")\r\n path = path.endsWith('/') ? path.substring(0, path.length - 1) : path\r\n path = path.startsWith('/') ? path.substring(1) : path\r\n\r\n const split = path.split(\"/\")\r\n const hash = split.shift()\r\n let client = this.clients.get(origin)\r\n if (!client) {\r\n client = this.clients.get(\"*\")\r\n }\r\n\r\n if (!hash?.length || !client) {\r\n throw new Response(\"Invalid client\", { status: 403 });\r\n }\r\n\r\n let secret = client.substring(0, hash.length);\r\n let searchParams: { [key: string]: any } = {}\r\n if (splitUrl.length > 1) {\r\n const uparams = new URLSearchParams(decodeURIComponent(splitUrl[1]))\r\n if (isDev) {\r\n searchParams = Object.fromEntries(uparams)\r\n } else {\r\n const keys = Array.from(uparams.keys());\r\n if (keys.length) {\r\n const key = keys[0]\r\n const value = uparams.get(key) as string;\r\n const decrypted: any = await crypto.decrypt(value, secret)\r\n if (decrypted && decrypted.key === key) {\r\n searchParams = decrypted.params || {}\r\n }\r\n }\r\n }\r\n }\r\n return {\r\n path: \"/\" + split.join('/'),\r\n secret,\r\n hash,\r\n searchParams\r\n }\r\n }\r\n\r\n protected async isValidSigneture(signeture: string | undefined, hash: string) {\r\n const serverSecret = await this.getSecret()\r\n if (this.secret && signeture) {\r\n let info: any = await crypto.decrypt(signeture, serverSecret)\r\n if (!info) throw new Response(\"Invalid Signeture\", { status: 403 });\r\n let isHashValid = info.hash === hash\r\n let isNotExpired = info.expire > Date.now()\r\n if (!isHashValid) throw new Response(\"Invalid Signeture\", { status: 403 });\r\n if (!isNotExpired) throw new Response(\"Signeture expired\", { status: 403 });\r\n } else {\r\n throw new Response(\"Invalid Signeture\", { status: 403 });\r\n }\r\n }\r\n\r\n async handleRequest(info: HandlerInfo, metadata?: Metadata) {\r\n if (this.config.accept) {\r\n const is = await this.config.accept(info, metadata)\r\n if (!is) throw new Response(\"Request not accepted\", { status: 403 })\r\n }\r\n\r\n const { path, method } = info;\r\n let values: any = Object.values(this.routes[method]);\r\n for (let { test, handler } of values) {\r\n const match = test(path)\r\n if (match) {\r\n await handler({ ...info, params: match.params }, metadata)\r\n }\r\n }\r\n }\r\n\r\n}\r\n\r\nexport default SecurequServerBase;"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Base.js","sources":["../../src/server/Base.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\nimport Router from \"./Router\";\nimport { HandlerInfo, SecurequServerConfig, ServerClientSecret, ServerClientOrigin, UploadFileMeta, Metadata } from \"./types\";\n\nclass SecurequServerBase extends Router {\n protected config: SecurequServerConfig;\n protected secret: string | null = null\n protected clients = new Map<ServerClientOrigin, ServerClientSecret>();\n protected uploadMeta = new Map<string, UploadFileMeta & { expire: number }>();\n readonly CONTENT_TYPE = \"application/octet-stream\";\n\n constructor(config: SecurequServerConfig) {\n super()\n if (!config.basepath) throw new Error(\"Basepath is required\");\n if (!config.clients || Object.keys(config.clients).length === 0) throw new Error(\"Atleast one client is required\");\n if (!config.basepath.startsWith(\"/\")) config.basepath = `/${config.basepath}`;\n if (config.basepath.endsWith(\"/\")) config.basepath = config.basepath.substring(0, config.basepath.length - 1);\n if (config.file) {\n config.file.maxFilesize = config.file.maxFilesize || 50 * 1024 // 50MB default\n config.file.checkFileType = config.file.checkFileType || true\n }\n config.mode = [\"production\", 'development'].includes(config.mode || \"\") ? config.mode : \"production\"\n this.config = config\n for (let client of this.config.clients) {\n this.clients.set(client.origin, client.secret)\n }\n }\n\n protected async getSecret() {\n if (!this.secret) {\n this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15))\n }\n return this.secret\n }\n\n protected async clientInfo(path: string, origin: string) {\n const isDev = path !== '/' && this.config.mode === 'development'\n let splitUrl = path.split(\"?\")\n path = splitUrl[0]\n path = path.replace(this.config.basepath + \"/\", \"\")\n path = path.endsWith('/') ? path.substring(0, path.length - 1) : path\n path = path.startsWith('/') ? path.substring(1) : path\n\n const split = path.split(\"/\")\n const hash = split.shift()\n let client = this.clients.get(origin)\n if (!client) {\n client = this.clients.get(\"*\")\n }\n\n if (!hash?.length || !client) {\n throw new Response(\"Invalid client\", { status: 403 });\n }\n\n let secret = client.substring(0, hash.length);\n let searchParams: { [key: string]: any } = {}\n if (splitUrl.length > 1) {\n const uparams = new URLSearchParams(decodeURIComponent(splitUrl[1]))\n if (isDev) {\n searchParams = Object.fromEntries(uparams)\n } else {\n const keys = Array.from(uparams.keys());\n if (keys.length) {\n const key = keys[0]\n const value = uparams.get(key) as string;\n const decrypted: any = await crypto.decrypt(value, secret)\n if (decrypted && decrypted.key === key) {\n searchParams = decrypted.params || {}\n }\n }\n }\n }\n return {\n path: \"/\" + split.join('/'),\n secret,\n hash,\n searchParams\n }\n }\n\n protected async isValidSigneture(signeture: string | undefined, hash: string) {\n const serverSecret = await this.getSecret()\n if (this.secret && signeture) {\n let info: any = await crypto.decrypt(signeture, serverSecret)\n if (!info) throw new Response(\"Invalid Signeture\", { status: 403 });\n let isHashValid = info.hash === hash\n let isNotExpired = info.expire > Date.now()\n if (!isHashValid) throw new Response(\"Invalid Signeture\", { status: 403 });\n if (!isNotExpired) throw new Response(\"Signeture expired\", { status: 403 });\n } else {\n throw new Response(\"Invalid Signeture\", { status: 403 });\n }\n }\n\n async handleRequest(info: HandlerInfo, metadata?: Metadata) {\n if (this.config.accept) {\n const is = await this.config.accept(info, metadata)\n if (!is) throw new Response(\"Request not accepted\", { status: 403 })\n }\n\n const { path, method } = info;\n let values: any = Object.values(this.routes[method]);\n for (let { test, handler } of values) {\n const match = test(path)\n if (match) {\n await handler({ ...info, params: match.params }, metadata)\n }\n }\n }\n\n}\n\nexport default SecurequServerBase;"],"names":[],"mappings":"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"}
|
package/server/Router.cjs
CHANGED
|
@@ -2,35 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
var pathToRegexp = require('path-to-regexp');
|
|
4
4
|
|
|
5
|
-
class Router {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.routes = {
|
|
8
|
-
GET: {},
|
|
9
|
-
POST: {},
|
|
10
|
-
PUT: {},
|
|
11
|
-
DELETE: {}
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
async addRoute(path, method, handler) {
|
|
15
|
-
if (this.routes[method][path])
|
|
16
|
-
return;
|
|
17
|
-
this.routes[method][path] = {
|
|
18
|
-
handler,
|
|
19
|
-
test: pathToRegexp.match(path)
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
async get(path, handler) {
|
|
23
|
-
this.addRoute(path, 'GET', handler);
|
|
24
|
-
}
|
|
25
|
-
async post(path, handler) {
|
|
26
|
-
this.addRoute(path, 'POST', handler);
|
|
27
|
-
}
|
|
28
|
-
async put(path, handler) {
|
|
29
|
-
this.addRoute(path, 'PUT', handler);
|
|
30
|
-
}
|
|
31
|
-
async delete(path, handler) {
|
|
32
|
-
this.addRoute(path, 'DELETE', handler);
|
|
33
|
-
}
|
|
5
|
+
class Router {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.routes = {
|
|
8
|
+
GET: {},
|
|
9
|
+
POST: {},
|
|
10
|
+
PUT: {},
|
|
11
|
+
DELETE: {}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
async addRoute(path, method, handler) {
|
|
15
|
+
if (this.routes[method][path])
|
|
16
|
+
return;
|
|
17
|
+
this.routes[method][path] = {
|
|
18
|
+
handler,
|
|
19
|
+
test: pathToRegexp.match(path)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async get(path, handler) {
|
|
23
|
+
this.addRoute(path, 'GET', handler);
|
|
24
|
+
}
|
|
25
|
+
async post(path, handler) {
|
|
26
|
+
this.addRoute(path, 'POST', handler);
|
|
27
|
+
}
|
|
28
|
+
async put(path, handler) {
|
|
29
|
+
this.addRoute(path, 'PUT', handler);
|
|
30
|
+
}
|
|
31
|
+
async delete(path, handler) {
|
|
32
|
+
this.addRoute(path, 'DELETE', handler);
|
|
33
|
+
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
module.exports = Router;
|