hono 4.9.11 → 4.10.0
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/helper/proxy/index.js +28 -5
- package/dist/cjs/helper/ssg/ssg.js +11 -1
- package/dist/cjs/request.js +31 -2
- package/dist/cjs/router/reg-exp-router/matcher.js +1 -4
- package/dist/cjs/router/reg-exp-router/prepared-router.js +62 -46
- package/dist/cjs/router/reg-exp-router/router.js +1 -1
- package/dist/cjs/validator/validator.js +1 -1
- package/dist/helper/proxy/index.js +28 -5
- package/dist/helper/ssg/ssg.js +10 -1
- package/dist/request.js +29 -1
- package/dist/router/reg-exp-router/matcher.js +1 -3
- package/dist/router/reg-exp-router/prepared-router.js +63 -47
- package/dist/router/reg-exp-router/router.js +2 -2
- package/dist/types/helper/factory/index.d.ts +2 -2
- package/dist/types/helper/proxy/index.d.ts +20 -0
- package/dist/types/helper/ssg/ssg.d.ts +8 -0
- package/dist/types/request.d.ts +32 -0
- package/dist/types/router/reg-exp-router/matcher.d.ts +0 -1
- package/dist/types/router/reg-exp-router/prepared-router.d.ts +7 -5
- package/dist/types/router/reg-exp-router/router.d.ts +2 -2
- package/dist/types/types.d.ts +142 -132
- package/dist/types/validator/validator.d.ts +11 -10
- package/dist/validator/validator.js +1 -1
- package/package.json +1 -1
|
@@ -21,20 +21,38 @@ __export(proxy_exports, {
|
|
|
21
21
|
proxy: () => proxy
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(proxy_exports);
|
|
24
|
+
var import_http_exception = require("../../http-exception");
|
|
24
25
|
const hopByHopHeaders = [
|
|
25
26
|
"connection",
|
|
26
27
|
"keep-alive",
|
|
27
28
|
"proxy-authenticate",
|
|
28
29
|
"proxy-authorization",
|
|
29
30
|
"te",
|
|
30
|
-
"
|
|
31
|
-
"transfer-encoding"
|
|
31
|
+
"trailer",
|
|
32
|
+
"transfer-encoding",
|
|
33
|
+
"upgrade"
|
|
32
34
|
];
|
|
33
|
-
const
|
|
35
|
+
const ALLOWED_TOKEN_PATTERN = /^[!#$%&'*+\-.0-9A-Z^_`a-z|~]+$/;
|
|
36
|
+
const buildRequestInitFromRequest = (request, strictConnectionProcessing) => {
|
|
34
37
|
if (!request) {
|
|
35
38
|
return {};
|
|
36
39
|
}
|
|
37
40
|
const headers = new Headers(request.headers);
|
|
41
|
+
if (strictConnectionProcessing) {
|
|
42
|
+
const connectionValue = headers.get("connection");
|
|
43
|
+
if (connectionValue) {
|
|
44
|
+
const headerNames = connectionValue.split(",").map((h) => h.trim());
|
|
45
|
+
const invalidHeaders = headerNames.filter((h) => !ALLOWED_TOKEN_PATTERN.test(h));
|
|
46
|
+
if (invalidHeaders.length > 0) {
|
|
47
|
+
throw new import_http_exception.HTTPException(400, {
|
|
48
|
+
message: `Invalid Connection header value: ${invalidHeaders.join(", ")}`
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
headerNames.forEach((headerName) => {
|
|
52
|
+
headers.delete(headerName);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
38
56
|
hopByHopHeaders.forEach((header) => {
|
|
39
57
|
headers.delete(header);
|
|
40
58
|
});
|
|
@@ -62,9 +80,14 @@ const preprocessRequestInit = (requestInit) => {
|
|
|
62
80
|
return requestInit;
|
|
63
81
|
};
|
|
64
82
|
const proxy = async (input, proxyInit) => {
|
|
65
|
-
const {
|
|
83
|
+
const {
|
|
84
|
+
raw,
|
|
85
|
+
customFetch,
|
|
86
|
+
strictConnectionProcessing = false,
|
|
87
|
+
...requestInit
|
|
88
|
+
} = proxyInit instanceof Request ? { raw: proxyInit } : proxyInit ?? {};
|
|
66
89
|
const req = new Request(input, {
|
|
67
|
-
...buildRequestInitFromRequest(raw),
|
|
90
|
+
...buildRequestInitFromRequest(raw, strictConnectionProcessing),
|
|
68
91
|
...preprocessRequestInit(requestInit)
|
|
69
92
|
});
|
|
70
93
|
req.headers.delete("accept-encoding");
|
|
@@ -23,6 +23,7 @@ __export(ssg_exports, {
|
|
|
23
23
|
combineAfterResponseHooks: () => combineAfterResponseHooks,
|
|
24
24
|
combineBeforeRequestHooks: () => combineBeforeRequestHooks,
|
|
25
25
|
defaultExtensionMap: () => defaultExtensionMap,
|
|
26
|
+
defaultPlugin: () => defaultPlugin,
|
|
26
27
|
fetchRoutesContent: () => fetchRoutesContent,
|
|
27
28
|
saveContentToFile: () => saveContentToFile,
|
|
28
29
|
toSSG: () => toSSG
|
|
@@ -213,11 +214,19 @@ const saveContentToFile = async (data, fsModule, outDir, extensionMap) => {
|
|
|
213
214
|
}
|
|
214
215
|
return filePath;
|
|
215
216
|
};
|
|
217
|
+
const defaultPlugin = {
|
|
218
|
+
afterResponseHook: (res) => {
|
|
219
|
+
if (res.status !== 200) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
return res;
|
|
223
|
+
}
|
|
224
|
+
};
|
|
216
225
|
const toSSG = async (app, fs, options) => {
|
|
217
226
|
let result;
|
|
218
227
|
const getInfoPromises = [];
|
|
219
228
|
const savePromises = [];
|
|
220
|
-
const plugins = options?.plugins || [];
|
|
229
|
+
const plugins = options?.plugins || [defaultPlugin];
|
|
221
230
|
const beforeRequestHooks = [];
|
|
222
231
|
const afterResponseHooks = [];
|
|
223
232
|
const afterGenerateHooks = [];
|
|
@@ -310,6 +319,7 @@ const toSSG = async (app, fs, options) => {
|
|
|
310
319
|
combineAfterResponseHooks,
|
|
311
320
|
combineBeforeRequestHooks,
|
|
312
321
|
defaultExtensionMap,
|
|
322
|
+
defaultPlugin,
|
|
313
323
|
fetchRoutesContent,
|
|
314
324
|
saveContentToFile,
|
|
315
325
|
toSSG
|
package/dist/cjs/request.js
CHANGED
|
@@ -18,9 +18,11 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var request_exports = {};
|
|
20
20
|
__export(request_exports, {
|
|
21
|
-
HonoRequest: () => HonoRequest
|
|
21
|
+
HonoRequest: () => HonoRequest,
|
|
22
|
+
cloneRawRequest: () => cloneRawRequest
|
|
22
23
|
});
|
|
23
24
|
module.exports = __toCommonJS(request_exports);
|
|
25
|
+
var import_http_exception = require("./http-exception");
|
|
24
26
|
var import_constants = require("./request/constants");
|
|
25
27
|
var import_body = require("./utils/body");
|
|
26
28
|
var import_url = require("./utils/url");
|
|
@@ -133,7 +135,34 @@ class HonoRequest {
|
|
|
133
135
|
return this.#matchResult[0].map(([[, route]]) => route)[this.routeIndex].path;
|
|
134
136
|
}
|
|
135
137
|
}
|
|
138
|
+
const cloneRawRequest = async (req) => {
|
|
139
|
+
if (!req.raw.bodyUsed) {
|
|
140
|
+
return req.raw.clone();
|
|
141
|
+
}
|
|
142
|
+
const cacheKey = Object.keys(req.bodyCache)[0];
|
|
143
|
+
if (!cacheKey) {
|
|
144
|
+
throw new import_http_exception.HTTPException(500, {
|
|
145
|
+
message: "Cannot clone request: body was already consumed and not cached. Please use HonoRequest methods (e.g., req.json(), req.text()) instead of consuming req.raw directly."
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
const requestInit = {
|
|
149
|
+
body: await req[cacheKey](),
|
|
150
|
+
cache: req.raw.cache,
|
|
151
|
+
credentials: req.raw.credentials,
|
|
152
|
+
headers: req.header(),
|
|
153
|
+
integrity: req.raw.integrity,
|
|
154
|
+
keepalive: req.raw.keepalive,
|
|
155
|
+
method: req.method,
|
|
156
|
+
mode: req.raw.mode,
|
|
157
|
+
redirect: req.raw.redirect,
|
|
158
|
+
referrer: req.raw.referrer,
|
|
159
|
+
referrerPolicy: req.raw.referrerPolicy,
|
|
160
|
+
signal: req.raw.signal
|
|
161
|
+
};
|
|
162
|
+
return new Request(req.url, requestInit);
|
|
163
|
+
};
|
|
136
164
|
// Annotate the CommonJS export names for ESM import in node:
|
|
137
165
|
0 && (module.exports = {
|
|
138
|
-
HonoRequest
|
|
166
|
+
HonoRequest,
|
|
167
|
+
cloneRawRequest
|
|
139
168
|
});
|
|
@@ -18,16 +18,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var matcher_exports = {};
|
|
20
20
|
__export(matcher_exports, {
|
|
21
|
-
buildAllMatchersKey: () => buildAllMatchersKey,
|
|
22
21
|
emptyParam: () => emptyParam,
|
|
23
22
|
match: () => match
|
|
24
23
|
});
|
|
25
24
|
module.exports = __toCommonJS(matcher_exports);
|
|
26
25
|
var import_router = require("../../router");
|
|
27
26
|
const emptyParam = [];
|
|
28
|
-
const buildAllMatchersKey = Symbol("buildAllMatchers");
|
|
29
27
|
function match(method, path) {
|
|
30
|
-
const matchers = this
|
|
28
|
+
const matchers = this.buildAllMatchers();
|
|
31
29
|
const match2 = (method2, path2) => {
|
|
32
30
|
const matcher = matchers[method2] || matchers[import_router.METHOD_NAME_ALL];
|
|
33
31
|
const staticMatch = matcher[2][path2];
|
|
@@ -46,7 +44,6 @@ function match(method, path) {
|
|
|
46
44
|
}
|
|
47
45
|
// Annotate the CommonJS export names for ESM import in node:
|
|
48
46
|
0 && (module.exports = {
|
|
49
|
-
buildAllMatchersKey,
|
|
50
47
|
emptyParam,
|
|
51
48
|
match
|
|
52
49
|
});
|
|
@@ -34,25 +34,48 @@ class PreparedRegExpRouter {
|
|
|
34
34
|
this.#matchers = matchers;
|
|
35
35
|
this.#relocateMap = relocateMap;
|
|
36
36
|
}
|
|
37
|
+
#addWildcard(method, handlerData) {
|
|
38
|
+
const matcher = this.#matchers[method];
|
|
39
|
+
matcher[1].forEach((list) => list && list.push(handlerData));
|
|
40
|
+
Object.values(matcher[2]).forEach((list) => list[0].push(handlerData));
|
|
41
|
+
}
|
|
42
|
+
#addPath(method, path, handler, indexes, map) {
|
|
43
|
+
const matcher = this.#matchers[method];
|
|
44
|
+
if (!map) {
|
|
45
|
+
matcher[2][path][0].push([handler, {}]);
|
|
46
|
+
} else {
|
|
47
|
+
indexes.forEach((index) => {
|
|
48
|
+
if (typeof index === "number") {
|
|
49
|
+
matcher[1][index].push([handler, map]);
|
|
50
|
+
} else {
|
|
51
|
+
;
|
|
52
|
+
matcher[2][index || path][0].push([handler, map]);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
37
57
|
add(method, path, handler) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
58
|
+
if (!this.#matchers[method]) {
|
|
59
|
+
const all = this.#matchers[import_router.METHOD_NAME_ALL];
|
|
60
|
+
const staticMap = {};
|
|
61
|
+
for (const key in all[2]) {
|
|
62
|
+
staticMap[key] = [all[2][key][0].slice(), import_matcher.emptyParam];
|
|
63
|
+
}
|
|
64
|
+
this.#matchers[method] = [
|
|
65
|
+
all[0],
|
|
66
|
+
all[1].map((list) => Array.isArray(list) ? list.slice() : 0),
|
|
67
|
+
staticMap
|
|
68
|
+
];
|
|
69
|
+
}
|
|
47
70
|
if (path === "/*" || path === "*") {
|
|
48
|
-
const
|
|
49
|
-
(method === import_router.METHOD_NAME_ALL
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
);
|
|
55
|
-
}
|
|
71
|
+
const handlerData = [handler, {}];
|
|
72
|
+
if (method === import_router.METHOD_NAME_ALL) {
|
|
73
|
+
for (const m in this.#matchers) {
|
|
74
|
+
this.#addWildcard(m, handlerData);
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
this.#addWildcard(method, handlerData);
|
|
78
|
+
}
|
|
56
79
|
return;
|
|
57
80
|
}
|
|
58
81
|
const data = this.#relocateMap[path];
|
|
@@ -60,38 +83,37 @@ class PreparedRegExpRouter {
|
|
|
60
83
|
throw new Error(`Path ${path} is not registered`);
|
|
61
84
|
}
|
|
62
85
|
for (const [indexes, map] of data) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (!map) {
|
|
67
|
-
matcher[2][path][0].push([handler, {}]);
|
|
68
|
-
} else {
|
|
69
|
-
indexes.forEach((index) => {
|
|
70
|
-
if (typeof index === "number") {
|
|
71
|
-
matcher[1][index].push([handler, map]);
|
|
72
|
-
} else {
|
|
73
|
-
;
|
|
74
|
-
matcher[2][index || path][0].push([handler, map]);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
86
|
+
if (method === import_router.METHOD_NAME_ALL) {
|
|
87
|
+
for (const m in this.#matchers) {
|
|
88
|
+
this.#addPath(m, path, handler, indexes, map);
|
|
77
89
|
}
|
|
78
|
-
}
|
|
90
|
+
} else {
|
|
91
|
+
this.#addPath(method, path, handler, indexes, map);
|
|
92
|
+
}
|
|
79
93
|
}
|
|
80
94
|
}
|
|
81
|
-
|
|
95
|
+
buildAllMatchers() {
|
|
82
96
|
return this.#matchers;
|
|
83
97
|
}
|
|
84
98
|
match = import_matcher.match;
|
|
85
99
|
}
|
|
86
100
|
const buildInitParams = ({ paths }) => {
|
|
87
|
-
const
|
|
101
|
+
const RegExpRouterWithMatcherExport = class extends import_router2.RegExpRouter {
|
|
102
|
+
buildAndExportAllMatchers() {
|
|
103
|
+
return this.buildAllMatchers();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const router = new RegExpRouterWithMatcherExport();
|
|
88
107
|
for (const path of paths) {
|
|
89
108
|
router.add(import_router.METHOD_NAME_ALL, path, path);
|
|
90
109
|
}
|
|
91
|
-
const matchers = router
|
|
110
|
+
const matchers = router.buildAndExportAllMatchers();
|
|
92
111
|
const all = matchers[import_router.METHOD_NAME_ALL];
|
|
93
112
|
const relocateMap = {};
|
|
94
113
|
for (const path of paths) {
|
|
114
|
+
if (path === "/*" || path === "*") {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
95
117
|
all[1].forEach((list, i) => {
|
|
96
118
|
list.forEach(([p, map]) => {
|
|
97
119
|
if (p === path) {
|
|
@@ -112,7 +134,7 @@ const buildInitParams = ({ paths }) => {
|
|
|
112
134
|
for (const path2 in all[2]) {
|
|
113
135
|
all[2][path2][0].forEach(([p]) => {
|
|
114
136
|
if (p === path) {
|
|
115
|
-
relocateMap[path] ||= [[[]
|
|
137
|
+
relocateMap[path] ||= [[[]]];
|
|
116
138
|
const value = path2 === path ? "" : path2;
|
|
117
139
|
if (relocateMap[path][0][0].findIndex((v) => v === value) === -1) {
|
|
118
140
|
relocateMap[path][0][0].push(value);
|
|
@@ -130,16 +152,10 @@ const buildInitParams = ({ paths }) => {
|
|
|
130
152
|
return [matchers, relocateMap];
|
|
131
153
|
};
|
|
132
154
|
const serializeInitParams = ([matchers, relocateMap]) => {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
const matchersStr = JSON.stringify(matchers).replace(
|
|
140
|
-
/"@(.+?)@"/g,
|
|
141
|
-
(_, str) => str.replace(/\\\\/g, "\\")
|
|
142
|
-
);
|
|
155
|
+
const matchersStr = JSON.stringify(
|
|
156
|
+
matchers,
|
|
157
|
+
(_, value) => value instanceof RegExp ? `##${value.toString()}##` : value
|
|
158
|
+
).replace(/"##(.+?)##"/g, (_, str) => str.replace(/\\\\/g, "\\"));
|
|
143
159
|
const relocateMapStr = JSON.stringify(relocateMap);
|
|
144
160
|
return `[${matchersStr},${relocateMapStr}]`;
|
|
145
161
|
};
|
|
@@ -173,7 +173,7 @@ class RegExpRouter {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
match = import_matcher.match;
|
|
176
|
-
|
|
176
|
+
buildAllMatchers() {
|
|
177
177
|
const matchers = /* @__PURE__ */ Object.create(null);
|
|
178
178
|
Object.keys(this.#routes).concat(Object.keys(this.#middleware)).forEach((method) => {
|
|
179
179
|
matchers[method] ||= this.#buildMatcher(method);
|
|
@@ -1,18 +1,36 @@
|
|
|
1
1
|
// src/helper/proxy/index.ts
|
|
2
|
+
import { HTTPException } from "../../http-exception.js";
|
|
2
3
|
var hopByHopHeaders = [
|
|
3
4
|
"connection",
|
|
4
5
|
"keep-alive",
|
|
5
6
|
"proxy-authenticate",
|
|
6
7
|
"proxy-authorization",
|
|
7
8
|
"te",
|
|
8
|
-
"
|
|
9
|
-
"transfer-encoding"
|
|
9
|
+
"trailer",
|
|
10
|
+
"transfer-encoding",
|
|
11
|
+
"upgrade"
|
|
10
12
|
];
|
|
11
|
-
var
|
|
13
|
+
var ALLOWED_TOKEN_PATTERN = /^[!#$%&'*+\-.0-9A-Z^_`a-z|~]+$/;
|
|
14
|
+
var buildRequestInitFromRequest = (request, strictConnectionProcessing) => {
|
|
12
15
|
if (!request) {
|
|
13
16
|
return {};
|
|
14
17
|
}
|
|
15
18
|
const headers = new Headers(request.headers);
|
|
19
|
+
if (strictConnectionProcessing) {
|
|
20
|
+
const connectionValue = headers.get("connection");
|
|
21
|
+
if (connectionValue) {
|
|
22
|
+
const headerNames = connectionValue.split(",").map((h) => h.trim());
|
|
23
|
+
const invalidHeaders = headerNames.filter((h) => !ALLOWED_TOKEN_PATTERN.test(h));
|
|
24
|
+
if (invalidHeaders.length > 0) {
|
|
25
|
+
throw new HTTPException(400, {
|
|
26
|
+
message: `Invalid Connection header value: ${invalidHeaders.join(", ")}`
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
headerNames.forEach((headerName) => {
|
|
30
|
+
headers.delete(headerName);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
16
34
|
hopByHopHeaders.forEach((header) => {
|
|
17
35
|
headers.delete(header);
|
|
18
36
|
});
|
|
@@ -40,9 +58,14 @@ var preprocessRequestInit = (requestInit) => {
|
|
|
40
58
|
return requestInit;
|
|
41
59
|
};
|
|
42
60
|
var proxy = async (input, proxyInit) => {
|
|
43
|
-
const {
|
|
61
|
+
const {
|
|
62
|
+
raw,
|
|
63
|
+
customFetch,
|
|
64
|
+
strictConnectionProcessing = false,
|
|
65
|
+
...requestInit
|
|
66
|
+
} = proxyInit instanceof Request ? { raw: proxyInit } : proxyInit ?? {};
|
|
44
67
|
const req = new Request(input, {
|
|
45
|
-
...buildRequestInitFromRequest(raw),
|
|
68
|
+
...buildRequestInitFromRequest(raw, strictConnectionProcessing),
|
|
46
69
|
...preprocessRequestInit(requestInit)
|
|
47
70
|
});
|
|
48
71
|
req.headers.delete("accept-encoding");
|
package/dist/helper/ssg/ssg.js
CHANGED
|
@@ -184,11 +184,19 @@ var saveContentToFile = async (data, fsModule, outDir, extensionMap) => {
|
|
|
184
184
|
}
|
|
185
185
|
return filePath;
|
|
186
186
|
};
|
|
187
|
+
var defaultPlugin = {
|
|
188
|
+
afterResponseHook: (res) => {
|
|
189
|
+
if (res.status !== 200) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
return res;
|
|
193
|
+
}
|
|
194
|
+
};
|
|
187
195
|
var toSSG = async (app, fs, options) => {
|
|
188
196
|
let result;
|
|
189
197
|
const getInfoPromises = [];
|
|
190
198
|
const savePromises = [];
|
|
191
|
-
const plugins = options?.plugins || [];
|
|
199
|
+
const plugins = options?.plugins || [defaultPlugin];
|
|
192
200
|
const beforeRequestHooks = [];
|
|
193
201
|
const afterResponseHooks = [];
|
|
194
202
|
const afterGenerateHooks = [];
|
|
@@ -280,6 +288,7 @@ export {
|
|
|
280
288
|
combineAfterResponseHooks,
|
|
281
289
|
combineBeforeRequestHooks,
|
|
282
290
|
defaultExtensionMap,
|
|
291
|
+
defaultPlugin,
|
|
283
292
|
fetchRoutesContent,
|
|
284
293
|
saveContentToFile,
|
|
285
294
|
toSSG
|
package/dist/request.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/request.ts
|
|
2
|
+
import { HTTPException } from "./http-exception.js";
|
|
2
3
|
import { GET_MATCH_RESULT } from "./request/constants.js";
|
|
3
4
|
import { parseBody } from "./utils/body.js";
|
|
4
5
|
import { decodeURIComponent_, getQueryParam, getQueryParams, tryDecode } from "./utils/url.js";
|
|
@@ -111,6 +112,33 @@ var HonoRequest = class {
|
|
|
111
112
|
return this.#matchResult[0].map(([[, route]]) => route)[this.routeIndex].path;
|
|
112
113
|
}
|
|
113
114
|
};
|
|
115
|
+
var cloneRawRequest = async (req) => {
|
|
116
|
+
if (!req.raw.bodyUsed) {
|
|
117
|
+
return req.raw.clone();
|
|
118
|
+
}
|
|
119
|
+
const cacheKey = Object.keys(req.bodyCache)[0];
|
|
120
|
+
if (!cacheKey) {
|
|
121
|
+
throw new HTTPException(500, {
|
|
122
|
+
message: "Cannot clone request: body was already consumed and not cached. Please use HonoRequest methods (e.g., req.json(), req.text()) instead of consuming req.raw directly."
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
const requestInit = {
|
|
126
|
+
body: await req[cacheKey](),
|
|
127
|
+
cache: req.raw.cache,
|
|
128
|
+
credentials: req.raw.credentials,
|
|
129
|
+
headers: req.header(),
|
|
130
|
+
integrity: req.raw.integrity,
|
|
131
|
+
keepalive: req.raw.keepalive,
|
|
132
|
+
method: req.method,
|
|
133
|
+
mode: req.raw.mode,
|
|
134
|
+
redirect: req.raw.redirect,
|
|
135
|
+
referrer: req.raw.referrer,
|
|
136
|
+
referrerPolicy: req.raw.referrerPolicy,
|
|
137
|
+
signal: req.raw.signal
|
|
138
|
+
};
|
|
139
|
+
return new Request(req.url, requestInit);
|
|
140
|
+
};
|
|
114
141
|
export {
|
|
115
|
-
HonoRequest
|
|
142
|
+
HonoRequest,
|
|
143
|
+
cloneRawRequest
|
|
116
144
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// src/router/reg-exp-router/matcher.ts
|
|
2
2
|
import { METHOD_NAME_ALL } from "../../router.js";
|
|
3
3
|
var emptyParam = [];
|
|
4
|
-
var buildAllMatchersKey = Symbol("buildAllMatchers");
|
|
5
4
|
function match(method, path) {
|
|
6
|
-
const matchers = this
|
|
5
|
+
const matchers = this.buildAllMatchers();
|
|
7
6
|
const match2 = (method2, path2) => {
|
|
8
7
|
const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
|
|
9
8
|
const staticMatch = matcher[2][path2];
|
|
@@ -21,7 +20,6 @@ function match(method, path) {
|
|
|
21
20
|
return match2(method, path);
|
|
22
21
|
}
|
|
23
22
|
export {
|
|
24
|
-
buildAllMatchersKey,
|
|
25
23
|
emptyParam,
|
|
26
24
|
match
|
|
27
25
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/router/reg-exp-router/prepared-router.ts
|
|
2
2
|
import { METHOD_NAME_ALL } from "../../router.js";
|
|
3
|
-
import { match,
|
|
3
|
+
import { match, emptyParam } from "./matcher.js";
|
|
4
4
|
import { RegExpRouter } from "./router.js";
|
|
5
5
|
var PreparedRegExpRouter = class {
|
|
6
6
|
name = "PreparedRegExpRouter";
|
|
@@ -10,25 +10,48 @@ var PreparedRegExpRouter = class {
|
|
|
10
10
|
this.#matchers = matchers;
|
|
11
11
|
this.#relocateMap = relocateMap;
|
|
12
12
|
}
|
|
13
|
+
#addWildcard(method, handlerData) {
|
|
14
|
+
const matcher = this.#matchers[method];
|
|
15
|
+
matcher[1].forEach((list) => list && list.push(handlerData));
|
|
16
|
+
Object.values(matcher[2]).forEach((list) => list[0].push(handlerData));
|
|
17
|
+
}
|
|
18
|
+
#addPath(method, path, handler, indexes, map) {
|
|
19
|
+
const matcher = this.#matchers[method];
|
|
20
|
+
if (!map) {
|
|
21
|
+
matcher[2][path][0].push([handler, {}]);
|
|
22
|
+
} else {
|
|
23
|
+
indexes.forEach((index) => {
|
|
24
|
+
if (typeof index === "number") {
|
|
25
|
+
matcher[1][index].push([handler, map]);
|
|
26
|
+
} else {
|
|
27
|
+
;
|
|
28
|
+
matcher[2][index || path][0].push([handler, map]);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
13
33
|
add(method, path, handler) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
34
|
+
if (!this.#matchers[method]) {
|
|
35
|
+
const all = this.#matchers[METHOD_NAME_ALL];
|
|
36
|
+
const staticMap = {};
|
|
37
|
+
for (const key in all[2]) {
|
|
38
|
+
staticMap[key] = [all[2][key][0].slice(), emptyParam];
|
|
39
|
+
}
|
|
40
|
+
this.#matchers[method] = [
|
|
41
|
+
all[0],
|
|
42
|
+
all[1].map((list) => Array.isArray(list) ? list.slice() : 0),
|
|
43
|
+
staticMap
|
|
44
|
+
];
|
|
45
|
+
}
|
|
23
46
|
if (path === "/*" || path === "*") {
|
|
24
|
-
const
|
|
25
|
-
(method === METHOD_NAME_ALL
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
);
|
|
31
|
-
}
|
|
47
|
+
const handlerData = [handler, {}];
|
|
48
|
+
if (method === METHOD_NAME_ALL) {
|
|
49
|
+
for (const m in this.#matchers) {
|
|
50
|
+
this.#addWildcard(m, handlerData);
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
this.#addWildcard(method, handlerData);
|
|
54
|
+
}
|
|
32
55
|
return;
|
|
33
56
|
}
|
|
34
57
|
const data = this.#relocateMap[path];
|
|
@@ -36,38 +59,37 @@ var PreparedRegExpRouter = class {
|
|
|
36
59
|
throw new Error(`Path ${path} is not registered`);
|
|
37
60
|
}
|
|
38
61
|
for (const [indexes, map] of data) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (!map) {
|
|
43
|
-
matcher[2][path][0].push([handler, {}]);
|
|
44
|
-
} else {
|
|
45
|
-
indexes.forEach((index) => {
|
|
46
|
-
if (typeof index === "number") {
|
|
47
|
-
matcher[1][index].push([handler, map]);
|
|
48
|
-
} else {
|
|
49
|
-
;
|
|
50
|
-
matcher[2][index || path][0].push([handler, map]);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
62
|
+
if (method === METHOD_NAME_ALL) {
|
|
63
|
+
for (const m in this.#matchers) {
|
|
64
|
+
this.#addPath(m, path, handler, indexes, map);
|
|
53
65
|
}
|
|
54
|
-
}
|
|
66
|
+
} else {
|
|
67
|
+
this.#addPath(method, path, handler, indexes, map);
|
|
68
|
+
}
|
|
55
69
|
}
|
|
56
70
|
}
|
|
57
|
-
|
|
71
|
+
buildAllMatchers() {
|
|
58
72
|
return this.#matchers;
|
|
59
73
|
}
|
|
60
74
|
match = match;
|
|
61
75
|
};
|
|
62
76
|
var buildInitParams = ({ paths }) => {
|
|
63
|
-
const
|
|
77
|
+
const RegExpRouterWithMatcherExport = class extends RegExpRouter {
|
|
78
|
+
buildAndExportAllMatchers() {
|
|
79
|
+
return this.buildAllMatchers();
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const router = new RegExpRouterWithMatcherExport();
|
|
64
83
|
for (const path of paths) {
|
|
65
84
|
router.add(METHOD_NAME_ALL, path, path);
|
|
66
85
|
}
|
|
67
|
-
const matchers = router
|
|
86
|
+
const matchers = router.buildAndExportAllMatchers();
|
|
68
87
|
const all = matchers[METHOD_NAME_ALL];
|
|
69
88
|
const relocateMap = {};
|
|
70
89
|
for (const path of paths) {
|
|
90
|
+
if (path === "/*" || path === "*") {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
71
93
|
all[1].forEach((list, i) => {
|
|
72
94
|
list.forEach(([p, map]) => {
|
|
73
95
|
if (p === path) {
|
|
@@ -88,7 +110,7 @@ var buildInitParams = ({ paths }) => {
|
|
|
88
110
|
for (const path2 in all[2]) {
|
|
89
111
|
all[2][path2][0].forEach(([p]) => {
|
|
90
112
|
if (p === path) {
|
|
91
|
-
relocateMap[path] ||= [[[]
|
|
113
|
+
relocateMap[path] ||= [[[]]];
|
|
92
114
|
const value = path2 === path ? "" : path2;
|
|
93
115
|
if (relocateMap[path][0][0].findIndex((v) => v === value) === -1) {
|
|
94
116
|
relocateMap[path][0][0].push(value);
|
|
@@ -106,16 +128,10 @@ var buildInitParams = ({ paths }) => {
|
|
|
106
128
|
return [matchers, relocateMap];
|
|
107
129
|
};
|
|
108
130
|
var serializeInitParams = ([matchers, relocateMap]) => {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
const matchersStr = JSON.stringify(matchers).replace(
|
|
116
|
-
/"@(.+?)@"/g,
|
|
117
|
-
(_, str) => str.replace(/\\\\/g, "\\")
|
|
118
|
-
);
|
|
131
|
+
const matchersStr = JSON.stringify(
|
|
132
|
+
matchers,
|
|
133
|
+
(_, value) => value instanceof RegExp ? `##${value.toString()}##` : value
|
|
134
|
+
).replace(/"##(.+?)##"/g, (_, str) => str.replace(/\\\\/g, "\\"));
|
|
119
135
|
const relocateMapStr = JSON.stringify(relocateMap);
|
|
120
136
|
return `[${matchersStr},${relocateMapStr}]`;
|
|
121
137
|
};
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
UnsupportedPathError
|
|
6
6
|
} from "../../router.js";
|
|
7
7
|
import { checkOptionalParameter } from "../../utils/url.js";
|
|
8
|
-
import { match, emptyParam
|
|
8
|
+
import { match, emptyParam } from "./matcher.js";
|
|
9
9
|
import { PATH_ERROR } from "./node.js";
|
|
10
10
|
import { Trie } from "./trie.js";
|
|
11
11
|
var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
|
|
@@ -155,7 +155,7 @@ var RegExpRouter = class {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
match = match;
|
|
158
|
-
|
|
158
|
+
buildAllMatchers() {
|
|
159
159
|
const matchers = /* @__PURE__ */ Object.create(null);
|
|
160
160
|
Object.keys(this.#routes).concat(Object.keys(this.#middleware)).forEach((method) => {
|
|
161
161
|
matchers[method] ||= this.#buildMatcher(method);
|