hono 3.12.6 → 3.12.7
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/adapter/aws-lambda/handler.js +1 -7
- package/dist/cjs/adapter/aws-lambda/handler.js +1 -7
- package/dist/cjs/helper/dev/index.js +4 -1
- package/dist/cjs/hono-base.js +4 -15
- package/dist/cjs/middleware/secure-headers/index.js +31 -21
- package/dist/cjs/utils/body.js +46 -30
- package/dist/cjs/utils/stream.js +1 -5
- package/dist/cjs/utils/url.js +15 -19
- package/dist/helper/dev/index.js +4 -1
- package/dist/hono-base.js +4 -15
- package/dist/middleware/secure-headers/index.js +31 -21
- package/dist/types/utils/url.d.ts +1 -1
- package/dist/utils/body.js +46 -30
- package/dist/utils/stream.js +1 -5
- package/dist/utils/url.js +15 -19
- package/package.json +6 -6
|
@@ -62,13 +62,7 @@ var createResult = async (event, res) => {
|
|
|
62
62
|
const contentEncoding = res.headers.get("content-encoding");
|
|
63
63
|
isBase64Encoded = isContentEncodingBinary(contentEncoding);
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
if (isBase64Encoded) {
|
|
67
|
-
const buffer = await res.arrayBuffer();
|
|
68
|
-
body = encodeBase64(buffer);
|
|
69
|
-
} else {
|
|
70
|
-
body = await res.text();
|
|
71
|
-
}
|
|
65
|
+
const body = isBase64Encoded ? encodeBase64(await res.arrayBuffer()) : await res.text();
|
|
72
66
|
const result = {
|
|
73
67
|
body,
|
|
74
68
|
headers: {},
|
|
@@ -93,13 +93,7 @@ const createResult = async (event, res) => {
|
|
|
93
93
|
const contentEncoding = res.headers.get("content-encoding");
|
|
94
94
|
isBase64Encoded = isContentEncodingBinary(contentEncoding);
|
|
95
95
|
}
|
|
96
|
-
|
|
97
|
-
if (isBase64Encoded) {
|
|
98
|
-
const buffer = await res.arrayBuffer();
|
|
99
|
-
body = (0, import_encode.encodeBase64)(buffer);
|
|
100
|
-
} else {
|
|
101
|
-
body = await res.text();
|
|
102
|
-
}
|
|
96
|
+
const body = isBase64Encoded ? (0, import_encode.encodeBase64)(await res.arrayBuffer()) : await res.text();
|
|
103
97
|
const result = {
|
|
104
98
|
body,
|
|
105
99
|
headers: {},
|
|
@@ -43,6 +43,9 @@ const inspectRoutes = (hono) => {
|
|
|
43
43
|
});
|
|
44
44
|
};
|
|
45
45
|
const showRoutes = (hono, opts) => {
|
|
46
|
+
const { process, Deno } = globalThis;
|
|
47
|
+
const isNoColor = typeof process !== "undefined" ? "NO_COLOR" in process?.env : typeof Deno?.noColor === "boolean" ? Deno.noColor : false;
|
|
48
|
+
const colorEnabled = opts?.colorize ?? !isNoColor;
|
|
46
49
|
const routeData = {};
|
|
47
50
|
let maxMethodLength = 0;
|
|
48
51
|
let maxPathLength = 0;
|
|
@@ -60,7 +63,7 @@ const showRoutes = (hono, opts) => {
|
|
|
60
63
|
return;
|
|
61
64
|
}
|
|
62
65
|
const { method, path, routes } = data;
|
|
63
|
-
const methodStr =
|
|
66
|
+
const methodStr = colorEnabled ? `\x1B[32m${method}\x1B[0m` : method;
|
|
64
67
|
console.log(`${methodStr} ${" ".repeat(maxMethodLength - method.length)} ${path}`);
|
|
65
68
|
if (!opts?.verbose) {
|
|
66
69
|
return;
|
package/dist/cjs/hono-base.js
CHANGED
|
@@ -248,27 +248,16 @@ const _Hono = class extends defineDynamicClass() {
|
|
|
248
248
|
let res;
|
|
249
249
|
try {
|
|
250
250
|
res = matchResult[0][0][0][0](c, async () => {
|
|
251
|
+
c.res = await this.notFoundHandler(c);
|
|
251
252
|
});
|
|
252
|
-
if (!res) {
|
|
253
|
-
return this.notFoundHandler(c);
|
|
254
|
-
}
|
|
255
253
|
} catch (err) {
|
|
256
254
|
return this.handleError(err, c);
|
|
257
255
|
}
|
|
258
256
|
if (res instanceof Response)
|
|
259
257
|
return res;
|
|
260
|
-
return (
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
awaited = await res;
|
|
264
|
-
if (!awaited) {
|
|
265
|
-
return this.notFoundHandler(c);
|
|
266
|
-
}
|
|
267
|
-
} catch (err) {
|
|
268
|
-
return this.handleError(err, c);
|
|
269
|
-
}
|
|
270
|
-
return awaited;
|
|
271
|
-
})();
|
|
258
|
+
return res.then(
|
|
259
|
+
(resolved) => resolved || (c.finalized ? c.res : this.notFoundHandler(c))
|
|
260
|
+
).catch((err) => this.handleError(err, c));
|
|
272
261
|
}
|
|
273
262
|
const composed = (0, import_compose.compose)(matchResult[0], this.errorHandler, this.notFoundHandler);
|
|
274
263
|
return (async () => {
|
|
@@ -51,38 +51,48 @@ const DEFAULT_OPTIONS = {
|
|
|
51
51
|
};
|
|
52
52
|
const secureHeaders = (customOptions) => {
|
|
53
53
|
const options = { ...DEFAULT_OPTIONS, ...customOptions };
|
|
54
|
-
const headersToSet =
|
|
55
|
-
const overrideValue = options[key];
|
|
56
|
-
if (typeof overrideValue === "string")
|
|
57
|
-
return [defaultValue[0], overrideValue];
|
|
58
|
-
return defaultValue;
|
|
59
|
-
});
|
|
54
|
+
const headersToSet = getFilteredHeaders(options);
|
|
60
55
|
if (options.contentSecurityPolicy) {
|
|
61
|
-
|
|
62
|
-
directive = directive.replace(
|
|
63
|
-
/[A-Z]+(?![a-z])|[A-Z]/g,
|
|
64
|
-
(match, offset) => (offset ? "-" : "") + match.toLowerCase()
|
|
65
|
-
);
|
|
66
|
-
return `${directive} ${Array.isArray(value) ? value.join(" ") : value}`;
|
|
67
|
-
}).join("; ");
|
|
68
|
-
headersToSet.push(["Content-Security-Policy", cspDirectives]);
|
|
56
|
+
headersToSet.push(["Content-Security-Policy", getCSPDirectives(options.contentSecurityPolicy)]);
|
|
69
57
|
}
|
|
70
58
|
if (options.reportingEndpoints) {
|
|
71
|
-
|
|
72
|
-
headersToSet.push(["Reporting-Endpoints", reportingEndpoints]);
|
|
59
|
+
headersToSet.push(["Reporting-Endpoints", getReportingEndpoints(options.reportingEndpoints)]);
|
|
73
60
|
}
|
|
74
61
|
if (options.reportTo) {
|
|
75
|
-
|
|
76
|
-
headersToSet.push(["Report-To", reportToOptions]);
|
|
62
|
+
headersToSet.push(["Report-To", getReportToOptions(options.reportTo)]);
|
|
77
63
|
}
|
|
78
64
|
return async function secureHeaders2(ctx, next) {
|
|
79
65
|
await next();
|
|
80
|
-
|
|
81
|
-
ctx.res.headers.set(header, value);
|
|
82
|
-
});
|
|
66
|
+
setHeaders(ctx, headersToSet);
|
|
83
67
|
ctx.res.headers.delete("X-Powered-By");
|
|
84
68
|
};
|
|
85
69
|
};
|
|
70
|
+
function getFilteredHeaders(options) {
|
|
71
|
+
return Object.entries(HEADERS_MAP).filter(([key]) => options[key]).map(([key, defaultValue]) => {
|
|
72
|
+
const overrideValue = options[key];
|
|
73
|
+
return typeof overrideValue === "string" ? [defaultValue[0], overrideValue] : defaultValue;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function getCSPDirectives(contentSecurityPolicy) {
|
|
77
|
+
return Object.entries(contentSecurityPolicy || []).map(([directive, value]) => {
|
|
78
|
+
const kebabCaseDirective = directive.replace(
|
|
79
|
+
/[A-Z]+(?![a-z])|[A-Z]/g,
|
|
80
|
+
(match, offset) => offset ? "-" + match.toLowerCase() : match.toLowerCase()
|
|
81
|
+
);
|
|
82
|
+
return `${kebabCaseDirective} ${Array.isArray(value) ? value.join(" ") : value}`;
|
|
83
|
+
}).join("; ");
|
|
84
|
+
}
|
|
85
|
+
function getReportingEndpoints(reportingEndpoints = []) {
|
|
86
|
+
return reportingEndpoints.map((endpoint) => `${endpoint.name}="${endpoint.url}"`).join(", ");
|
|
87
|
+
}
|
|
88
|
+
function getReportToOptions(reportTo = []) {
|
|
89
|
+
return reportTo.map((option) => JSON.stringify(option)).join(", ");
|
|
90
|
+
}
|
|
91
|
+
function setHeaders(ctx, headersToSet) {
|
|
92
|
+
headersToSet.forEach(([header, value]) => {
|
|
93
|
+
ctx.res.headers.set(header, value);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
86
96
|
// Annotate the CommonJS export names for ESM import in node:
|
|
87
97
|
0 && (module.exports = {
|
|
88
98
|
secureHeaders
|
package/dist/cjs/utils/body.js
CHANGED
|
@@ -21,39 +21,55 @@ __export(body_exports, {
|
|
|
21
21
|
parseBody: () => parseBody
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(body_exports);
|
|
24
|
-
const
|
|
25
|
-
return Array.isArray(value);
|
|
26
|
-
};
|
|
27
|
-
const parseBody = async (request, options = {
|
|
28
|
-
all: false
|
|
29
|
-
}) => {
|
|
30
|
-
let body = {};
|
|
24
|
+
const parseBody = async (request, options = { all: false }) => {
|
|
31
25
|
const contentType = request.headers.get("Content-Type");
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
26
|
+
if (isFormDataContent(contentType)) {
|
|
27
|
+
return parseFormData(request, options);
|
|
28
|
+
}
|
|
29
|
+
return {};
|
|
30
|
+
};
|
|
31
|
+
function isFormDataContent(contentType) {
|
|
32
|
+
if (contentType === null) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return contentType.startsWith("multipart/form-data") || contentType.startsWith("application/x-www-form-urlencoded");
|
|
36
|
+
}
|
|
37
|
+
async function parseFormData(request, options) {
|
|
38
|
+
const formData = await request.formData();
|
|
39
|
+
if (formData) {
|
|
40
|
+
return convertFormDataToBodyData(formData, options);
|
|
41
|
+
}
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
function convertFormDataToBodyData(formData, options) {
|
|
45
|
+
const form = {};
|
|
46
|
+
formData.forEach((value, key) => {
|
|
47
|
+
const shouldParseAllValues = options.all || key.endsWith("[]");
|
|
48
|
+
if (!shouldParseAllValues) {
|
|
49
|
+
form[key] = value;
|
|
50
|
+
} else {
|
|
51
|
+
handleParsingAllValues(form, key, value);
|
|
54
52
|
}
|
|
53
|
+
});
|
|
54
|
+
return form;
|
|
55
|
+
}
|
|
56
|
+
const handleParsingAllValues = (form, key, value) => {
|
|
57
|
+
if (form[key] && isArrayField(form[key])) {
|
|
58
|
+
appendToExistingArray(form[key], value);
|
|
59
|
+
} else if (form[key]) {
|
|
60
|
+
convertToNewArray(form, key, value);
|
|
61
|
+
} else {
|
|
62
|
+
form[key] = value;
|
|
55
63
|
}
|
|
56
|
-
|
|
64
|
+
};
|
|
65
|
+
function isArrayField(field) {
|
|
66
|
+
return Array.isArray(field);
|
|
67
|
+
}
|
|
68
|
+
const appendToExistingArray = (arr, value) => {
|
|
69
|
+
arr.push(value);
|
|
70
|
+
};
|
|
71
|
+
const convertToNewArray = (form, key, value) => {
|
|
72
|
+
form[key] = [form[key], value];
|
|
57
73
|
};
|
|
58
74
|
// Annotate the CommonJS export names for ESM import in node:
|
|
59
75
|
0 && (module.exports = {
|
package/dist/cjs/utils/stream.js
CHANGED
|
@@ -31,11 +31,7 @@ class StreamingApi {
|
|
|
31
31
|
this.responseReadable = new ReadableStream({
|
|
32
32
|
async pull(controller) {
|
|
33
33
|
const { done, value } = await reader.read();
|
|
34
|
-
|
|
35
|
-
controller.close();
|
|
36
|
-
} else {
|
|
37
|
-
controller.enqueue(value);
|
|
38
|
-
}
|
|
34
|
+
done ? controller.close() : controller.enqueue(value);
|
|
39
35
|
},
|
|
40
36
|
cancel: () => {
|
|
41
37
|
this.abortSubscribers.forEach((subscriber) => subscriber());
|
package/dist/cjs/utils/url.js
CHANGED
|
@@ -38,29 +38,25 @@ const splitPath = (path) => {
|
|
|
38
38
|
}
|
|
39
39
|
return paths;
|
|
40
40
|
};
|
|
41
|
-
const splitRoutingPath = (
|
|
41
|
+
const splitRoutingPath = (routePath) => {
|
|
42
|
+
const { groups, path } = extractGroupsFromPath(routePath);
|
|
43
|
+
const paths = splitPath(path);
|
|
44
|
+
return replaceGroupMarks(paths, groups);
|
|
45
|
+
};
|
|
46
|
+
const extractGroupsFromPath = (path) => {
|
|
42
47
|
const groups = [];
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
if (!replaced) {
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
const paths = path.split("/");
|
|
57
|
-
if (paths[0] === "") {
|
|
58
|
-
paths.shift();
|
|
59
|
-
}
|
|
48
|
+
path = path.replace(/\{[^}]+\}/g, (match, index) => {
|
|
49
|
+
const mark = `@${index}`;
|
|
50
|
+
groups.push([mark, match]);
|
|
51
|
+
return mark;
|
|
52
|
+
});
|
|
53
|
+
return { groups, path };
|
|
54
|
+
};
|
|
55
|
+
const replaceGroupMarks = (paths, groups) => {
|
|
60
56
|
for (let i = groups.length - 1; i >= 0; i--) {
|
|
61
57
|
const [mark] = groups[i];
|
|
62
58
|
for (let j = paths.length - 1; j >= 0; j--) {
|
|
63
|
-
if (paths[j].
|
|
59
|
+
if (paths[j].includes(mark)) {
|
|
64
60
|
paths[j] = paths[j].replace(mark, groups[i][1]);
|
|
65
61
|
break;
|
|
66
62
|
}
|
package/dist/helper/dev/index.js
CHANGED
|
@@ -19,6 +19,9 @@ var inspectRoutes = (hono) => {
|
|
|
19
19
|
});
|
|
20
20
|
};
|
|
21
21
|
var showRoutes = (hono, opts) => {
|
|
22
|
+
const { process, Deno } = globalThis;
|
|
23
|
+
const isNoColor = typeof process !== "undefined" ? "NO_COLOR" in process?.env : typeof Deno?.noColor === "boolean" ? Deno.noColor : false;
|
|
24
|
+
const colorEnabled = opts?.colorize ?? !isNoColor;
|
|
22
25
|
const routeData = {};
|
|
23
26
|
let maxMethodLength = 0;
|
|
24
27
|
let maxPathLength = 0;
|
|
@@ -36,7 +39,7 @@ var showRoutes = (hono, opts) => {
|
|
|
36
39
|
return;
|
|
37
40
|
}
|
|
38
41
|
const { method, path, routes } = data;
|
|
39
|
-
const methodStr =
|
|
42
|
+
const methodStr = colorEnabled ? `\x1B[32m${method}\x1B[0m` : method;
|
|
40
43
|
console.log(`${methodStr} ${" ".repeat(maxMethodLength - method.length)} ${path}`);
|
|
41
44
|
if (!opts?.verbose) {
|
|
42
45
|
return;
|
package/dist/hono-base.js
CHANGED
|
@@ -226,27 +226,16 @@ var _Hono = class extends defineDynamicClass() {
|
|
|
226
226
|
let res;
|
|
227
227
|
try {
|
|
228
228
|
res = matchResult[0][0][0][0](c, async () => {
|
|
229
|
+
c.res = await this.notFoundHandler(c);
|
|
229
230
|
});
|
|
230
|
-
if (!res) {
|
|
231
|
-
return this.notFoundHandler(c);
|
|
232
|
-
}
|
|
233
231
|
} catch (err) {
|
|
234
232
|
return this.handleError(err, c);
|
|
235
233
|
}
|
|
236
234
|
if (res instanceof Response)
|
|
237
235
|
return res;
|
|
238
|
-
return (
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
awaited = await res;
|
|
242
|
-
if (!awaited) {
|
|
243
|
-
return this.notFoundHandler(c);
|
|
244
|
-
}
|
|
245
|
-
} catch (err) {
|
|
246
|
-
return this.handleError(err, c);
|
|
247
|
-
}
|
|
248
|
-
return awaited;
|
|
249
|
-
})();
|
|
236
|
+
return res.then(
|
|
237
|
+
(resolved) => resolved || (c.finalized ? c.res : this.notFoundHandler(c))
|
|
238
|
+
).catch((err) => this.handleError(err, c));
|
|
250
239
|
}
|
|
251
240
|
const composed = compose(matchResult[0], this.errorHandler, this.notFoundHandler);
|
|
252
241
|
return (async () => {
|
|
@@ -29,38 +29,48 @@ var DEFAULT_OPTIONS = {
|
|
|
29
29
|
};
|
|
30
30
|
var secureHeaders = (customOptions) => {
|
|
31
31
|
const options = { ...DEFAULT_OPTIONS, ...customOptions };
|
|
32
|
-
const headersToSet =
|
|
33
|
-
const overrideValue = options[key];
|
|
34
|
-
if (typeof overrideValue === "string")
|
|
35
|
-
return [defaultValue[0], overrideValue];
|
|
36
|
-
return defaultValue;
|
|
37
|
-
});
|
|
32
|
+
const headersToSet = getFilteredHeaders(options);
|
|
38
33
|
if (options.contentSecurityPolicy) {
|
|
39
|
-
|
|
40
|
-
directive = directive.replace(
|
|
41
|
-
/[A-Z]+(?![a-z])|[A-Z]/g,
|
|
42
|
-
(match, offset) => (offset ? "-" : "") + match.toLowerCase()
|
|
43
|
-
);
|
|
44
|
-
return `${directive} ${Array.isArray(value) ? value.join(" ") : value}`;
|
|
45
|
-
}).join("; ");
|
|
46
|
-
headersToSet.push(["Content-Security-Policy", cspDirectives]);
|
|
34
|
+
headersToSet.push(["Content-Security-Policy", getCSPDirectives(options.contentSecurityPolicy)]);
|
|
47
35
|
}
|
|
48
36
|
if (options.reportingEndpoints) {
|
|
49
|
-
|
|
50
|
-
headersToSet.push(["Reporting-Endpoints", reportingEndpoints]);
|
|
37
|
+
headersToSet.push(["Reporting-Endpoints", getReportingEndpoints(options.reportingEndpoints)]);
|
|
51
38
|
}
|
|
52
39
|
if (options.reportTo) {
|
|
53
|
-
|
|
54
|
-
headersToSet.push(["Report-To", reportToOptions]);
|
|
40
|
+
headersToSet.push(["Report-To", getReportToOptions(options.reportTo)]);
|
|
55
41
|
}
|
|
56
42
|
return async function secureHeaders2(ctx, next) {
|
|
57
43
|
await next();
|
|
58
|
-
|
|
59
|
-
ctx.res.headers.set(header, value);
|
|
60
|
-
});
|
|
44
|
+
setHeaders(ctx, headersToSet);
|
|
61
45
|
ctx.res.headers.delete("X-Powered-By");
|
|
62
46
|
};
|
|
63
47
|
};
|
|
48
|
+
function getFilteredHeaders(options) {
|
|
49
|
+
return Object.entries(HEADERS_MAP).filter(([key]) => options[key]).map(([key, defaultValue]) => {
|
|
50
|
+
const overrideValue = options[key];
|
|
51
|
+
return typeof overrideValue === "string" ? [defaultValue[0], overrideValue] : defaultValue;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function getCSPDirectives(contentSecurityPolicy) {
|
|
55
|
+
return Object.entries(contentSecurityPolicy || []).map(([directive, value]) => {
|
|
56
|
+
const kebabCaseDirective = directive.replace(
|
|
57
|
+
/[A-Z]+(?![a-z])|[A-Z]/g,
|
|
58
|
+
(match, offset) => offset ? "-" + match.toLowerCase() : match.toLowerCase()
|
|
59
|
+
);
|
|
60
|
+
return `${kebabCaseDirective} ${Array.isArray(value) ? value.join(" ") : value}`;
|
|
61
|
+
}).join("; ");
|
|
62
|
+
}
|
|
63
|
+
function getReportingEndpoints(reportingEndpoints = []) {
|
|
64
|
+
return reportingEndpoints.map((endpoint) => `${endpoint.name}="${endpoint.url}"`).join(", ");
|
|
65
|
+
}
|
|
66
|
+
function getReportToOptions(reportTo = []) {
|
|
67
|
+
return reportTo.map((option) => JSON.stringify(option)).join(", ");
|
|
68
|
+
}
|
|
69
|
+
function setHeaders(ctx, headersToSet) {
|
|
70
|
+
headersToSet.forEach(([header, value]) => {
|
|
71
|
+
ctx.res.headers.set(header, value);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
64
74
|
export {
|
|
65
75
|
secureHeaders
|
|
66
76
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type Pattern = readonly [string, string, RegExp | true] | '*';
|
|
2
2
|
export declare const splitPath: (path: string) => string[];
|
|
3
|
-
export declare const splitRoutingPath: (
|
|
3
|
+
export declare const splitRoutingPath: (routePath: string) => string[];
|
|
4
4
|
export declare const getPattern: (label: string) => Pattern | null;
|
|
5
5
|
export declare const getPath: (request: Request) => string;
|
|
6
6
|
export declare const getQueryStrings: (url: string) => string;
|
package/dist/utils/body.js
CHANGED
|
@@ -1,37 +1,53 @@
|
|
|
1
1
|
// src/utils/body.ts
|
|
2
|
-
var
|
|
3
|
-
return Array.isArray(value);
|
|
4
|
-
};
|
|
5
|
-
var parseBody = async (request, options = {
|
|
6
|
-
all: false
|
|
7
|
-
}) => {
|
|
8
|
-
let body = {};
|
|
2
|
+
var parseBody = async (request, options = { all: false }) => {
|
|
9
3
|
const contentType = request.headers.get("Content-Type");
|
|
10
|
-
if (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
4
|
+
if (isFormDataContent(contentType)) {
|
|
5
|
+
return parseFormData(request, options);
|
|
6
|
+
}
|
|
7
|
+
return {};
|
|
8
|
+
};
|
|
9
|
+
function isFormDataContent(contentType) {
|
|
10
|
+
if (contentType === null) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
return contentType.startsWith("multipart/form-data") || contentType.startsWith("application/x-www-form-urlencoded");
|
|
14
|
+
}
|
|
15
|
+
async function parseFormData(request, options) {
|
|
16
|
+
const formData = await request.formData();
|
|
17
|
+
if (formData) {
|
|
18
|
+
return convertFormDataToBodyData(formData, options);
|
|
19
|
+
}
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
function convertFormDataToBodyData(formData, options) {
|
|
23
|
+
const form = {};
|
|
24
|
+
formData.forEach((value, key) => {
|
|
25
|
+
const shouldParseAllValues = options.all || key.endsWith("[]");
|
|
26
|
+
if (!shouldParseAllValues) {
|
|
27
|
+
form[key] = value;
|
|
28
|
+
} else {
|
|
29
|
+
handleParsingAllValues(form, key, value);
|
|
32
30
|
}
|
|
31
|
+
});
|
|
32
|
+
return form;
|
|
33
|
+
}
|
|
34
|
+
var handleParsingAllValues = (form, key, value) => {
|
|
35
|
+
if (form[key] && isArrayField(form[key])) {
|
|
36
|
+
appendToExistingArray(form[key], value);
|
|
37
|
+
} else if (form[key]) {
|
|
38
|
+
convertToNewArray(form, key, value);
|
|
39
|
+
} else {
|
|
40
|
+
form[key] = value;
|
|
33
41
|
}
|
|
34
|
-
|
|
42
|
+
};
|
|
43
|
+
function isArrayField(field) {
|
|
44
|
+
return Array.isArray(field);
|
|
45
|
+
}
|
|
46
|
+
var appendToExistingArray = (arr, value) => {
|
|
47
|
+
arr.push(value);
|
|
48
|
+
};
|
|
49
|
+
var convertToNewArray = (form, key, value) => {
|
|
50
|
+
form[key] = [form[key], value];
|
|
35
51
|
};
|
|
36
52
|
export {
|
|
37
53
|
parseBody
|
package/dist/utils/stream.js
CHANGED
|
@@ -9,11 +9,7 @@ var StreamingApi = class {
|
|
|
9
9
|
this.responseReadable = new ReadableStream({
|
|
10
10
|
async pull(controller) {
|
|
11
11
|
const { done, value } = await reader.read();
|
|
12
|
-
|
|
13
|
-
controller.close();
|
|
14
|
-
} else {
|
|
15
|
-
controller.enqueue(value);
|
|
16
|
-
}
|
|
12
|
+
done ? controller.close() : controller.enqueue(value);
|
|
17
13
|
},
|
|
18
14
|
cancel: () => {
|
|
19
15
|
this.abortSubscribers.forEach((subscriber) => subscriber());
|
package/dist/utils/url.js
CHANGED
|
@@ -6,29 +6,25 @@ var splitPath = (path) => {
|
|
|
6
6
|
}
|
|
7
7
|
return paths;
|
|
8
8
|
};
|
|
9
|
-
var splitRoutingPath = (
|
|
9
|
+
var splitRoutingPath = (routePath) => {
|
|
10
|
+
const { groups, path } = extractGroupsFromPath(routePath);
|
|
11
|
+
const paths = splitPath(path);
|
|
12
|
+
return replaceGroupMarks(paths, groups);
|
|
13
|
+
};
|
|
14
|
+
var extractGroupsFromPath = (path) => {
|
|
10
15
|
const groups = [];
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
});
|
|
20
|
-
if (!replaced) {
|
|
21
|
-
break;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
const paths = path.split("/");
|
|
25
|
-
if (paths[0] === "") {
|
|
26
|
-
paths.shift();
|
|
27
|
-
}
|
|
16
|
+
path = path.replace(/\{[^}]+\}/g, (match, index) => {
|
|
17
|
+
const mark = `@${index}`;
|
|
18
|
+
groups.push([mark, match]);
|
|
19
|
+
return mark;
|
|
20
|
+
});
|
|
21
|
+
return { groups, path };
|
|
22
|
+
};
|
|
23
|
+
var replaceGroupMarks = (paths, groups) => {
|
|
28
24
|
for (let i = groups.length - 1; i >= 0; i--) {
|
|
29
25
|
const [mark] = groups[i];
|
|
30
26
|
for (let j = paths.length - 1; j >= 0; j--) {
|
|
31
|
-
if (paths[j].
|
|
27
|
+
if (paths[j].includes(mark)) {
|
|
32
28
|
paths[j] = paths[j].replace(mark, groups[i][1]);
|
|
33
29
|
break;
|
|
34
30
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono",
|
|
3
|
-
"version": "3.12.
|
|
3
|
+
"version": "3.12.7",
|
|
4
4
|
"description": "Ultrafast web framework for the Edges",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
"scripts": {
|
|
13
13
|
"test": "tsc --noEmit && vitest --run",
|
|
14
14
|
"test:watch": "vitest --watch",
|
|
15
|
-
"test:deno": "
|
|
16
|
-
"test:bun": "
|
|
15
|
+
"test:deno": "deno test --allow-read --allow-env runtime_tests/deno && deno test --no-lock -c runtime_tests/deno-jsx/deno.precompile.json runtime_tests/deno-jsx && deno test --no-lock -c runtime_tests/deno-jsx/deno.react-jsx.json runtime_tests/deno-jsx",
|
|
16
|
+
"test:bun": "bun test --jsx-import-source ../../src/jsx runtime_tests/bun/index.test.tsx",
|
|
17
17
|
"test:fastly": "vitest --run --config ./runtime_tests/fastly/vitest.config.ts",
|
|
18
18
|
"test:lagon": "start-server-and-test \"lagon dev runtime_tests/lagon/index.ts -e runtime_tests/lagon/.env.lagon\" http://127.0.0.1:1234 \"yarn vitest --run runtime_tests/lagon/index.test.ts --config runtime_tests/lagon/vitest.config.ts\"",
|
|
19
|
-
"test:node": "
|
|
19
|
+
"test:node": "vitest --run --config ./runtime_tests/node/vitest.config.ts",
|
|
20
20
|
"test:wrangler": "vitest --run --config ./runtime_tests/wrangler/vitest.config.ts",
|
|
21
|
-
"test:lambda": "
|
|
22
|
-
"test:lambda-edge": "
|
|
21
|
+
"test:lambda": "vitest --run --config ./runtime_tests/lambda/vitest.config.ts",
|
|
22
|
+
"test:lambda-edge": "vitest --run --config ./runtime_tests/lambda-edge/vitest.config.ts",
|
|
23
23
|
"test:all": "yarn test && yarn test:deno && yarn test:bun && yarn test:fastly && yarn test:lagon && yarn test:node && yarn test:wrangler && yarn test:lambda && yarn test:lambda-edge",
|
|
24
24
|
"lint": "eslint --ext js,ts src runtime_tests",
|
|
25
25
|
"lint:fix": "eslint --ext js,ts src runtime_tests --fix",
|