@jwn-js/common 2.2.1 → 2.2.3
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/ApiError.js +37 -1
- package/ApiError.mjs +35 -1
- package/Jwt-B4QZ2Ypb.js +80 -0
- package/Jwt-Be4GWrIO.js +75 -0
- package/Jwt.js +8 -1
- package/Jwt.mjs +2 -1
- package/Memcached.js +166 -9
- package/Memcached.mjs +164 -9
- package/Server.js +316 -1
- package/Server.mjs +313 -1
- package/cookieParse.js +25 -1
- package/cookieParse.mjs +23 -1
- package/cookieString.js +22 -1
- package/cookieString.mjs +20 -1
- package/docs/classes/ApiError.html +2 -2
- package/docs/classes/AsyncJwt.html +2 -2
- package/docs/classes/Controller.html +2 -2
- package/docs/classes/Jwt.html +2 -2
- package/docs/classes/Memcached.html +2 -2
- package/docs/classes/Model.html +2 -2
- package/docs/classes/Server.html +2 -2
- package/docs/classes/Ssr.html +2 -2
- package/docs/classes/Web.html +2 -2
- package/docs/functions/action.html +2 -2
- package/docs/functions/body.html +2 -2
- package/docs/functions/codeToStatus.html +2 -2
- package/docs/functions/config.html +2 -2
- package/docs/functions/connection.html +2 -2
- package/docs/functions/context.html +2 -2
- package/docs/functions/controller-1.html +2 -2
- package/docs/functions/cookies.html +2 -2
- package/docs/functions/db.html +2 -2
- package/docs/functions/headers.html +2 -2
- package/docs/functions/home.html +2 -2
- package/docs/functions/hostname.html +2 -2
- package/docs/functions/http.html +2 -2
- package/docs/functions/init.html +2 -2
- package/docs/functions/json.html +2 -2
- package/docs/functions/logerror.html +2 -2
- package/docs/functions/method.html +2 -2
- package/docs/functions/mixin.html +2 -2
- package/docs/functions/mount.html +2 -2
- package/docs/functions/pool.html +2 -2
- package/docs/functions/protocol.html +2 -2
- package/docs/functions/request.html +2 -2
- package/docs/functions/selectControllersSchema.html +1 -1
- package/docs/functions/stream.html +2 -2
- package/docs/functions/subaction.html +2 -2
- package/docs/functions/url.html +2 -2
- package/docs/functions/xml.html +2 -2
- package/docs/index.html +2 -2
- package/docs/interfaces/ApiErrorMessage.html +2 -2
- package/docs/interfaces/ContextSsr.html +2 -2
- package/docs/interfaces/ContextWeb.html +2 -2
- package/docs/interfaces/OptionsSsr.html +2 -2
- package/docs/interfaces/OptionsWeb.html +2 -2
- package/docs/interfaces/ResponseOptions.html +2 -2
- package/docs/interfaces/Route.html +2 -2
- package/docs/interfaces/Schema.html +2 -2
- package/docs/interfaces/ServerHandler.html +2 -2
- package/docs/interfaces/ServerOptions.html +2 -2
- package/docs/interfaces/ServerWebsocket.html +2 -2
- package/docs/modules.html +2 -2
- package/docs/types/ServerRoutes.html +1 -1
- package/docs/variables/helpers.html +2 -2
- package/index.js +1473 -4
- package/index.mjs +1417 -4
- package/jsonBody.js +25 -1
- package/jsonBody.mjs +23 -1
- package/multipartBody.js +42 -1
- package/multipartBody.mjs +40 -1
- package/package.json +1 -1
- package/readConfig.js +11 -1
- package/readConfig.mjs +9 -1
- package/readConfigSync.js +11 -1
- package/readConfigSync.mjs +9 -1
- package/staticBody.js +205 -1
- package/staticBody.mjs +200 -1
- package/urlencodedBody.js +26 -1
- package/urlencodedBody.mjs +24 -1
- package/Jwt-7tQL-rwa.js +0 -1
- package/Jwt-CDdbxwvH.js +0 -1
package/ApiError.js
CHANGED
|
@@ -1 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
class ApiError extends Error {
|
|
4
|
+
constructor(params = "", code = 0, statusCode = 404) {
|
|
5
|
+
super();
|
|
6
|
+
let paramsObj = {};
|
|
7
|
+
if (typeof params === "string") {
|
|
8
|
+
paramsObj.message = params;
|
|
9
|
+
paramsObj.code = code;
|
|
10
|
+
paramsObj.statusCode = statusCode;
|
|
11
|
+
} else {
|
|
12
|
+
paramsObj = params;
|
|
13
|
+
}
|
|
14
|
+
this.statusCode = paramsObj.statusCode ?? 404;
|
|
15
|
+
this.code = paramsObj.code ?? 0;
|
|
16
|
+
this.message = paramsObj.message ?? "";
|
|
17
|
+
this.data = paramsObj.data ?? {};
|
|
18
|
+
this.headers = paramsObj.headers ?? {};
|
|
19
|
+
}
|
|
20
|
+
getMessage() {
|
|
21
|
+
return this.message;
|
|
22
|
+
}
|
|
23
|
+
getStatusCode() {
|
|
24
|
+
return this.statusCode;
|
|
25
|
+
}
|
|
26
|
+
getCode() {
|
|
27
|
+
return this.code;
|
|
28
|
+
}
|
|
29
|
+
getData() {
|
|
30
|
+
return this.data;
|
|
31
|
+
}
|
|
32
|
+
getHeaders() {
|
|
33
|
+
return this.headers;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
exports.ApiError = ApiError;
|
package/ApiError.mjs
CHANGED
|
@@ -1 +1,35 @@
|
|
|
1
|
-
class
|
|
1
|
+
class ApiError extends Error {
|
|
2
|
+
constructor(params = "", code = 0, statusCode = 404) {
|
|
3
|
+
super();
|
|
4
|
+
let paramsObj = {};
|
|
5
|
+
if (typeof params === "string") {
|
|
6
|
+
paramsObj.message = params;
|
|
7
|
+
paramsObj.code = code;
|
|
8
|
+
paramsObj.statusCode = statusCode;
|
|
9
|
+
} else {
|
|
10
|
+
paramsObj = params;
|
|
11
|
+
}
|
|
12
|
+
this.statusCode = paramsObj.statusCode ?? 404;
|
|
13
|
+
this.code = paramsObj.code ?? 0;
|
|
14
|
+
this.message = paramsObj.message ?? "";
|
|
15
|
+
this.data = paramsObj.data ?? {};
|
|
16
|
+
this.headers = paramsObj.headers ?? {};
|
|
17
|
+
}
|
|
18
|
+
getMessage() {
|
|
19
|
+
return this.message;
|
|
20
|
+
}
|
|
21
|
+
getStatusCode() {
|
|
22
|
+
return this.statusCode;
|
|
23
|
+
}
|
|
24
|
+
getCode() {
|
|
25
|
+
return this.code;
|
|
26
|
+
}
|
|
27
|
+
getData() {
|
|
28
|
+
return this.data;
|
|
29
|
+
}
|
|
30
|
+
getHeaders() {
|
|
31
|
+
return this.headers;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { ApiError };
|
package/Jwt-B4QZ2Ypb.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var crypto = require('crypto');
|
|
4
|
+
|
|
5
|
+
const urlEncode = (str) => {
|
|
6
|
+
return str.replace(/\+/ig, "-").replace(/\//ig, "_").replace(/=+$/, "");
|
|
7
|
+
};
|
|
8
|
+
const urlDecode = (str) => {
|
|
9
|
+
return str.replace(/-/ig, "+").replace(/_/ig, "/");
|
|
10
|
+
};
|
|
11
|
+
const toBase64url = (params) => {
|
|
12
|
+
return urlEncode(
|
|
13
|
+
Buffer.from(JSON.stringify(params)).toString("base64")
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
const fromBase64url = (str) => {
|
|
17
|
+
return JSON.parse(
|
|
18
|
+
Buffer.from(
|
|
19
|
+
urlDecode(str),
|
|
20
|
+
"base64"
|
|
21
|
+
).toString()
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
class Jwt {
|
|
26
|
+
/**
|
|
27
|
+
* @constructor
|
|
28
|
+
* @param secret
|
|
29
|
+
* @param opt addition options
|
|
30
|
+
*/
|
|
31
|
+
constructor(secret, opt) {
|
|
32
|
+
this.algorithm = "SHA256";
|
|
33
|
+
this.secret = secret;
|
|
34
|
+
this.algorithm = opt?.algorithm || this.algorithm;
|
|
35
|
+
this.algorithm = this.algorithm.replace("-", "");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Verify jwt token
|
|
39
|
+
* @param jwt token
|
|
40
|
+
* @returns is token valid
|
|
41
|
+
*/
|
|
42
|
+
verify(jwt) {
|
|
43
|
+
if (!jwt) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const parts = jwt.split(".");
|
|
47
|
+
const signature = urlEncode(crypto.createHmac(this.algorithm, this.secret).update(`${parts[0]}.${parts[1]}`).digest("base64"));
|
|
48
|
+
return signature === parts[2];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get token
|
|
52
|
+
* @param data - user data
|
|
53
|
+
* @returns jwt
|
|
54
|
+
*/
|
|
55
|
+
sign(data) {
|
|
56
|
+
const head = toBase64url({
|
|
57
|
+
alg: this.algorithm.replace("SHA", "HS"),
|
|
58
|
+
typ: "JWT"
|
|
59
|
+
});
|
|
60
|
+
const body = toBase64url(data);
|
|
61
|
+
const signature = urlEncode(crypto.createHmac(this.algorithm, this.secret).update(`${head}.${body}`).digest("base64"));
|
|
62
|
+
return `${head}.${body}.${signature}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Decode token
|
|
66
|
+
* @param jwt - jwt token
|
|
67
|
+
* @returns {head, body}
|
|
68
|
+
*/
|
|
69
|
+
decode(jwt) {
|
|
70
|
+
const parts = (jwt || "").split(".");
|
|
71
|
+
const head = fromBase64url(parts[0]);
|
|
72
|
+
const body = fromBase64url(parts[1]);
|
|
73
|
+
return { head, body };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
exports.Jwt = Jwt;
|
|
78
|
+
exports.fromBase64url = fromBase64url;
|
|
79
|
+
exports.toBase64url = toBase64url;
|
|
80
|
+
exports.urlEncode = urlEncode;
|
package/Jwt-Be4GWrIO.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
|
|
3
|
+
const urlEncode = (str) => {
|
|
4
|
+
return str.replace(/\+/ig, "-").replace(/\//ig, "_").replace(/=+$/, "");
|
|
5
|
+
};
|
|
6
|
+
const urlDecode = (str) => {
|
|
7
|
+
return str.replace(/-/ig, "+").replace(/_/ig, "/");
|
|
8
|
+
};
|
|
9
|
+
const toBase64url = (params) => {
|
|
10
|
+
return urlEncode(
|
|
11
|
+
Buffer.from(JSON.stringify(params)).toString("base64")
|
|
12
|
+
);
|
|
13
|
+
};
|
|
14
|
+
const fromBase64url = (str) => {
|
|
15
|
+
return JSON.parse(
|
|
16
|
+
Buffer.from(
|
|
17
|
+
urlDecode(str),
|
|
18
|
+
"base64"
|
|
19
|
+
).toString()
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
class Jwt {
|
|
24
|
+
/**
|
|
25
|
+
* @constructor
|
|
26
|
+
* @param secret
|
|
27
|
+
* @param opt addition options
|
|
28
|
+
*/
|
|
29
|
+
constructor(secret, opt) {
|
|
30
|
+
this.algorithm = "SHA256";
|
|
31
|
+
this.secret = secret;
|
|
32
|
+
this.algorithm = opt?.algorithm || this.algorithm;
|
|
33
|
+
this.algorithm = this.algorithm.replace("-", "");
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Verify jwt token
|
|
37
|
+
* @param jwt token
|
|
38
|
+
* @returns is token valid
|
|
39
|
+
*/
|
|
40
|
+
verify(jwt) {
|
|
41
|
+
if (!jwt) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const parts = jwt.split(".");
|
|
45
|
+
const signature = urlEncode(crypto.createHmac(this.algorithm, this.secret).update(`${parts[0]}.${parts[1]}`).digest("base64"));
|
|
46
|
+
return signature === parts[2];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get token
|
|
50
|
+
* @param data - user data
|
|
51
|
+
* @returns jwt
|
|
52
|
+
*/
|
|
53
|
+
sign(data) {
|
|
54
|
+
const head = toBase64url({
|
|
55
|
+
alg: this.algorithm.replace("SHA", "HS"),
|
|
56
|
+
typ: "JWT"
|
|
57
|
+
});
|
|
58
|
+
const body = toBase64url(data);
|
|
59
|
+
const signature = urlEncode(crypto.createHmac(this.algorithm, this.secret).update(`${head}.${body}`).digest("base64"));
|
|
60
|
+
return `${head}.${body}.${signature}`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Decode token
|
|
64
|
+
* @param jwt - jwt token
|
|
65
|
+
* @returns {head, body}
|
|
66
|
+
*/
|
|
67
|
+
decode(jwt) {
|
|
68
|
+
const parts = (jwt || "").split(".");
|
|
69
|
+
const head = fromBase64url(parts[0]);
|
|
70
|
+
const body = fromBase64url(parts[1]);
|
|
71
|
+
return { head, body };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { Jwt as J, fromBase64url as f, toBase64url as t, urlEncode as u };
|
package/Jwt.js
CHANGED
package/Jwt.mjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import 'crypto';
|
|
2
|
+
export { J as Jwt } from './Jwt-Be4GWrIO.js';
|
package/Memcached.js
CHANGED
|
@@ -1,9 +1,166 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
class Memcached {
|
|
4
|
+
/**
|
|
5
|
+
* @constructor
|
|
6
|
+
* @param memjs - memjs Client instance
|
|
7
|
+
* @param specialHeaders - special headers
|
|
8
|
+
* @param maxKeyLength - max key length
|
|
9
|
+
* @param debug
|
|
10
|
+
*/
|
|
11
|
+
constructor(memjs, specialHeaders = { "x-cache": "memcached-js" }, maxKeyLength = 160, debug = 0) {
|
|
12
|
+
this.prefix = "";
|
|
13
|
+
this.memjs = memjs;
|
|
14
|
+
this.specialHeaders = specialHeaders;
|
|
15
|
+
this.maxKeyLength = maxKeyLength;
|
|
16
|
+
this.debug = debug;
|
|
17
|
+
this.prefix = process.env.NODE_ENV !== "production" ? "dev::" : "";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Is Client exists
|
|
21
|
+
*/
|
|
22
|
+
isClient() {
|
|
23
|
+
return !!this.memjs;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Is in client is one or more conected servers
|
|
27
|
+
*/
|
|
28
|
+
isConnectedServers() {
|
|
29
|
+
if (!this.isClient()) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
const servers = this.memjs?.servers || [];
|
|
33
|
+
for (const server of servers) {
|
|
34
|
+
if (server.connected) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Set value to memcache
|
|
42
|
+
* @param key string key
|
|
43
|
+
* @param value value
|
|
44
|
+
* @param expires expiers in second
|
|
45
|
+
*/
|
|
46
|
+
async setValue(key, value, expires) {
|
|
47
|
+
if ((expires || expires === 0) && key.length <= this.maxKeyLength && this.memjs) {
|
|
48
|
+
try {
|
|
49
|
+
await this.memjs.set(`${this.prefix}${key}`, Buffer.from(value), { expires });
|
|
50
|
+
} catch (e) {
|
|
51
|
+
if (this.debug) {
|
|
52
|
+
console.log(e);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get value from memory
|
|
59
|
+
* @param key string key
|
|
60
|
+
*/
|
|
61
|
+
async getValue(key) {
|
|
62
|
+
if (key.length <= this.maxKeyLength && this.memjs) {
|
|
63
|
+
try {
|
|
64
|
+
const obj = await this.memjs.get(`${this.prefix}${key}`);
|
|
65
|
+
const result = typeof obj === "object" ? obj?.value : obj;
|
|
66
|
+
if (!result) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
} catch (e) {
|
|
71
|
+
if (this.debug) {
|
|
72
|
+
console.log(e);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Delete value
|
|
80
|
+
* @param key
|
|
81
|
+
*/
|
|
82
|
+
async deleteValue(key) {
|
|
83
|
+
if (key.length <= this.maxKeyLength && this.memjs) {
|
|
84
|
+
try {
|
|
85
|
+
return this.memjs.delete(`${this.prefix}${key}`);
|
|
86
|
+
} catch (e) {
|
|
87
|
+
if (this.debug) {
|
|
88
|
+
console.log(e);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Set page to cache
|
|
96
|
+
* @param url https://yur.site.net
|
|
97
|
+
* @param headers
|
|
98
|
+
* @param data eny data string or Buffer
|
|
99
|
+
* @param expires
|
|
100
|
+
*/
|
|
101
|
+
async setPage(url, headers, data, expires) {
|
|
102
|
+
if ((expires || expires === 0) && url.length <= this.maxKeyLength && this.memjs) {
|
|
103
|
+
try {
|
|
104
|
+
headers = this.objectKeysToLower(headers);
|
|
105
|
+
delete headers["set-cookie"];
|
|
106
|
+
const headersString = Object.entries(headers).map((v) => v.join(":")).join("\r\n");
|
|
107
|
+
const memjsHeaders = "EXTRACT_HEADERS\r\n" + headersString + "\r\n\r\n";
|
|
108
|
+
const toMamcache = Buffer.concat([Buffer.from(memjsHeaders), Buffer.from(data)]);
|
|
109
|
+
const key = /^http/.test(url) ? url : `${this.prefix}${url}`;
|
|
110
|
+
await this.memjs.set(key, toMamcache, { expires });
|
|
111
|
+
} catch (e) {
|
|
112
|
+
if (this.debug) {
|
|
113
|
+
console.log(e);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get Page and headers
|
|
120
|
+
* @param url https://your.site.net
|
|
121
|
+
* @returns {data, headers}
|
|
122
|
+
*/
|
|
123
|
+
async getPage(url) {
|
|
124
|
+
if (url.length <= this.maxKeyLength && this.memjs) {
|
|
125
|
+
try {
|
|
126
|
+
let headers = {};
|
|
127
|
+
const key = /^http/.test(url) ? url : `${this.prefix}${url}`;
|
|
128
|
+
const obj = await this.memjs.get(key);
|
|
129
|
+
const result = typeof obj === "object" ? obj?.value : obj;
|
|
130
|
+
if (!result) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
const memData = Buffer.from(result);
|
|
134
|
+
const start = memData.indexOf(Buffer.from("EXTRACT_HEADERS\r\n"));
|
|
135
|
+
const end = memData.indexOf(Buffer.from("\r\n\r\n"));
|
|
136
|
+
if (start < 0 || end < 0) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
const arr = memData.subarray(start, end).toString().split("\r\n");
|
|
140
|
+
arr.shift();
|
|
141
|
+
arr.map((row) => {
|
|
142
|
+
const [index, value] = row.split(":");
|
|
143
|
+
headers[index] = value;
|
|
144
|
+
});
|
|
145
|
+
headers = Object.assign(headers, this.specialHeaders);
|
|
146
|
+
const data = memData.subarray(end + 4);
|
|
147
|
+
return { headers, data };
|
|
148
|
+
} catch (e) {
|
|
149
|
+
if (this.debug) {
|
|
150
|
+
console.log(e);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Keys to lower case in Object
|
|
158
|
+
* @param o
|
|
159
|
+
* @private
|
|
160
|
+
*/
|
|
161
|
+
objectKeysToLower(o) {
|
|
162
|
+
return Object.keys(o).reduce((c, k) => (c[k.toLowerCase()] = o[k], c), {});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
exports.Memcached = Memcached;
|
package/Memcached.mjs
CHANGED
|
@@ -1,9 +1,164 @@
|
|
|
1
|
-
class
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
class Memcached {
|
|
2
|
+
/**
|
|
3
|
+
* @constructor
|
|
4
|
+
* @param memjs - memjs Client instance
|
|
5
|
+
* @param specialHeaders - special headers
|
|
6
|
+
* @param maxKeyLength - max key length
|
|
7
|
+
* @param debug
|
|
8
|
+
*/
|
|
9
|
+
constructor(memjs, specialHeaders = { "x-cache": "memcached-js" }, maxKeyLength = 160, debug = 0) {
|
|
10
|
+
this.prefix = "";
|
|
11
|
+
this.memjs = memjs;
|
|
12
|
+
this.specialHeaders = specialHeaders;
|
|
13
|
+
this.maxKeyLength = maxKeyLength;
|
|
14
|
+
this.debug = debug;
|
|
15
|
+
this.prefix = process.env.NODE_ENV !== "production" ? "dev::" : "";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Is Client exists
|
|
19
|
+
*/
|
|
20
|
+
isClient() {
|
|
21
|
+
return !!this.memjs;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Is in client is one or more conected servers
|
|
25
|
+
*/
|
|
26
|
+
isConnectedServers() {
|
|
27
|
+
if (!this.isClient()) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const servers = this.memjs?.servers || [];
|
|
31
|
+
for (const server of servers) {
|
|
32
|
+
if (server.connected) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Set value to memcache
|
|
40
|
+
* @param key string key
|
|
41
|
+
* @param value value
|
|
42
|
+
* @param expires expiers in second
|
|
43
|
+
*/
|
|
44
|
+
async setValue(key, value, expires) {
|
|
45
|
+
if ((expires || expires === 0) && key.length <= this.maxKeyLength && this.memjs) {
|
|
46
|
+
try {
|
|
47
|
+
await this.memjs.set(`${this.prefix}${key}`, Buffer.from(value), { expires });
|
|
48
|
+
} catch (e) {
|
|
49
|
+
if (this.debug) {
|
|
50
|
+
console.log(e);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get value from memory
|
|
57
|
+
* @param key string key
|
|
58
|
+
*/
|
|
59
|
+
async getValue(key) {
|
|
60
|
+
if (key.length <= this.maxKeyLength && this.memjs) {
|
|
61
|
+
try {
|
|
62
|
+
const obj = await this.memjs.get(`${this.prefix}${key}`);
|
|
63
|
+
const result = typeof obj === "object" ? obj?.value : obj;
|
|
64
|
+
if (!result) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
} catch (e) {
|
|
69
|
+
if (this.debug) {
|
|
70
|
+
console.log(e);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Delete value
|
|
78
|
+
* @param key
|
|
79
|
+
*/
|
|
80
|
+
async deleteValue(key) {
|
|
81
|
+
if (key.length <= this.maxKeyLength && this.memjs) {
|
|
82
|
+
try {
|
|
83
|
+
return this.memjs.delete(`${this.prefix}${key}`);
|
|
84
|
+
} catch (e) {
|
|
85
|
+
if (this.debug) {
|
|
86
|
+
console.log(e);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Set page to cache
|
|
94
|
+
* @param url https://yur.site.net
|
|
95
|
+
* @param headers
|
|
96
|
+
* @param data eny data string or Buffer
|
|
97
|
+
* @param expires
|
|
98
|
+
*/
|
|
99
|
+
async setPage(url, headers, data, expires) {
|
|
100
|
+
if ((expires || expires === 0) && url.length <= this.maxKeyLength && this.memjs) {
|
|
101
|
+
try {
|
|
102
|
+
headers = this.objectKeysToLower(headers);
|
|
103
|
+
delete headers["set-cookie"];
|
|
104
|
+
const headersString = Object.entries(headers).map((v) => v.join(":")).join("\r\n");
|
|
105
|
+
const memjsHeaders = "EXTRACT_HEADERS\r\n" + headersString + "\r\n\r\n";
|
|
106
|
+
const toMamcache = Buffer.concat([Buffer.from(memjsHeaders), Buffer.from(data)]);
|
|
107
|
+
const key = /^http/.test(url) ? url : `${this.prefix}${url}`;
|
|
108
|
+
await this.memjs.set(key, toMamcache, { expires });
|
|
109
|
+
} catch (e) {
|
|
110
|
+
if (this.debug) {
|
|
111
|
+
console.log(e);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get Page and headers
|
|
118
|
+
* @param url https://your.site.net
|
|
119
|
+
* @returns {data, headers}
|
|
120
|
+
*/
|
|
121
|
+
async getPage(url) {
|
|
122
|
+
if (url.length <= this.maxKeyLength && this.memjs) {
|
|
123
|
+
try {
|
|
124
|
+
let headers = {};
|
|
125
|
+
const key = /^http/.test(url) ? url : `${this.prefix}${url}`;
|
|
126
|
+
const obj = await this.memjs.get(key);
|
|
127
|
+
const result = typeof obj === "object" ? obj?.value : obj;
|
|
128
|
+
if (!result) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
const memData = Buffer.from(result);
|
|
132
|
+
const start = memData.indexOf(Buffer.from("EXTRACT_HEADERS\r\n"));
|
|
133
|
+
const end = memData.indexOf(Buffer.from("\r\n\r\n"));
|
|
134
|
+
if (start < 0 || end < 0) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
const arr = memData.subarray(start, end).toString().split("\r\n");
|
|
138
|
+
arr.shift();
|
|
139
|
+
arr.map((row) => {
|
|
140
|
+
const [index, value] = row.split(":");
|
|
141
|
+
headers[index] = value;
|
|
142
|
+
});
|
|
143
|
+
headers = Object.assign(headers, this.specialHeaders);
|
|
144
|
+
const data = memData.subarray(end + 4);
|
|
145
|
+
return { headers, data };
|
|
146
|
+
} catch (e) {
|
|
147
|
+
if (this.debug) {
|
|
148
|
+
console.log(e);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Keys to lower case in Object
|
|
156
|
+
* @param o
|
|
157
|
+
* @private
|
|
158
|
+
*/
|
|
159
|
+
objectKeysToLower(o) {
|
|
160
|
+
return Object.keys(o).reduce((c, k) => (c[k.toLowerCase()] = o[k], c), {});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export { Memcached };
|