hono 4.5.9 → 4.5.11
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/README.md +1 -1
- package/dist/cjs/jsx/base.js +1 -1
- package/dist/cjs/jsx/components.js +10 -5
- package/dist/cjs/jsx/intrinsic-element/components.js +15 -3
- package/dist/cjs/middleware/basic-auth/index.js +2 -20
- package/dist/cjs/middleware/compress/index.js +15 -0
- package/dist/cjs/middleware/logger/index.js +1 -1
- package/dist/cjs/utils/basic-auth.js +46 -0
- package/dist/cjs/utils/body.js +1 -1
- package/dist/jsx/base.js +1 -1
- package/dist/jsx/components.js +10 -5
- package/dist/jsx/intrinsic-element/components.js +15 -3
- package/dist/middleware/basic-auth/index.js +2 -20
- package/dist/middleware/compress/index.js +15 -0
- package/dist/middleware/logger/index.js +1 -1
- package/dist/types/jsx/intrinsic-elements.d.ts +22 -9
- package/dist/types/middleware/compress/index.d.ts +2 -0
- package/dist/types/middleware/jsx-renderer/index.d.ts +1 -1
- package/dist/types/utils/basic-auth.d.ts +5 -0
- package/dist/utils/basic-auth.js +23 -0
- package/dist/utils/body.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -71,7 +71,7 @@ Contributions Welcome! You can contribute in the following ways.
|
|
|
71
71
|
- Create an Issue - Propose a new feature. Report a bug.
|
|
72
72
|
- Pull Request - Fix a bug and typo. Refactor the code.
|
|
73
73
|
- Create third-party middleware - Instruct below.
|
|
74
|
-
- Share - Share your thoughts on the Blog,
|
|
74
|
+
- Share - Share your thoughts on the Blog, X, and others.
|
|
75
75
|
- Make your application - Please try to use Hono.
|
|
76
76
|
|
|
77
77
|
For more details, see [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md).
|
package/dist/cjs/jsx/base.js
CHANGED
|
@@ -271,7 +271,7 @@ const jsxFn = (tag, props, children) => {
|
|
|
271
271
|
props,
|
|
272
272
|
children
|
|
273
273
|
);
|
|
274
|
-
} else if (tag === "svg") {
|
|
274
|
+
} else if (tag === "svg" || tag === "head") {
|
|
275
275
|
nameSpaceContext ||= (0, import_context.createContext)("");
|
|
276
276
|
return new JSXNode(tag, props, [
|
|
277
277
|
new JSXFunctionNode(
|
|
@@ -71,11 +71,11 @@ const ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) =>
|
|
|
71
71
|
const index = errorBoundaryCounter++;
|
|
72
72
|
const replaceRe = RegExp(`(<template id="E:${index}"></template>.*?)(.*?)(<!--E:${index}-->)`);
|
|
73
73
|
const caught = false;
|
|
74
|
-
const catchCallback = ({ error, buffer }) => {
|
|
74
|
+
const catchCallback = ({ error: error2, buffer }) => {
|
|
75
75
|
if (caught) {
|
|
76
76
|
return "";
|
|
77
77
|
}
|
|
78
|
-
const fallbackResString = fallbackRes(
|
|
78
|
+
const fallbackResString = fallbackRes(error2);
|
|
79
79
|
if (buffer) {
|
|
80
80
|
buffer[0] = buffer[0].replace(replaceRe, fallbackResString);
|
|
81
81
|
}
|
|
@@ -89,12 +89,17 @@ d.replaceWith(c.content)
|
|
|
89
89
|
})(document)
|
|
90
90
|
<\/script>`;
|
|
91
91
|
};
|
|
92
|
+
let error;
|
|
93
|
+
const promiseAll = Promise.all(resArray).catch((e) => error = e);
|
|
92
94
|
return (0, import_html.raw)(`<template id="E:${index}"></template><!--E:${index}-->`, [
|
|
93
95
|
({ phase, buffer, context }) => {
|
|
94
96
|
if (phase === import_html2.HtmlEscapedCallbackPhase.BeforeStream) {
|
|
95
97
|
return;
|
|
96
98
|
}
|
|
97
|
-
return
|
|
99
|
+
return promiseAll.then(async (htmlArray) => {
|
|
100
|
+
if (error) {
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
98
103
|
htmlArray = htmlArray.flat();
|
|
99
104
|
const content = htmlArray.join("");
|
|
100
105
|
let html = buffer ? "" : `<template data-hono-target="E:${index}">${content}</template><script>
|
|
@@ -150,10 +155,10 @@ d.remove()
|
|
|
150
155
|
<\/script>`),
|
|
151
156
|
content2.callbacks
|
|
152
157
|
);
|
|
153
|
-
}).catch((
|
|
158
|
+
}).catch((error2) => catchCallback({ error: error2, buffer }))
|
|
154
159
|
);
|
|
155
160
|
return (0, import_html.raw)(html, promises);
|
|
156
|
-
}).catch((
|
|
161
|
+
}).catch((error2) => catchCallback({ error: error2, buffer }));
|
|
157
162
|
}
|
|
158
163
|
]);
|
|
159
164
|
} else {
|
|
@@ -107,8 +107,15 @@ const documentMetadataTag = (tag, children, props, sort) => {
|
|
|
107
107
|
};
|
|
108
108
|
const title = ({ children, ...props }) => {
|
|
109
109
|
const nameSpaceContext = (0, import_base.getNameSpaceContext)();
|
|
110
|
-
if (nameSpaceContext
|
|
111
|
-
|
|
110
|
+
if (nameSpaceContext) {
|
|
111
|
+
const context = (0, import_context.useContext)(nameSpaceContext);
|
|
112
|
+
if (context === "svg" || context === "head") {
|
|
113
|
+
return new import_base.JSXNode(
|
|
114
|
+
"title",
|
|
115
|
+
props,
|
|
116
|
+
(0, import_children.toArray)(children ?? [])
|
|
117
|
+
);
|
|
118
|
+
}
|
|
112
119
|
}
|
|
113
120
|
return documentMetadataTag("title", children, props, false);
|
|
114
121
|
};
|
|
@@ -116,7 +123,8 @@ const script = ({
|
|
|
116
123
|
children,
|
|
117
124
|
...props
|
|
118
125
|
}) => {
|
|
119
|
-
|
|
126
|
+
const nameSpaceContext = (0, import_base.getNameSpaceContext)();
|
|
127
|
+
if (["src", "async"].some((k) => !props[k]) || nameSpaceContext && (0, import_context.useContext)(nameSpaceContext) === "head") {
|
|
120
128
|
return returnWithoutSpecialBehavior("script", children, props);
|
|
121
129
|
}
|
|
122
130
|
return documentMetadataTag("script", children, props, false);
|
|
@@ -139,6 +147,10 @@ const link = ({ children, ...props }) => {
|
|
|
139
147
|
return documentMetadataTag("link", children, props, "precedence" in props);
|
|
140
148
|
};
|
|
141
149
|
const meta = ({ children, ...props }) => {
|
|
150
|
+
const nameSpaceContext = (0, import_base.getNameSpaceContext)();
|
|
151
|
+
if (nameSpaceContext && (0, import_context.useContext)(nameSpaceContext) === "head") {
|
|
152
|
+
return returnWithoutSpecialBehavior("meta", children, props);
|
|
153
|
+
}
|
|
142
154
|
return documentMetadataTag("meta", children, props, false);
|
|
143
155
|
};
|
|
144
156
|
const newJSXNode = (tag, { children, ...props }) => new import_base.JSXNode(tag, props, (0, import_children.toArray)(children ?? []));
|
|
@@ -22,26 +22,8 @@ __export(basic_auth_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(basic_auth_exports);
|
|
24
24
|
var import_http_exception = require("../../http-exception");
|
|
25
|
+
var import_basic_auth = require("../../utils/basic-auth");
|
|
25
26
|
var import_buffer = require("../../utils/buffer");
|
|
26
|
-
var import_encode = require("../../utils/encode");
|
|
27
|
-
const CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
|
|
28
|
-
const USER_PASS_REGEXP = /^([^:]*):(.*)$/;
|
|
29
|
-
const utf8Decoder = new TextDecoder();
|
|
30
|
-
const auth = (req) => {
|
|
31
|
-
const match = CREDENTIALS_REGEXP.exec(req.header("Authorization") || "");
|
|
32
|
-
if (!match) {
|
|
33
|
-
return void 0;
|
|
34
|
-
}
|
|
35
|
-
let userPass = void 0;
|
|
36
|
-
try {
|
|
37
|
-
userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode((0, import_encode.decodeBase64)(match[1])));
|
|
38
|
-
} catch {
|
|
39
|
-
}
|
|
40
|
-
if (!userPass) {
|
|
41
|
-
return void 0;
|
|
42
|
-
}
|
|
43
|
-
return { username: userPass[1], password: userPass[2] };
|
|
44
|
-
};
|
|
45
27
|
const basicAuth = (options, ...users) => {
|
|
46
28
|
const usernamePasswordInOptions = "username" in options && "password" in options;
|
|
47
29
|
const verifyUserInOptions = "verifyUser" in options;
|
|
@@ -57,7 +39,7 @@ const basicAuth = (options, ...users) => {
|
|
|
57
39
|
users.unshift({ username: options.username, password: options.password });
|
|
58
40
|
}
|
|
59
41
|
return async function basicAuth2(ctx, next) {
|
|
60
|
-
const requestUser = auth(ctx.req);
|
|
42
|
+
const requestUser = (0, import_basic_auth.auth)(ctx.req.raw);
|
|
61
43
|
if (requestUser) {
|
|
62
44
|
if (verifyUserInOptions) {
|
|
63
45
|
if (await options.verifyUser(requestUser.username, requestUser.password, ctx)) {
|
|
@@ -22,9 +22,16 @@ __export(compress_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(compress_exports);
|
|
24
24
|
const ENCODING_TYPES = ["gzip", "deflate"];
|
|
25
|
+
const cacheControlNoTransformRegExp = /(?:^|,)\s*?no-transform\s*?(?:,|$)/i;
|
|
26
|
+
const compressibleContentTypeRegExp = /^\s*(?:text\/[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
|
|
25
27
|
const compress = (options) => {
|
|
28
|
+
const threshold = options?.threshold ?? 1024;
|
|
26
29
|
return async function compress2(ctx, next) {
|
|
27
30
|
await next();
|
|
31
|
+
const contentLength = ctx.res.headers.get("Content-Length");
|
|
32
|
+
if (ctx.res.headers.has("Content-Encoding") || ctx.req.method === "HEAD" || contentLength && Number(contentLength) < threshold || !shouldCompress(ctx.res) || !shouldTransform(ctx.res)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
28
35
|
const accepted = ctx.req.header("Accept-Encoding");
|
|
29
36
|
const encoding = options?.encoding ?? ENCODING_TYPES.find((encoding2) => accepted?.includes(encoding2));
|
|
30
37
|
if (!encoding || !ctx.res.body) {
|
|
@@ -36,6 +43,14 @@ const compress = (options) => {
|
|
|
36
43
|
ctx.res.headers.set("Content-Encoding", encoding);
|
|
37
44
|
};
|
|
38
45
|
};
|
|
46
|
+
const shouldCompress = (res) => {
|
|
47
|
+
const type = res.headers.get("Content-Type");
|
|
48
|
+
return type && compressibleContentTypeRegExp.test(type);
|
|
49
|
+
};
|
|
50
|
+
const shouldTransform = (res) => {
|
|
51
|
+
const cacheControl = res.headers.get("Cache-Control");
|
|
52
|
+
return !cacheControl || !cacheControlNoTransformRegExp.test(cacheControl);
|
|
53
|
+
};
|
|
39
54
|
// Annotate the CommonJS export names for ESM import in node:
|
|
40
55
|
0 && (module.exports = {
|
|
41
56
|
compress
|
|
@@ -53,7 +53,7 @@ const colorStatus = (status) => {
|
|
|
53
53
|
return out[calculateStatus];
|
|
54
54
|
};
|
|
55
55
|
function log(fn, prefix, method, path, status = 0, elapsed) {
|
|
56
|
-
const out = prefix === "<--" /* Incoming */ ?
|
|
56
|
+
const out = prefix === "<--" /* Incoming */ ? `${prefix} ${method} ${path}` : `${prefix} ${method} ${path} ${colorStatus(status)} ${elapsed}`;
|
|
57
57
|
fn(out);
|
|
58
58
|
}
|
|
59
59
|
const logger = (fn = console.log) => {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var basic_auth_exports = {};
|
|
20
|
+
__export(basic_auth_exports, {
|
|
21
|
+
auth: () => auth
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(basic_auth_exports);
|
|
24
|
+
var import_encode = require("./encode");
|
|
25
|
+
const CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
|
|
26
|
+
const USER_PASS_REGEXP = /^([^:]*):(.*)$/;
|
|
27
|
+
const utf8Decoder = new TextDecoder();
|
|
28
|
+
const auth = (req) => {
|
|
29
|
+
const match = CREDENTIALS_REGEXP.exec(req.headers.get("Authorization") || "");
|
|
30
|
+
if (!match) {
|
|
31
|
+
return void 0;
|
|
32
|
+
}
|
|
33
|
+
let userPass = void 0;
|
|
34
|
+
try {
|
|
35
|
+
userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode((0, import_encode.decodeBase64)(match[1])));
|
|
36
|
+
} catch {
|
|
37
|
+
}
|
|
38
|
+
if (!userPass) {
|
|
39
|
+
return void 0;
|
|
40
|
+
}
|
|
41
|
+
return { username: userPass[1], password: userPass[2] };
|
|
42
|
+
};
|
|
43
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
44
|
+
0 && (module.exports = {
|
|
45
|
+
auth
|
|
46
|
+
});
|
package/dist/cjs/utils/body.js
CHANGED
|
@@ -26,7 +26,7 @@ const parseBody = async (request, options = /* @__PURE__ */ Object.create(null))
|
|
|
26
26
|
const { all = false, dot = false } = options;
|
|
27
27
|
const headers = request instanceof import_request.HonoRequest ? request.raw.headers : request.headers;
|
|
28
28
|
const contentType = headers.get("Content-Type");
|
|
29
|
-
if (contentType
|
|
29
|
+
if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) {
|
|
30
30
|
return parseFormData(request, { all, dot });
|
|
31
31
|
}
|
|
32
32
|
return {};
|
package/dist/jsx/base.js
CHANGED
|
@@ -234,7 +234,7 @@ var jsxFn = (tag, props, children) => {
|
|
|
234
234
|
props,
|
|
235
235
|
children
|
|
236
236
|
);
|
|
237
|
-
} else if (tag === "svg") {
|
|
237
|
+
} else if (tag === "svg" || tag === "head") {
|
|
238
238
|
nameSpaceContext ||= createContext("");
|
|
239
239
|
return new JSXNode(tag, props, [
|
|
240
240
|
new JSXFunctionNode(
|
package/dist/jsx/components.js
CHANGED
|
@@ -48,11 +48,11 @@ var ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) => {
|
|
|
48
48
|
const index = errorBoundaryCounter++;
|
|
49
49
|
const replaceRe = RegExp(`(<template id="E:${index}"></template>.*?)(.*?)(<!--E:${index}-->)`);
|
|
50
50
|
const caught = false;
|
|
51
|
-
const catchCallback = ({ error, buffer }) => {
|
|
51
|
+
const catchCallback = ({ error: error2, buffer }) => {
|
|
52
52
|
if (caught) {
|
|
53
53
|
return "";
|
|
54
54
|
}
|
|
55
|
-
const fallbackResString = fallbackRes(
|
|
55
|
+
const fallbackResString = fallbackRes(error2);
|
|
56
56
|
if (buffer) {
|
|
57
57
|
buffer[0] = buffer[0].replace(replaceRe, fallbackResString);
|
|
58
58
|
}
|
|
@@ -66,12 +66,17 @@ d.replaceWith(c.content)
|
|
|
66
66
|
})(document)
|
|
67
67
|
<\/script>`;
|
|
68
68
|
};
|
|
69
|
+
let error;
|
|
70
|
+
const promiseAll = Promise.all(resArray).catch((e) => error = e);
|
|
69
71
|
return raw(`<template id="E:${index}"></template><!--E:${index}-->`, [
|
|
70
72
|
({ phase, buffer, context }) => {
|
|
71
73
|
if (phase === HtmlEscapedCallbackPhase.BeforeStream) {
|
|
72
74
|
return;
|
|
73
75
|
}
|
|
74
|
-
return
|
|
76
|
+
return promiseAll.then(async (htmlArray) => {
|
|
77
|
+
if (error) {
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
75
80
|
htmlArray = htmlArray.flat();
|
|
76
81
|
const content = htmlArray.join("");
|
|
77
82
|
let html = buffer ? "" : `<template data-hono-target="E:${index}">${content}</template><script>
|
|
@@ -127,10 +132,10 @@ d.remove()
|
|
|
127
132
|
<\/script>`),
|
|
128
133
|
content2.callbacks
|
|
129
134
|
);
|
|
130
|
-
}).catch((
|
|
135
|
+
}).catch((error2) => catchCallback({ error: error2, buffer }))
|
|
131
136
|
);
|
|
132
137
|
return raw(html, promises);
|
|
133
|
-
}).catch((
|
|
138
|
+
}).catch((error2) => catchCallback({ error: error2, buffer }));
|
|
134
139
|
}
|
|
135
140
|
]);
|
|
136
141
|
} else {
|
|
@@ -78,8 +78,15 @@ var documentMetadataTag = (tag, children, props, sort) => {
|
|
|
78
78
|
};
|
|
79
79
|
var title = ({ children, ...props }) => {
|
|
80
80
|
const nameSpaceContext = getNameSpaceContext();
|
|
81
|
-
if (nameSpaceContext
|
|
82
|
-
|
|
81
|
+
if (nameSpaceContext) {
|
|
82
|
+
const context = useContext(nameSpaceContext);
|
|
83
|
+
if (context === "svg" || context === "head") {
|
|
84
|
+
return new JSXNode(
|
|
85
|
+
"title",
|
|
86
|
+
props,
|
|
87
|
+
toArray(children ?? [])
|
|
88
|
+
);
|
|
89
|
+
}
|
|
83
90
|
}
|
|
84
91
|
return documentMetadataTag("title", children, props, false);
|
|
85
92
|
};
|
|
@@ -87,7 +94,8 @@ var script = ({
|
|
|
87
94
|
children,
|
|
88
95
|
...props
|
|
89
96
|
}) => {
|
|
90
|
-
|
|
97
|
+
const nameSpaceContext = getNameSpaceContext();
|
|
98
|
+
if (["src", "async"].some((k) => !props[k]) || nameSpaceContext && useContext(nameSpaceContext) === "head") {
|
|
91
99
|
return returnWithoutSpecialBehavior("script", children, props);
|
|
92
100
|
}
|
|
93
101
|
return documentMetadataTag("script", children, props, false);
|
|
@@ -110,6 +118,10 @@ var link = ({ children, ...props }) => {
|
|
|
110
118
|
return documentMetadataTag("link", children, props, "precedence" in props);
|
|
111
119
|
};
|
|
112
120
|
var meta = ({ children, ...props }) => {
|
|
121
|
+
const nameSpaceContext = getNameSpaceContext();
|
|
122
|
+
if (nameSpaceContext && useContext(nameSpaceContext) === "head") {
|
|
123
|
+
return returnWithoutSpecialBehavior("meta", children, props);
|
|
124
|
+
}
|
|
113
125
|
return documentMetadataTag("meta", children, props, false);
|
|
114
126
|
};
|
|
115
127
|
var newJSXNode = (tag, { children, ...props }) => new JSXNode(tag, props, toArray(children ?? []));
|
|
@@ -1,25 +1,7 @@
|
|
|
1
1
|
// src/middleware/basic-auth/index.ts
|
|
2
2
|
import { HTTPException } from "../../http-exception.js";
|
|
3
|
+
import { auth } from "../../utils/basic-auth.js";
|
|
3
4
|
import { timingSafeEqual } from "../../utils/buffer.js";
|
|
4
|
-
import { decodeBase64 } from "../../utils/encode.js";
|
|
5
|
-
var CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
|
|
6
|
-
var USER_PASS_REGEXP = /^([^:]*):(.*)$/;
|
|
7
|
-
var utf8Decoder = new TextDecoder();
|
|
8
|
-
var auth = (req) => {
|
|
9
|
-
const match = CREDENTIALS_REGEXP.exec(req.header("Authorization") || "");
|
|
10
|
-
if (!match) {
|
|
11
|
-
return void 0;
|
|
12
|
-
}
|
|
13
|
-
let userPass = void 0;
|
|
14
|
-
try {
|
|
15
|
-
userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode(decodeBase64(match[1])));
|
|
16
|
-
} catch {
|
|
17
|
-
}
|
|
18
|
-
if (!userPass) {
|
|
19
|
-
return void 0;
|
|
20
|
-
}
|
|
21
|
-
return { username: userPass[1], password: userPass[2] };
|
|
22
|
-
};
|
|
23
5
|
var basicAuth = (options, ...users) => {
|
|
24
6
|
const usernamePasswordInOptions = "username" in options && "password" in options;
|
|
25
7
|
const verifyUserInOptions = "verifyUser" in options;
|
|
@@ -35,7 +17,7 @@ var basicAuth = (options, ...users) => {
|
|
|
35
17
|
users.unshift({ username: options.username, password: options.password });
|
|
36
18
|
}
|
|
37
19
|
return async function basicAuth2(ctx, next) {
|
|
38
|
-
const requestUser = auth(ctx.req);
|
|
20
|
+
const requestUser = auth(ctx.req.raw);
|
|
39
21
|
if (requestUser) {
|
|
40
22
|
if (verifyUserInOptions) {
|
|
41
23
|
if (await options.verifyUser(requestUser.username, requestUser.password, ctx)) {
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
// src/middleware/compress/index.ts
|
|
2
2
|
var ENCODING_TYPES = ["gzip", "deflate"];
|
|
3
|
+
var cacheControlNoTransformRegExp = /(?:^|,)\s*?no-transform\s*?(?:,|$)/i;
|
|
4
|
+
var compressibleContentTypeRegExp = /^\s*(?:text\/[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
|
|
3
5
|
var compress = (options) => {
|
|
6
|
+
const threshold = options?.threshold ?? 1024;
|
|
4
7
|
return async function compress2(ctx, next) {
|
|
5
8
|
await next();
|
|
9
|
+
const contentLength = ctx.res.headers.get("Content-Length");
|
|
10
|
+
if (ctx.res.headers.has("Content-Encoding") || ctx.req.method === "HEAD" || contentLength && Number(contentLength) < threshold || !shouldCompress(ctx.res) || !shouldTransform(ctx.res)) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
6
13
|
const accepted = ctx.req.header("Accept-Encoding");
|
|
7
14
|
const encoding = options?.encoding ?? ENCODING_TYPES.find((encoding2) => accepted?.includes(encoding2));
|
|
8
15
|
if (!encoding || !ctx.res.body) {
|
|
@@ -14,6 +21,14 @@ var compress = (options) => {
|
|
|
14
21
|
ctx.res.headers.set("Content-Encoding", encoding);
|
|
15
22
|
};
|
|
16
23
|
};
|
|
24
|
+
var shouldCompress = (res) => {
|
|
25
|
+
const type = res.headers.get("Content-Type");
|
|
26
|
+
return type && compressibleContentTypeRegExp.test(type);
|
|
27
|
+
};
|
|
28
|
+
var shouldTransform = (res) => {
|
|
29
|
+
const cacheControl = res.headers.get("Cache-Control");
|
|
30
|
+
return !cacheControl || !cacheControlNoTransformRegExp.test(cacheControl);
|
|
31
|
+
};
|
|
17
32
|
export {
|
|
18
33
|
compress
|
|
19
34
|
};
|
|
@@ -25,7 +25,7 @@ var colorStatus = (status) => {
|
|
|
25
25
|
return out[calculateStatus];
|
|
26
26
|
};
|
|
27
27
|
function log(fn, prefix, method, path, status = 0, elapsed) {
|
|
28
|
-
const out = prefix === "<--" /* Incoming */ ?
|
|
28
|
+
const out = prefix === "<--" /* Incoming */ ? `${prefix} ${method} ${path}` : `${prefix} ${method} ${path} ${colorStatus(status)} ${elapsed}`;
|
|
29
29
|
fn(out);
|
|
30
30
|
}
|
|
31
31
|
var logger = (fn = console.log) => {
|
|
@@ -166,7 +166,8 @@ export declare namespace JSX {
|
|
|
166
166
|
lang?: string | undefined;
|
|
167
167
|
nonce?: string | undefined;
|
|
168
168
|
placeholder?: string | undefined;
|
|
169
|
-
|
|
169
|
+
/** @see https://developer.mozilla.org/en-US/docs/Web/API/Popover_API */
|
|
170
|
+
popover?: boolean | 'auto' | 'manual' | undefined;
|
|
170
171
|
slot?: string | undefined;
|
|
171
172
|
spellcheck?: boolean | undefined;
|
|
172
173
|
style?: CSSProperties | string | undefined;
|
|
@@ -207,16 +208,20 @@ export declare namespace JSX {
|
|
|
207
208
|
interface BlockquoteHTMLAttributes extends HTMLAttributes {
|
|
208
209
|
cite?: string | undefined;
|
|
209
210
|
}
|
|
211
|
+
/** @see https://developer.mozilla.org/en-US/docs/Web/API/Popover_API */
|
|
212
|
+
type HTMLAttributePopoverTargetAction = 'show' | 'hide' | 'toggle';
|
|
210
213
|
interface ButtonHTMLAttributes extends HTMLAttributes {
|
|
211
214
|
disabled?: boolean | undefined;
|
|
212
215
|
form?: string | undefined;
|
|
213
|
-
formenctype?:
|
|
214
|
-
formmethod?:
|
|
216
|
+
formenctype?: HTMLAttributeFormEnctype | undefined;
|
|
217
|
+
formmethod?: HTMLAttributeFormMethod | undefined;
|
|
215
218
|
formnovalidate?: boolean | undefined;
|
|
216
219
|
formtarget?: HTMLAttributeAnchorTarget | undefined;
|
|
217
220
|
name?: string | undefined;
|
|
218
221
|
type?: 'submit' | 'reset' | 'button' | undefined;
|
|
219
222
|
value?: string | ReadonlyArray<string> | number | undefined;
|
|
223
|
+
popovertarget?: string | undefined;
|
|
224
|
+
popovertargetaction?: HTMLAttributePopoverTargetAction | undefined;
|
|
220
225
|
formAction?: string | Function | undefined;
|
|
221
226
|
}
|
|
222
227
|
interface CanvasHTMLAttributes extends HTMLAttributes {
|
|
@@ -254,11 +259,17 @@ export declare namespace JSX {
|
|
|
254
259
|
form?: string | undefined;
|
|
255
260
|
name?: string | undefined;
|
|
256
261
|
}
|
|
262
|
+
/** @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#method */
|
|
263
|
+
type HTMLAttributeFormMethod = 'get' | 'post' | 'dialog';
|
|
264
|
+
/** @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#enctype */
|
|
265
|
+
type HTMLAttributeFormEnctype = 'application/x-www-form-urlencoded' | 'multipart/form-data' | 'text/plain';
|
|
266
|
+
/** @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#autocomplete */
|
|
267
|
+
type HTMLAttributeFormAutocomplete = 'on' | 'off';
|
|
257
268
|
interface FormHTMLAttributes extends HTMLAttributes {
|
|
258
|
-
'accept-charset'?:
|
|
259
|
-
autocomplete?:
|
|
260
|
-
enctype?:
|
|
261
|
-
method?:
|
|
269
|
+
'accept-charset'?: StringLiteralUnion<'utf-8'> | undefined;
|
|
270
|
+
autocomplete?: HTMLAttributeFormAutocomplete | undefined;
|
|
271
|
+
enctype?: HTMLAttributeFormEnctype | undefined;
|
|
272
|
+
method?: HTMLAttributeFormMethod | undefined;
|
|
262
273
|
name?: string | undefined;
|
|
263
274
|
novalidate?: boolean | undefined;
|
|
264
275
|
target?: HTMLAttributeAnchorTarget | undefined;
|
|
@@ -317,8 +328,8 @@ export declare namespace JSX {
|
|
|
317
328
|
checked?: boolean | undefined;
|
|
318
329
|
disabled?: boolean | undefined;
|
|
319
330
|
form?: string | undefined;
|
|
320
|
-
formenctype?:
|
|
321
|
-
formmethod?:
|
|
331
|
+
formenctype?: HTMLAttributeFormEnctype | undefined;
|
|
332
|
+
formmethod?: HTMLAttributeFormMethod | undefined;
|
|
322
333
|
formnovalidate?: boolean | undefined;
|
|
323
334
|
formtarget?: HTMLAttributeAnchorTarget | undefined;
|
|
324
335
|
height?: number | string | undefined;
|
|
@@ -339,6 +350,8 @@ export declare namespace JSX {
|
|
|
339
350
|
type?: HTMLInputTypeAttribute | undefined;
|
|
340
351
|
value?: string | ReadonlyArray<string> | number | undefined;
|
|
341
352
|
width?: number | string | undefined;
|
|
353
|
+
popovertarget?: string | undefined;
|
|
354
|
+
popovertargetaction?: HTMLAttributePopoverTargetAction | undefined;
|
|
342
355
|
formAction?: string | Function | undefined;
|
|
343
356
|
}
|
|
344
357
|
interface KeygenHTMLAttributes extends HTMLAttributes {
|
|
@@ -6,6 +6,7 @@ import type { MiddlewareHandler } from '../../types';
|
|
|
6
6
|
declare const ENCODING_TYPES: readonly ["gzip", "deflate"];
|
|
7
7
|
interface CompressionOptions {
|
|
8
8
|
encoding?: (typeof ENCODING_TYPES)[number];
|
|
9
|
+
threshold?: number;
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* Compress Middleware for Hono.
|
|
@@ -14,6 +15,7 @@ interface CompressionOptions {
|
|
|
14
15
|
*
|
|
15
16
|
* @param {CompressionOptions} [options] - The options for the compress middleware.
|
|
16
17
|
* @param {'gzip' | 'deflate'} [options.encoding] - The compression scheme to allow for response compression. Either 'gzip' or 'deflate'. If not defined, both are allowed and will be used based on the Accept-Encoding header. 'gzip' is prioritized if this option is not provided and the client provides both in the Accept-Encoding header.
|
|
18
|
+
* @param {number} [options.threshold=1024] - The minimum size in bytes to compress. Defaults to 1024 bytes.
|
|
17
19
|
* @returns {MiddlewareHandler} The middleware handler function.
|
|
18
20
|
*
|
|
19
21
|
* @example
|
|
@@ -17,7 +17,7 @@ type ComponentWithChildren = (props: PropsWithChildren<PropsForRenderer & {
|
|
|
17
17
|
/**
|
|
18
18
|
* JSX Renderer Middleware for hono.
|
|
19
19
|
*
|
|
20
|
-
* @see {@link
|
|
20
|
+
* @see {@link https://hono.dev/docs/middleware/builtin/jsx-renderer}
|
|
21
21
|
*
|
|
22
22
|
* @param {ComponentWithChildren} [component] - The component to render, which can accept children and props.
|
|
23
23
|
* @param {RendererOptions} [options] - The options for the JSX renderer middleware.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/utils/basic-auth.ts
|
|
2
|
+
import { decodeBase64 } from "./encode.js";
|
|
3
|
+
var CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
|
|
4
|
+
var USER_PASS_REGEXP = /^([^:]*):(.*)$/;
|
|
5
|
+
var utf8Decoder = new TextDecoder();
|
|
6
|
+
var auth = (req) => {
|
|
7
|
+
const match = CREDENTIALS_REGEXP.exec(req.headers.get("Authorization") || "");
|
|
8
|
+
if (!match) {
|
|
9
|
+
return void 0;
|
|
10
|
+
}
|
|
11
|
+
let userPass = void 0;
|
|
12
|
+
try {
|
|
13
|
+
userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode(decodeBase64(match[1])));
|
|
14
|
+
} catch {
|
|
15
|
+
}
|
|
16
|
+
if (!userPass) {
|
|
17
|
+
return void 0;
|
|
18
|
+
}
|
|
19
|
+
return { username: userPass[1], password: userPass[2] };
|
|
20
|
+
};
|
|
21
|
+
export {
|
|
22
|
+
auth
|
|
23
|
+
};
|
package/dist/utils/body.js
CHANGED
|
@@ -4,7 +4,7 @@ var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) =
|
|
|
4
4
|
const { all = false, dot = false } = options;
|
|
5
5
|
const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
|
|
6
6
|
const contentType = headers.get("Content-Type");
|
|
7
|
-
if (contentType
|
|
7
|
+
if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) {
|
|
8
8
|
return parseFormData(request, { all, dot });
|
|
9
9
|
}
|
|
10
10
|
return {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.11",
|
|
4
4
|
"description": "Web framework built on Web Standards",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -617,7 +617,7 @@
|
|
|
617
617
|
"@types/jsdom": "^21.1.4",
|
|
618
618
|
"@types/node": "20.11.4",
|
|
619
619
|
"@types/supertest": "^2.0.12",
|
|
620
|
-
"@vitest/coverage-v8": "^
|
|
620
|
+
"@vitest/coverage-v8": "^2.0.5",
|
|
621
621
|
"arg": "^5.0.2",
|
|
622
622
|
"crypto-js": "^4.1.1",
|
|
623
623
|
"esbuild": "^0.15.12",
|
|
@@ -631,7 +631,7 @@
|
|
|
631
631
|
"supertest": "^6.3.3",
|
|
632
632
|
"typescript": "^5.3.3",
|
|
633
633
|
"vite-plugin-fastly-js-compute": "^0.4.2",
|
|
634
|
-
"vitest": "^
|
|
634
|
+
"vitest": "^2.0.5",
|
|
635
635
|
"wrangler": "^3.58.0",
|
|
636
636
|
"ws": "^8.17.0",
|
|
637
637
|
"zod": "^3.20.2"
|