hono 4.12.19 → 4.12.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/dist/cjs/hono-base.js +9 -4
- package/dist/cjs/middleware/ip-restriction/index.js +58 -28
- package/dist/cjs/middleware/jwk/jwk.js +1 -1
- package/dist/cjs/middleware/jwt/jwt.js +1 -1
- package/dist/cjs/utils/cookie.js +1 -1
- package/dist/cjs/utils/ipaddr.js +186 -8
- package/dist/hono-base.js +9 -4
- package/dist/middleware/ip-restriction/index.js +60 -29
- package/dist/middleware/jwk/jwk.js +1 -1
- package/dist/middleware/jwt/jwt.js +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/jsx/base.d.ts +2 -2
- package/dist/types/jsx/index.d.ts +1 -1
- package/dist/types/utils/ipaddr.d.ts +4 -0
- package/dist/utils/cookie.js +1 -1
- package/dist/utils/ipaddr.js +185 -8
- package/package.json +1 -1
package/dist/cjs/hono-base.js
CHANGED
|
@@ -139,7 +139,7 @@ class Hono {
|
|
|
139
139
|
handler = async (c, next) => (await (0, import_compose.compose)([], app.errorHandler)(c, () => r.handler(c, next))).res;
|
|
140
140
|
handler[import_constants.COMPOSED_HANDLER] = r.handler;
|
|
141
141
|
}
|
|
142
|
-
subApp.#addRoute(r.method, r.path, handler);
|
|
142
|
+
subApp.#addRoute(r.method, r.path, handler, r.basePath);
|
|
143
143
|
});
|
|
144
144
|
return this;
|
|
145
145
|
}
|
|
@@ -263,7 +263,7 @@ class Hono {
|
|
|
263
263
|
const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
|
|
264
264
|
return (request) => {
|
|
265
265
|
const url = new URL(request.url);
|
|
266
|
-
url.pathname =
|
|
266
|
+
url.pathname = this.getPath(request).slice(pathPrefixLength) || "/";
|
|
267
267
|
return new Request(url, request);
|
|
268
268
|
};
|
|
269
269
|
})();
|
|
@@ -277,10 +277,15 @@ class Hono {
|
|
|
277
277
|
this.#addRoute(import_router.METHOD_NAME_ALL, (0, import_url.mergePath)(path, "*"), handler);
|
|
278
278
|
return this;
|
|
279
279
|
}
|
|
280
|
-
#addRoute(method, path, handler) {
|
|
280
|
+
#addRoute(method, path, handler, baseRoutePath) {
|
|
281
281
|
method = method.toUpperCase();
|
|
282
282
|
path = (0, import_url.mergePath)(this._basePath, path);
|
|
283
|
-
const r = {
|
|
283
|
+
const r = {
|
|
284
|
+
basePath: baseRoutePath !== void 0 ? (0, import_url.mergePath)(this._basePath, baseRoutePath) : this._basePath,
|
|
285
|
+
path,
|
|
286
|
+
method,
|
|
287
|
+
handler
|
|
288
|
+
};
|
|
284
289
|
this.router.add(method, path, [handler, r]);
|
|
285
290
|
this.routes.push(r);
|
|
286
291
|
}
|
|
@@ -22,11 +22,45 @@ __export(ip_restriction_exports, {
|
|
|
22
22
|
module.exports = __toCommonJS(ip_restriction_exports);
|
|
23
23
|
var import_http_exception = require("../../http-exception");
|
|
24
24
|
var import_ipaddr = require("../../utils/ipaddr");
|
|
25
|
-
const IS_CIDR_NOTATION_REGEX = /\/[
|
|
25
|
+
const IS_CIDR_NOTATION_REGEX = /\/[^/]*$/;
|
|
26
|
+
const parseCidrPrefix = (rule, prefix, max) => {
|
|
27
|
+
if (!/^[0-9]{1,3}$/.test(prefix)) {
|
|
28
|
+
throw new TypeError(`Invalid rule: ${rule}`);
|
|
29
|
+
}
|
|
30
|
+
const parsedPrefix = parseInt(prefix);
|
|
31
|
+
if (parsedPrefix > max) {
|
|
32
|
+
throw new TypeError(`Invalid rule: ${rule}`);
|
|
33
|
+
}
|
|
34
|
+
return parsedPrefix;
|
|
35
|
+
};
|
|
26
36
|
const buildMatcher = (rules) => {
|
|
27
37
|
const functionRules = [];
|
|
28
38
|
const staticRules = /* @__PURE__ */ new Set();
|
|
39
|
+
const staticIPv4Rules = /* @__PURE__ */ new Set();
|
|
40
|
+
const staticIPv6Rules = /* @__PURE__ */ new Set();
|
|
29
41
|
const cidrRules = [];
|
|
42
|
+
const registerStaticRule = (rule) => {
|
|
43
|
+
const type = (0, import_ipaddr.distinctRemoteAddr)(rule);
|
|
44
|
+
if (type === void 0) {
|
|
45
|
+
throw new TypeError(`Invalid rule: ${rule}`);
|
|
46
|
+
}
|
|
47
|
+
if (type === "IPv4") {
|
|
48
|
+
const ipv4binary = (0, import_ipaddr.convertIPv4ToBinary)(rule);
|
|
49
|
+
staticRules.add(rule);
|
|
50
|
+
staticRules.add(`::ffff:${rule}`);
|
|
51
|
+
staticIPv4Rules.add(ipv4binary);
|
|
52
|
+
staticIPv6Rules.add(0xffffn << 32n | ipv4binary);
|
|
53
|
+
} else {
|
|
54
|
+
const ipv6binary = (0, import_ipaddr.convertIPv6ToBinary)(rule);
|
|
55
|
+
const ipv6Addr = (0, import_ipaddr.convertIPv6BinaryToString)(ipv6binary);
|
|
56
|
+
staticRules.add(ipv6Addr);
|
|
57
|
+
staticIPv6Rules.add(ipv6binary);
|
|
58
|
+
if ((0, import_ipaddr.isIPv4MappedIPv6)(ipv6binary)) {
|
|
59
|
+
staticRules.add(ipv6Addr.substring(7));
|
|
60
|
+
staticIPv4Rules.add((0, import_ipaddr.convertIPv4MappedIPv6ToIPv4)(ipv6binary));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
30
64
|
for (let rule of rules) {
|
|
31
65
|
if (rule === "*") {
|
|
32
66
|
return () => true;
|
|
@@ -36,17 +70,17 @@ const buildMatcher = (rules) => {
|
|
|
36
70
|
if (IS_CIDR_NOTATION_REGEX.test(rule)) {
|
|
37
71
|
const separatedRule = rule.split("/");
|
|
38
72
|
const addrStr = separatedRule[0];
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
73
|
+
const type = (0, import_ipaddr.distinctRemoteAddr)(addrStr);
|
|
74
|
+
if (type === void 0) {
|
|
41
75
|
throw new TypeError(`Invalid rule: ${rule}`);
|
|
42
76
|
}
|
|
43
|
-
let isIPv4 =
|
|
44
|
-
let prefix =
|
|
77
|
+
let isIPv4 = type === "IPv4";
|
|
78
|
+
let prefix = parseCidrPrefix(rule, separatedRule[1], isIPv4 ? 32 : 128);
|
|
45
79
|
if (isIPv4 ? prefix === 32 : prefix === 128) {
|
|
46
80
|
rule = addrStr;
|
|
47
81
|
} else {
|
|
48
82
|
let addr = (isIPv4 ? import_ipaddr.convertIPv4ToBinary : import_ipaddr.convertIPv6ToBinary)(addrStr);
|
|
49
|
-
if (
|
|
83
|
+
if (type === "IPv6" && (0, import_ipaddr.isIPv4MappedIPv6)(addr) && prefix >= 96) {
|
|
50
84
|
isIPv4 = true;
|
|
51
85
|
addr = (0, import_ipaddr.convertIPv4MappedIPv6ToIPv4)(addr);
|
|
52
86
|
prefix -= 96;
|
|
@@ -56,21 +90,7 @@ const buildMatcher = (rules) => {
|
|
|
56
90
|
continue;
|
|
57
91
|
}
|
|
58
92
|
}
|
|
59
|
-
|
|
60
|
-
if (type === void 0) {
|
|
61
|
-
throw new TypeError(`Invalid rule: ${rule}`);
|
|
62
|
-
}
|
|
63
|
-
if (type === "IPv4") {
|
|
64
|
-
staticRules.add(rule);
|
|
65
|
-
staticRules.add(`::ffff:${rule}`);
|
|
66
|
-
} else {
|
|
67
|
-
const ipv6binary = (0, import_ipaddr.convertIPv6ToBinary)(rule);
|
|
68
|
-
const ipv6Addr = (0, import_ipaddr.convertIPv6BinaryToString)(ipv6binary);
|
|
69
|
-
staticRules.add(ipv6Addr);
|
|
70
|
-
if ((0, import_ipaddr.isIPv4MappedIPv6)(ipv6binary)) {
|
|
71
|
-
staticRules.add(ipv6Addr.substring(7));
|
|
72
|
-
}
|
|
73
|
-
}
|
|
93
|
+
registerStaticRule(rule);
|
|
74
94
|
}
|
|
75
95
|
}
|
|
76
96
|
return (remote) => {
|
|
@@ -79,6 +99,9 @@ const buildMatcher = (rules) => {
|
|
|
79
99
|
}
|
|
80
100
|
const remoteAddr = remote.binaryAddr ||= (remote.isIPv4 ? import_ipaddr.convertIPv4ToBinary : import_ipaddr.convertIPv6ToBinary)(remote.addr);
|
|
81
101
|
const remoteIPv4Addr = remote.isIPv4 || (0, import_ipaddr.isIPv4MappedIPv6)(remoteAddr) ? remote.isIPv4 ? remoteAddr : (0, import_ipaddr.convertIPv4MappedIPv6ToIPv4)(remoteAddr) : void 0;
|
|
102
|
+
if ((remote.isIPv4 ? staticIPv4Rules : staticIPv6Rules).has(remoteAddr)) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
82
105
|
for (const [isIPv4, addr, mask] of cidrRules) {
|
|
83
106
|
if (isIPv4) {
|
|
84
107
|
if (remoteIPv4Addr === void 0) {
|
|
@@ -121,14 +144,21 @@ const ipRestriction = (getIP, { denyList = [], allowList = [] }, onError) => {
|
|
|
121
144
|
}
|
|
122
145
|
const type = typeof connInfo !== "string" && connInfo.remote.addressType || (0, import_ipaddr.distinctRemoteAddr)(addr);
|
|
123
146
|
const remoteData = { addr, type, isIPv4: type === "IPv4" };
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
|
|
147
|
+
try {
|
|
148
|
+
if (denyMatcher(remoteData)) {
|
|
149
|
+
if (onError) {
|
|
150
|
+
return onError({ addr, type }, c);
|
|
151
|
+
}
|
|
152
|
+
throw blockError(c);
|
|
127
153
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
154
|
+
if (allowMatcher(remoteData)) {
|
|
155
|
+
return await next();
|
|
156
|
+
}
|
|
157
|
+
} catch (e) {
|
|
158
|
+
if (e instanceof TypeError && e.code === import_ipaddr.INVALID_IP_ADDRESS_ERROR_CODE) {
|
|
159
|
+
throw blockError(c);
|
|
160
|
+
}
|
|
161
|
+
throw e;
|
|
132
162
|
}
|
|
133
163
|
if (allowLength === 0) {
|
|
134
164
|
return await next();
|
|
@@ -38,7 +38,7 @@ const jwk = (options, init) => {
|
|
|
38
38
|
let token;
|
|
39
39
|
if (credentials) {
|
|
40
40
|
const parts = credentials.split(/\s+/);
|
|
41
|
-
if (parts.length !== 2) {
|
|
41
|
+
if (parts.length !== 2 || parts[0].toLowerCase() !== "bearer") {
|
|
42
42
|
const errDescription = "invalid credentials structure";
|
|
43
43
|
throw new import_http_exception.HTTPException(401, {
|
|
44
44
|
message: errDescription,
|
|
@@ -45,7 +45,7 @@ const jwt = (options) => {
|
|
|
45
45
|
let token;
|
|
46
46
|
if (credentials) {
|
|
47
47
|
const parts = credentials.split(/\s+/);
|
|
48
|
-
if (parts.length !== 2) {
|
|
48
|
+
if (parts.length !== 2 || parts[0].toLowerCase() !== "bearer") {
|
|
49
49
|
const errDescription = "invalid credentials structure";
|
|
50
50
|
throw new import_http_exception.HTTPException(401, {
|
|
51
51
|
message: errDescription,
|
package/dist/cjs/utils/cookie.js
CHANGED
|
@@ -132,7 +132,7 @@ const _serialize = (name, value, opt = {}) => {
|
|
|
132
132
|
throw new Error("__Host- Cookie must not have Domain attributes");
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
-
for (const key of ["domain", "path"]) {
|
|
135
|
+
for (const key of ["domain", "path", "sameSite", "priority"]) {
|
|
136
136
|
if (opt[key] && /[;\r\n]/.test(opt[key])) {
|
|
137
137
|
throw new Error(`${key} must not contain ";", "\\r", or "\\n"`);
|
|
138
138
|
}
|
package/dist/cjs/utils/ipaddr.js
CHANGED
|
@@ -17,6 +17,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
17
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
18
|
var ipaddr_exports = {};
|
|
19
19
|
__export(ipaddr_exports, {
|
|
20
|
+
INVALID_IP_ADDRESS_ERROR_CODE: () => INVALID_IP_ADDRESS_ERROR_CODE,
|
|
20
21
|
convertIPv4BinaryToString: () => convertIPv4BinaryToString,
|
|
21
22
|
convertIPv4MappedIPv6ToIPv4: () => convertIPv4MappedIPv6ToIPv4,
|
|
22
23
|
convertIPv4ToBinary: () => convertIPv4ToBinary,
|
|
@@ -50,6 +51,16 @@ const expandIPv6 = (ipV6) => {
|
|
|
50
51
|
};
|
|
51
52
|
const IPV4_OCTET_PART = "(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])";
|
|
52
53
|
const IPV4_REGEX = new RegExp(`^(?:${IPV4_OCTET_PART}\\.){3}${IPV4_OCTET_PART}$`);
|
|
54
|
+
const INVALID_IP_ADDRESS_ERROR_CODE = "ERR_INVALID_IP_ADDRESS";
|
|
55
|
+
const CHAR_CODE_0 = 48;
|
|
56
|
+
const CHAR_CODE_9 = 57;
|
|
57
|
+
const CHAR_CODE_A = 65;
|
|
58
|
+
const CHAR_CODE_F = 70;
|
|
59
|
+
const CHAR_CODE_a = 97;
|
|
60
|
+
const CHAR_CODE_f = 102;
|
|
61
|
+
const CHAR_CODE_DOT = 46;
|
|
62
|
+
const CHAR_CODE_COLON = 58;
|
|
63
|
+
const CHAR_CODE_PERCENT = 37;
|
|
53
64
|
const distinctRemoteAddr = (remoteAddr) => {
|
|
54
65
|
if (IPV4_REGEX.test(remoteAddr)) {
|
|
55
66
|
return "IPv4";
|
|
@@ -58,21 +69,187 @@ const distinctRemoteAddr = (remoteAddr) => {
|
|
|
58
69
|
return "IPv6";
|
|
59
70
|
}
|
|
60
71
|
};
|
|
61
|
-
const
|
|
62
|
-
const
|
|
72
|
+
const createInvalidIPAddressError = (message) => {
|
|
73
|
+
const error = new TypeError(message);
|
|
74
|
+
error.code = INVALID_IP_ADDRESS_ERROR_CODE;
|
|
75
|
+
return error;
|
|
76
|
+
};
|
|
77
|
+
const throwInvalidIPv4Address = (ipv4) => {
|
|
78
|
+
throw createInvalidIPAddressError(`Invalid IPv4 address: ${ipv4}`);
|
|
79
|
+
};
|
|
80
|
+
const throwInvalidIPv6Address = (ipv6) => {
|
|
81
|
+
throw createInvalidIPAddressError(`Invalid IPv6 address: ${ipv6}`);
|
|
82
|
+
};
|
|
83
|
+
const parseIPv4ToBinary = (ipv4, start, end, onInvalid) => {
|
|
63
84
|
let result = 0n;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
85
|
+
let octets = 0;
|
|
86
|
+
let octet = 0;
|
|
87
|
+
let digits = 0;
|
|
88
|
+
let firstDigit = 0;
|
|
89
|
+
for (let i = start; i <= end; i++) {
|
|
90
|
+
const code = i < end ? ipv4.charCodeAt(i) : CHAR_CODE_DOT;
|
|
91
|
+
if (code >= CHAR_CODE_0 && code <= CHAR_CODE_9) {
|
|
92
|
+
if (digits === 0) {
|
|
93
|
+
firstDigit = code;
|
|
94
|
+
} else if (firstDigit === CHAR_CODE_0) {
|
|
95
|
+
onInvalid();
|
|
96
|
+
}
|
|
97
|
+
octet = octet * 10 + code - CHAR_CODE_0;
|
|
98
|
+
if (octet > 255) {
|
|
99
|
+
onInvalid();
|
|
100
|
+
}
|
|
101
|
+
digits++;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (code !== CHAR_CODE_DOT || digits === 0 || octets === 4) {
|
|
105
|
+
onInvalid();
|
|
106
|
+
}
|
|
107
|
+
result = (result << 8n) + BigInt(octet);
|
|
108
|
+
octets++;
|
|
109
|
+
octet = 0;
|
|
110
|
+
digits = 0;
|
|
111
|
+
}
|
|
112
|
+
if (octets !== 4) {
|
|
113
|
+
onInvalid();
|
|
67
114
|
}
|
|
68
115
|
return result;
|
|
69
116
|
};
|
|
117
|
+
const parseIPv6HexCode = (code) => {
|
|
118
|
+
if (code >= CHAR_CODE_0 && code <= CHAR_CODE_9) {
|
|
119
|
+
return code - CHAR_CODE_0;
|
|
120
|
+
}
|
|
121
|
+
if (code >= CHAR_CODE_A && code <= CHAR_CODE_F) {
|
|
122
|
+
return code - CHAR_CODE_A + 10;
|
|
123
|
+
}
|
|
124
|
+
if (code >= CHAR_CODE_a && code <= CHAR_CODE_f) {
|
|
125
|
+
return code - CHAR_CODE_a + 10;
|
|
126
|
+
}
|
|
127
|
+
return -1;
|
|
128
|
+
};
|
|
129
|
+
const isIPv6LinkLocal = (ipv6binary) => ipv6binary >> 118n === 0x3fan;
|
|
130
|
+
const convertIPv4ToBinary = (ipv4) => {
|
|
131
|
+
return parseIPv4ToBinary(ipv4, 0, ipv4.length, () => throwInvalidIPv4Address(ipv4));
|
|
132
|
+
};
|
|
70
133
|
const convertIPv6ToBinary = (ipv6) => {
|
|
71
|
-
const
|
|
134
|
+
const length = ipv6.length;
|
|
135
|
+
const sections = [];
|
|
136
|
+
let hasZoneId = false;
|
|
137
|
+
let compressAt = -1;
|
|
138
|
+
let index = 0;
|
|
139
|
+
if (length === 0) {
|
|
140
|
+
throwInvalidIPv6Address(ipv6);
|
|
141
|
+
}
|
|
142
|
+
while (index < length) {
|
|
143
|
+
if (sections.length > 8) {
|
|
144
|
+
throwInvalidIPv6Address(ipv6);
|
|
145
|
+
}
|
|
146
|
+
let code = ipv6.charCodeAt(index);
|
|
147
|
+
if (code === CHAR_CODE_PERCENT) {
|
|
148
|
+
if (index + 1 === length) {
|
|
149
|
+
throwInvalidIPv6Address(ipv6);
|
|
150
|
+
}
|
|
151
|
+
hasZoneId = true;
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
if (code === CHAR_CODE_COLON) {
|
|
155
|
+
if (index + 1 < length && ipv6.charCodeAt(index + 1) === CHAR_CODE_COLON) {
|
|
156
|
+
if (compressAt !== -1) {
|
|
157
|
+
throwInvalidIPv6Address(ipv6);
|
|
158
|
+
}
|
|
159
|
+
compressAt = sections.length;
|
|
160
|
+
index += 2;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
throwInvalidIPv6Address(ipv6);
|
|
164
|
+
}
|
|
165
|
+
let value = 0;
|
|
166
|
+
let digits = 0;
|
|
167
|
+
const sectionStart = index;
|
|
168
|
+
while (index < length) {
|
|
169
|
+
code = ipv6.charCodeAt(index);
|
|
170
|
+
const hex = parseIPv6HexCode(code);
|
|
171
|
+
if (hex === -1) {
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
if (digits === 4) {
|
|
175
|
+
throwInvalidIPv6Address(ipv6);
|
|
176
|
+
}
|
|
177
|
+
value = value << 4 | hex;
|
|
178
|
+
digits++;
|
|
179
|
+
index++;
|
|
180
|
+
}
|
|
181
|
+
if (index < length && ipv6.charCodeAt(index) === CHAR_CODE_DOT) {
|
|
182
|
+
let ipv4End = length;
|
|
183
|
+
for (let i = index; i < length; i++) {
|
|
184
|
+
if (ipv6.charCodeAt(i) === CHAR_CODE_PERCENT) {
|
|
185
|
+
if (i + 1 === length) {
|
|
186
|
+
throwInvalidIPv6Address(ipv6);
|
|
187
|
+
}
|
|
188
|
+
hasZoneId = true;
|
|
189
|
+
ipv4End = i;
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const ipv4 = parseIPv4ToBinary(
|
|
194
|
+
ipv6,
|
|
195
|
+
sectionStart,
|
|
196
|
+
ipv4End,
|
|
197
|
+
() => throwInvalidIPv6Address(ipv6)
|
|
198
|
+
);
|
|
199
|
+
sections.push(Number(ipv4 >> 16n & 0xffffn), Number(ipv4 & 0xffffn));
|
|
200
|
+
index = length;
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
if (digits === 0) {
|
|
204
|
+
throwInvalidIPv6Address(ipv6);
|
|
205
|
+
}
|
|
206
|
+
sections.push(value);
|
|
207
|
+
if (index === length) {
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
code = ipv6.charCodeAt(index);
|
|
211
|
+
if (code === CHAR_CODE_PERCENT) {
|
|
212
|
+
if (index + 1 === length) {
|
|
213
|
+
throwInvalidIPv6Address(ipv6);
|
|
214
|
+
}
|
|
215
|
+
hasZoneId = true;
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
if (code !== CHAR_CODE_COLON) {
|
|
219
|
+
throwInvalidIPv6Address(ipv6);
|
|
220
|
+
}
|
|
221
|
+
if (index + 1 < length && ipv6.charCodeAt(index + 1) === CHAR_CODE_COLON) {
|
|
222
|
+
if (compressAt !== -1) {
|
|
223
|
+
throwInvalidIPv6Address(ipv6);
|
|
224
|
+
}
|
|
225
|
+
compressAt = sections.length;
|
|
226
|
+
index += 2;
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
index++;
|
|
230
|
+
if (index === length) {
|
|
231
|
+
throwInvalidIPv6Address(ipv6);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (compressAt === -1 ? sections.length !== 8 : sections.length >= 8) {
|
|
235
|
+
throwInvalidIPv6Address(ipv6);
|
|
236
|
+
}
|
|
72
237
|
let result = 0n;
|
|
73
|
-
|
|
238
|
+
const zeros = compressAt === -1 ? 0 : 8 - sections.length;
|
|
239
|
+
const firstSectionEnd = compressAt === -1 ? sections.length : compressAt;
|
|
240
|
+
for (let i = 0; i < firstSectionEnd; i++) {
|
|
74
241
|
result <<= 16n;
|
|
75
|
-
result += BigInt(
|
|
242
|
+
result += BigInt(sections[i]);
|
|
243
|
+
}
|
|
244
|
+
for (let i = 0; i < zeros; i++) {
|
|
245
|
+
result <<= 16n;
|
|
246
|
+
}
|
|
247
|
+
for (let i = firstSectionEnd; i < sections.length; i++) {
|
|
248
|
+
result <<= 16n;
|
|
249
|
+
result += BigInt(sections[i]);
|
|
250
|
+
}
|
|
251
|
+
if (hasZoneId && !isIPv6LinkLocal(result)) {
|
|
252
|
+
throwInvalidIPv6Address(ipv6);
|
|
76
253
|
}
|
|
77
254
|
return result;
|
|
78
255
|
};
|
|
@@ -124,6 +301,7 @@ const convertIPv6BinaryToString = (ipV6) => {
|
|
|
124
301
|
};
|
|
125
302
|
// Annotate the CommonJS export names for ESM import in node:
|
|
126
303
|
0 && (module.exports = {
|
|
304
|
+
INVALID_IP_ADDRESS_ERROR_CODE,
|
|
127
305
|
convertIPv4BinaryToString,
|
|
128
306
|
convertIPv4MappedIPv6ToIPv4,
|
|
129
307
|
convertIPv4ToBinary,
|
package/dist/hono-base.js
CHANGED
|
@@ -118,7 +118,7 @@ var Hono = class _Hono {
|
|
|
118
118
|
handler = async (c, next) => (await compose([], app.errorHandler)(c, () => r.handler(c, next))).res;
|
|
119
119
|
handler[COMPOSED_HANDLER] = r.handler;
|
|
120
120
|
}
|
|
121
|
-
subApp.#addRoute(r.method, r.path, handler);
|
|
121
|
+
subApp.#addRoute(r.method, r.path, handler, r.basePath);
|
|
122
122
|
});
|
|
123
123
|
return this;
|
|
124
124
|
}
|
|
@@ -242,7 +242,7 @@ var Hono = class _Hono {
|
|
|
242
242
|
const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
|
|
243
243
|
return (request) => {
|
|
244
244
|
const url = new URL(request.url);
|
|
245
|
-
url.pathname =
|
|
245
|
+
url.pathname = this.getPath(request).slice(pathPrefixLength) || "/";
|
|
246
246
|
return new Request(url, request);
|
|
247
247
|
};
|
|
248
248
|
})();
|
|
@@ -256,10 +256,15 @@ var Hono = class _Hono {
|
|
|
256
256
|
this.#addRoute(METHOD_NAME_ALL, mergePath(path, "*"), handler);
|
|
257
257
|
return this;
|
|
258
258
|
}
|
|
259
|
-
#addRoute(method, path, handler) {
|
|
259
|
+
#addRoute(method, path, handler, baseRoutePath) {
|
|
260
260
|
method = method.toUpperCase();
|
|
261
261
|
path = mergePath(this._basePath, path);
|
|
262
|
-
const r = {
|
|
262
|
+
const r = {
|
|
263
|
+
basePath: baseRoutePath !== void 0 ? mergePath(this._basePath, baseRoutePath) : this._basePath,
|
|
264
|
+
path,
|
|
265
|
+
method,
|
|
266
|
+
handler
|
|
267
|
+
};
|
|
263
268
|
this.router.add(method, path, [handler, r]);
|
|
264
269
|
this.routes.push(r);
|
|
265
270
|
}
|
|
@@ -6,13 +6,48 @@ import {
|
|
|
6
6
|
convertIPv6BinaryToString,
|
|
7
7
|
convertIPv6ToBinary,
|
|
8
8
|
distinctRemoteAddr,
|
|
9
|
-
isIPv4MappedIPv6
|
|
9
|
+
isIPv4MappedIPv6,
|
|
10
|
+
INVALID_IP_ADDRESS_ERROR_CODE
|
|
10
11
|
} from "../../utils/ipaddr.js";
|
|
11
|
-
var IS_CIDR_NOTATION_REGEX = /\/[
|
|
12
|
+
var IS_CIDR_NOTATION_REGEX = /\/[^/]*$/;
|
|
13
|
+
var parseCidrPrefix = (rule, prefix, max) => {
|
|
14
|
+
if (!/^[0-9]{1,3}$/.test(prefix)) {
|
|
15
|
+
throw new TypeError(`Invalid rule: ${rule}`);
|
|
16
|
+
}
|
|
17
|
+
const parsedPrefix = parseInt(prefix);
|
|
18
|
+
if (parsedPrefix > max) {
|
|
19
|
+
throw new TypeError(`Invalid rule: ${rule}`);
|
|
20
|
+
}
|
|
21
|
+
return parsedPrefix;
|
|
22
|
+
};
|
|
12
23
|
var buildMatcher = (rules) => {
|
|
13
24
|
const functionRules = [];
|
|
14
25
|
const staticRules = /* @__PURE__ */ new Set();
|
|
26
|
+
const staticIPv4Rules = /* @__PURE__ */ new Set();
|
|
27
|
+
const staticIPv6Rules = /* @__PURE__ */ new Set();
|
|
15
28
|
const cidrRules = [];
|
|
29
|
+
const registerStaticRule = (rule) => {
|
|
30
|
+
const type = distinctRemoteAddr(rule);
|
|
31
|
+
if (type === void 0) {
|
|
32
|
+
throw new TypeError(`Invalid rule: ${rule}`);
|
|
33
|
+
}
|
|
34
|
+
if (type === "IPv4") {
|
|
35
|
+
const ipv4binary = convertIPv4ToBinary(rule);
|
|
36
|
+
staticRules.add(rule);
|
|
37
|
+
staticRules.add(`::ffff:${rule}`);
|
|
38
|
+
staticIPv4Rules.add(ipv4binary);
|
|
39
|
+
staticIPv6Rules.add(0xffffn << 32n | ipv4binary);
|
|
40
|
+
} else {
|
|
41
|
+
const ipv6binary = convertIPv6ToBinary(rule);
|
|
42
|
+
const ipv6Addr = convertIPv6BinaryToString(ipv6binary);
|
|
43
|
+
staticRules.add(ipv6Addr);
|
|
44
|
+
staticIPv6Rules.add(ipv6binary);
|
|
45
|
+
if (isIPv4MappedIPv6(ipv6binary)) {
|
|
46
|
+
staticRules.add(ipv6Addr.substring(7));
|
|
47
|
+
staticIPv4Rules.add(convertIPv4MappedIPv6ToIPv4(ipv6binary));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
16
51
|
for (let rule of rules) {
|
|
17
52
|
if (rule === "*") {
|
|
18
53
|
return () => true;
|
|
@@ -22,17 +57,17 @@ var buildMatcher = (rules) => {
|
|
|
22
57
|
if (IS_CIDR_NOTATION_REGEX.test(rule)) {
|
|
23
58
|
const separatedRule = rule.split("/");
|
|
24
59
|
const addrStr = separatedRule[0];
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
60
|
+
const type = distinctRemoteAddr(addrStr);
|
|
61
|
+
if (type === void 0) {
|
|
27
62
|
throw new TypeError(`Invalid rule: ${rule}`);
|
|
28
63
|
}
|
|
29
|
-
let isIPv4 =
|
|
30
|
-
let prefix =
|
|
64
|
+
let isIPv4 = type === "IPv4";
|
|
65
|
+
let prefix = parseCidrPrefix(rule, separatedRule[1], isIPv4 ? 32 : 128);
|
|
31
66
|
if (isIPv4 ? prefix === 32 : prefix === 128) {
|
|
32
67
|
rule = addrStr;
|
|
33
68
|
} else {
|
|
34
69
|
let addr = (isIPv4 ? convertIPv4ToBinary : convertIPv6ToBinary)(addrStr);
|
|
35
|
-
if (
|
|
70
|
+
if (type === "IPv6" && isIPv4MappedIPv6(addr) && prefix >= 96) {
|
|
36
71
|
isIPv4 = true;
|
|
37
72
|
addr = convertIPv4MappedIPv6ToIPv4(addr);
|
|
38
73
|
prefix -= 96;
|
|
@@ -42,21 +77,7 @@ var buildMatcher = (rules) => {
|
|
|
42
77
|
continue;
|
|
43
78
|
}
|
|
44
79
|
}
|
|
45
|
-
|
|
46
|
-
if (type === void 0) {
|
|
47
|
-
throw new TypeError(`Invalid rule: ${rule}`);
|
|
48
|
-
}
|
|
49
|
-
if (type === "IPv4") {
|
|
50
|
-
staticRules.add(rule);
|
|
51
|
-
staticRules.add(`::ffff:${rule}`);
|
|
52
|
-
} else {
|
|
53
|
-
const ipv6binary = convertIPv6ToBinary(rule);
|
|
54
|
-
const ipv6Addr = convertIPv6BinaryToString(ipv6binary);
|
|
55
|
-
staticRules.add(ipv6Addr);
|
|
56
|
-
if (isIPv4MappedIPv6(ipv6binary)) {
|
|
57
|
-
staticRules.add(ipv6Addr.substring(7));
|
|
58
|
-
}
|
|
59
|
-
}
|
|
80
|
+
registerStaticRule(rule);
|
|
60
81
|
}
|
|
61
82
|
}
|
|
62
83
|
return (remote) => {
|
|
@@ -65,6 +86,9 @@ var buildMatcher = (rules) => {
|
|
|
65
86
|
}
|
|
66
87
|
const remoteAddr = remote.binaryAddr ||= (remote.isIPv4 ? convertIPv4ToBinary : convertIPv6ToBinary)(remote.addr);
|
|
67
88
|
const remoteIPv4Addr = remote.isIPv4 || isIPv4MappedIPv6(remoteAddr) ? remote.isIPv4 ? remoteAddr : convertIPv4MappedIPv6ToIPv4(remoteAddr) : void 0;
|
|
89
|
+
if ((remote.isIPv4 ? staticIPv4Rules : staticIPv6Rules).has(remoteAddr)) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
68
92
|
for (const [isIPv4, addr, mask] of cidrRules) {
|
|
69
93
|
if (isIPv4) {
|
|
70
94
|
if (remoteIPv4Addr === void 0) {
|
|
@@ -107,14 +131,21 @@ var ipRestriction = (getIP, { denyList = [], allowList = [] }, onError) => {
|
|
|
107
131
|
}
|
|
108
132
|
const type = typeof connInfo !== "string" && connInfo.remote.addressType || distinctRemoteAddr(addr);
|
|
109
133
|
const remoteData = { addr, type, isIPv4: type === "IPv4" };
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
|
|
134
|
+
try {
|
|
135
|
+
if (denyMatcher(remoteData)) {
|
|
136
|
+
if (onError) {
|
|
137
|
+
return onError({ addr, type }, c);
|
|
138
|
+
}
|
|
139
|
+
throw blockError(c);
|
|
113
140
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
141
|
+
if (allowMatcher(remoteData)) {
|
|
142
|
+
return await next();
|
|
143
|
+
}
|
|
144
|
+
} catch (e) {
|
|
145
|
+
if (e instanceof TypeError && e.code === INVALID_IP_ADDRESS_ERROR_CODE) {
|
|
146
|
+
throw blockError(c);
|
|
147
|
+
}
|
|
148
|
+
throw e;
|
|
118
149
|
}
|
|
119
150
|
if (allowLength === 0) {
|
|
120
151
|
return await next();
|
|
@@ -17,7 +17,7 @@ var jwk = (options, init) => {
|
|
|
17
17
|
let token;
|
|
18
18
|
if (credentials) {
|
|
19
19
|
const parts = credentials.split(/\s+/);
|
|
20
|
-
if (parts.length !== 2) {
|
|
20
|
+
if (parts.length !== 2 || parts[0].toLowerCase() !== "bearer") {
|
|
21
21
|
const errDescription = "invalid credentials structure";
|
|
22
22
|
throw new HTTPException(401, {
|
|
23
23
|
message: errDescription,
|
|
@@ -20,7 +20,7 @@ var jwt = (options) => {
|
|
|
20
20
|
let token;
|
|
21
21
|
if (credentials) {
|
|
22
22
|
const parts = credentials.split(/\s+/);
|
|
23
|
-
if (parts.length !== 2) {
|
|
23
|
+
if (parts.length !== 2 || parts[0].toLowerCase() !== "bearer") {
|
|
24
24
|
const errDescription = "invalid credentials structure";
|
|
25
25
|
throw new HTTPException(401, {
|
|
26
26
|
message: errDescription,
|