hono 3.3.4 → 3.4.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/README.md +7 -7
- package/dist/adapter/aws-lambda/handler.js +12 -1
- package/dist/adapter/netlify/handler.js +9 -0
- package/dist/adapter/netlify/mod.js +5 -0
- package/dist/cjs/adapter/aws-lambda/handler.js +13 -1
- package/dist/cjs/adapter/netlify/handler.js +32 -0
- package/dist/cjs/adapter/netlify/mod.js +28 -0
- package/dist/cjs/context.js +7 -9
- package/dist/cjs/hono-base.js +4 -4
- package/dist/cjs/middleware/cookie/index.js +23 -2
- package/dist/cjs/middleware/pretty-json/index.js +4 -1
- package/dist/cjs/utils/body.js +2 -2
- package/dist/cjs/utils/cookie.js +61 -8
- package/dist/cjs/utils/url.js +3 -4
- package/dist/cjs/validator/validator.js +2 -2
- package/dist/context.js +7 -9
- package/dist/hono-base.js +4 -4
- package/dist/middleware/cookie/index.js +21 -2
- package/dist/middleware/pretty-json/index.js +4 -1
- package/dist/types/adapter/aws-lambda/handler.d.ts +1 -0
- package/dist/types/adapter/netlify/handler.d.ts +7 -0
- package/dist/types/adapter/netlify/mod.d.ts +2 -0
- package/dist/types/context.d.ts +1 -3
- package/dist/types/hono-base.d.ts +10 -4
- package/dist/types/middleware/cookie/index.d.ts +7 -1
- package/dist/types/request.d.ts +1 -1
- package/dist/types/types.d.ts +2 -1
- package/dist/types/utils/body.d.ts +1 -1
- package/dist/types/utils/cookie.d.ts +5 -2
- package/dist/types/validator/validator.d.ts +1 -1
- package/dist/utils/body.js +2 -2
- package/dist/utils/cookie.js +58 -7
- package/dist/utils/url.js +3 -4
- package/dist/validator/validator.js +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
[](https://discord.gg/KMh2eNSdxV)
|
|
27
27
|
|
|
28
28
|
Hono - _**\[炎\] means flame🔥 in Japanese**_ - is a small, simple, and ultrafast web framework for the Edges.
|
|
29
|
-
It works on any JavaScript runtime: Cloudflare Workers, Fastly Compute@Edge, Deno, Bun, Vercel, Lagon, AWS Lambda, and Node.js.
|
|
29
|
+
It works on any JavaScript runtime: Cloudflare Workers, Fastly Compute@Edge, Deno, Bun, Vercel, Lagon, AWS Lambda, Lambda@Edge, and Node.js.
|
|
30
30
|
|
|
31
31
|
Fast, but not only fast.
|
|
32
32
|
|
|
@@ -49,7 +49,7 @@ npm create hono@latest my-app
|
|
|
49
49
|
|
|
50
50
|
- **Ultrafast** 🚀 - The router `RegExpRouter` is really fast. Not using linear loops. Fast.
|
|
51
51
|
- **Lightweight** 🪶 - The `hono/tiny` preset is under 12kB. Hono has zero dependencies and uses only the Web Standard API.
|
|
52
|
-
- **Multi-runtime** 🌍 - Works on Cloudflare Workers, Fastly Compute@Edge, Deno, Bun, Lagon, AWS Lambda, or Node.js. The same code runs on all platforms.
|
|
52
|
+
- **Multi-runtime** 🌍 - Works on Cloudflare Workers, Fastly Compute@Edge, Deno, Bun, Lagon, AWS Lambda, Lambda@Edge, or Node.js. The same code runs on all platforms.
|
|
53
53
|
- **Batteries Included** 🔋 - Hono has built-in middleware, custom middleware, and third-party middleware. Batteries included.
|
|
54
54
|
- **Delightful DX** 🛠️ - Super clean APIs. First-class TypeScript support. Now, we've got "Types".
|
|
55
55
|
|
|
@@ -58,12 +58,12 @@ npm create hono@latest my-app
|
|
|
58
58
|
**Hono is the fastest**, compared to other routers for Cloudflare Workers.
|
|
59
59
|
|
|
60
60
|
```
|
|
61
|
-
Hono x
|
|
62
|
-
itty-router x
|
|
63
|
-
sunder x
|
|
64
|
-
worktop x
|
|
61
|
+
Hono x 510,171 ops/sec ±4.61% (82 runs sampled)
|
|
62
|
+
itty-router x 285,810 ops/sec ±4.13% (85 runs sampled)
|
|
63
|
+
sunder x 345,272 ops/sec ±4.46% (87 runs sampled)
|
|
64
|
+
worktop x 203,468 ops/sec ±3.03% (91 runs sampled)
|
|
65
65
|
Fastest is Hono
|
|
66
|
-
✨ Done in 28.
|
|
66
|
+
✨ Done in 28.68s.
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
## Documentation
|
|
@@ -11,7 +11,11 @@ var handle = (app) => {
|
|
|
11
11
|
};
|
|
12
12
|
var createResult = async (res) => {
|
|
13
13
|
const contentType = res.headers.get("content-type");
|
|
14
|
-
|
|
14
|
+
let isBase64Encoded = contentType && isContentTypeBinary(contentType) ? true : false;
|
|
15
|
+
if (!isBase64Encoded) {
|
|
16
|
+
const contentEncoding = res.headers.get("content-encoding");
|
|
17
|
+
isBase64Encoded = isContentEncodingBinary(contentEncoding);
|
|
18
|
+
}
|
|
15
19
|
let body;
|
|
16
20
|
if (isBase64Encoded) {
|
|
17
21
|
const buffer = await res.arrayBuffer();
|
|
@@ -66,7 +70,14 @@ var isContentTypeBinary = (contentType) => {
|
|
|
66
70
|
contentType
|
|
67
71
|
);
|
|
68
72
|
};
|
|
73
|
+
var isContentEncodingBinary = (contentEncoding) => {
|
|
74
|
+
if (contentEncoding === null) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
return /^(gzip|deflate|compress|br)/.test(contentEncoding);
|
|
78
|
+
};
|
|
69
79
|
export {
|
|
70
80
|
handle,
|
|
81
|
+
isContentEncodingBinary,
|
|
71
82
|
isContentTypeBinary
|
|
72
83
|
};
|
|
@@ -25,6 +25,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
25
25
|
var handler_exports = {};
|
|
26
26
|
__export(handler_exports, {
|
|
27
27
|
handle: () => handle,
|
|
28
|
+
isContentEncodingBinary: () => isContentEncodingBinary,
|
|
28
29
|
isContentTypeBinary: () => isContentTypeBinary
|
|
29
30
|
});
|
|
30
31
|
module.exports = __toCommonJS(handler_exports);
|
|
@@ -40,7 +41,11 @@ const handle = (app) => {
|
|
|
40
41
|
};
|
|
41
42
|
const createResult = async (res) => {
|
|
42
43
|
const contentType = res.headers.get("content-type");
|
|
43
|
-
|
|
44
|
+
let isBase64Encoded = contentType && isContentTypeBinary(contentType) ? true : false;
|
|
45
|
+
if (!isBase64Encoded) {
|
|
46
|
+
const contentEncoding = res.headers.get("content-encoding");
|
|
47
|
+
isBase64Encoded = isContentEncodingBinary(contentEncoding);
|
|
48
|
+
}
|
|
44
49
|
let body;
|
|
45
50
|
if (isBase64Encoded) {
|
|
46
51
|
const buffer = await res.arrayBuffer();
|
|
@@ -95,8 +100,15 @@ const isContentTypeBinary = (contentType) => {
|
|
|
95
100
|
contentType
|
|
96
101
|
);
|
|
97
102
|
};
|
|
103
|
+
const isContentEncodingBinary = (contentEncoding) => {
|
|
104
|
+
if (contentEncoding === null) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
return /^(gzip|deflate|compress|br)/.test(contentEncoding);
|
|
108
|
+
};
|
|
98
109
|
// Annotate the CommonJS export names for ESM import in node:
|
|
99
110
|
0 && (module.exports = {
|
|
100
111
|
handle,
|
|
112
|
+
isContentEncodingBinary,
|
|
101
113
|
isContentTypeBinary
|
|
102
114
|
});
|
|
@@ -0,0 +1,32 @@
|
|
|
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 handler_exports = {};
|
|
20
|
+
__export(handler_exports, {
|
|
21
|
+
handle: () => handle
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(handler_exports);
|
|
24
|
+
const handle = (app) => {
|
|
25
|
+
return (req, context) => {
|
|
26
|
+
return app.fetch(req, { context });
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
30
|
+
0 && (module.exports = {
|
|
31
|
+
handle
|
|
32
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
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 mod_exports = {};
|
|
20
|
+
__export(mod_exports, {
|
|
21
|
+
handle: () => import_handler.handle
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(mod_exports);
|
|
24
|
+
var import_handler = require("./handler.ts");
|
|
25
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
26
|
+
0 && (module.exports = {
|
|
27
|
+
handle
|
|
28
|
+
});
|
package/dist/cjs/context.js
CHANGED
|
@@ -30,11 +30,10 @@ class Context {
|
|
|
30
30
|
this.finalized = false;
|
|
31
31
|
this.error = void 0;
|
|
32
32
|
this._status = 200;
|
|
33
|
-
this._pre = false;
|
|
34
|
-
this._preS = 2;
|
|
35
33
|
this._h = void 0;
|
|
36
34
|
this._pH = void 0;
|
|
37
35
|
this._path = "/";
|
|
36
|
+
this._init = true;
|
|
38
37
|
this.notFoundHandler = () => new Response();
|
|
39
38
|
this.header = (name, value, options) => {
|
|
40
39
|
if (value === void 0) {
|
|
@@ -50,6 +49,7 @@ class Context {
|
|
|
50
49
|
}
|
|
51
50
|
if (options?.append) {
|
|
52
51
|
if (!this._h) {
|
|
52
|
+
this._init = false;
|
|
53
53
|
this._h = new Headers(this._pH);
|
|
54
54
|
this._pH = {};
|
|
55
55
|
}
|
|
@@ -80,12 +80,8 @@ class Context {
|
|
|
80
80
|
this.get = (key) => {
|
|
81
81
|
return this._map ? this._map[key] : void 0;
|
|
82
82
|
};
|
|
83
|
-
this.pretty = (prettyJSON, space = 2) => {
|
|
84
|
-
this._pre = prettyJSON;
|
|
85
|
-
this._preS = space;
|
|
86
|
-
};
|
|
87
83
|
this.newResponse = (data, arg, headers) => {
|
|
88
|
-
if (
|
|
84
|
+
if (this._init && !headers && !arg && this._status === 200) {
|
|
89
85
|
return new Response(data, {
|
|
90
86
|
headers: this._pH
|
|
91
87
|
});
|
|
@@ -133,7 +129,7 @@ class Context {
|
|
|
133
129
|
};
|
|
134
130
|
this.text = (text, arg, headers) => {
|
|
135
131
|
if (!this._pH) {
|
|
136
|
-
if (
|
|
132
|
+
if (this._init && !headers && !arg) {
|
|
137
133
|
return new Response(text);
|
|
138
134
|
}
|
|
139
135
|
this._pH = {};
|
|
@@ -144,7 +140,7 @@ class Context {
|
|
|
144
140
|
return typeof arg === "number" ? this.newResponse(text, arg, headers) : this.newResponse(text, arg);
|
|
145
141
|
};
|
|
146
142
|
this.json = (object, arg, headers) => {
|
|
147
|
-
const body =
|
|
143
|
+
const body = JSON.stringify(object);
|
|
148
144
|
this._pH ?? (this._pH = {});
|
|
149
145
|
this._pH["content-type"] = "application/json; charset=UTF-8";
|
|
150
146
|
return typeof arg === "number" ? this.newResponse(body, arg, headers) : this.newResponse(body, arg);
|
|
@@ -209,9 +205,11 @@ class Context {
|
|
|
209
205
|
}
|
|
210
206
|
}
|
|
211
207
|
get res() {
|
|
208
|
+
this._init = false;
|
|
212
209
|
return this._res || (this._res = new Response("404 Not Found", { status: 404 }));
|
|
213
210
|
}
|
|
214
211
|
set res(_res) {
|
|
212
|
+
this._init = false;
|
|
215
213
|
if (this._res && _res) {
|
|
216
214
|
this._res.headers.delete("content-type");
|
|
217
215
|
this._res.headers.forEach((v, k) => {
|
package/dist/cjs/hono-base.js
CHANGED
|
@@ -59,21 +59,21 @@ class Hono extends defineDynamicClass() {
|
|
|
59
59
|
this.fetch = (request, Env, executionCtx) => {
|
|
60
60
|
return this.dispatch(request, executionCtx, Env, request.method);
|
|
61
61
|
};
|
|
62
|
-
this.request =
|
|
62
|
+
this.request = (input, requestInit) => {
|
|
63
63
|
if (input instanceof Request) {
|
|
64
64
|
if (requestInit !== void 0) {
|
|
65
65
|
input = new Request(input, requestInit);
|
|
66
66
|
}
|
|
67
|
-
return
|
|
67
|
+
return this.fetch(input);
|
|
68
68
|
}
|
|
69
69
|
input = input.toString();
|
|
70
70
|
const path = /^https?:\/\//.test(input) ? input : `http://localhost${(0, import_url.mergePath)("/", input)}`;
|
|
71
71
|
const req = new Request(path, requestInit);
|
|
72
|
-
return
|
|
72
|
+
return this.fetch(req);
|
|
73
73
|
};
|
|
74
74
|
this.fire = () => {
|
|
75
75
|
addEventListener("fetch", (event) => {
|
|
76
|
-
|
|
76
|
+
event.respondWith(this.dispatch(event.request, event, void 0, event.request.method));
|
|
77
77
|
});
|
|
78
78
|
};
|
|
79
79
|
const allMethods = [...import_router.METHODS, import_router.METHOD_NAME_ALL_LOWERCASE];
|
|
@@ -20,7 +20,9 @@ var cookie_exports = {};
|
|
|
20
20
|
__export(cookie_exports, {
|
|
21
21
|
deleteCookie: () => deleteCookie,
|
|
22
22
|
getCookie: () => getCookie,
|
|
23
|
-
|
|
23
|
+
getSignedCookie: () => getSignedCookie,
|
|
24
|
+
setCookie: () => setCookie,
|
|
25
|
+
setSignedCookie: () => setSignedCookie
|
|
24
26
|
});
|
|
25
27
|
module.exports = __toCommonJS(cookie_exports);
|
|
26
28
|
var import_cookie = require("../../utils/cookie");
|
|
@@ -37,10 +39,27 @@ const getCookie = (c, key) => {
|
|
|
37
39
|
const obj = (0, import_cookie.parse)(cookie);
|
|
38
40
|
return obj;
|
|
39
41
|
};
|
|
42
|
+
const getSignedCookie = async (c, secret, key) => {
|
|
43
|
+
const cookie = c.req.raw.headers.get("Cookie");
|
|
44
|
+
if (typeof key === "string") {
|
|
45
|
+
if (!cookie)
|
|
46
|
+
return void 0;
|
|
47
|
+
const obj2 = await (0, import_cookie.parseSigned)(cookie, secret, key);
|
|
48
|
+
return obj2[key];
|
|
49
|
+
}
|
|
50
|
+
if (!cookie)
|
|
51
|
+
return {};
|
|
52
|
+
const obj = await (0, import_cookie.parseSigned)(cookie, secret);
|
|
53
|
+
return obj;
|
|
54
|
+
};
|
|
40
55
|
const setCookie = (c, name, value, opt) => {
|
|
41
56
|
const cookie = (0, import_cookie.serialize)(name, value, opt);
|
|
42
57
|
c.header("set-cookie", cookie, { append: true });
|
|
43
58
|
};
|
|
59
|
+
const setSignedCookie = async (c, name, value, secret, opt) => {
|
|
60
|
+
const cookie = await (0, import_cookie.serializeSigned)(name, value, secret, opt);
|
|
61
|
+
c.header("set-cookie", cookie, { append: true });
|
|
62
|
+
};
|
|
44
63
|
const deleteCookie = (c, name, opt) => {
|
|
45
64
|
setCookie(c, name, "", { ...opt, maxAge: 0 });
|
|
46
65
|
};
|
|
@@ -48,5 +67,7 @@ const deleteCookie = (c, name, opt) => {
|
|
|
48
67
|
0 && (module.exports = {
|
|
49
68
|
deleteCookie,
|
|
50
69
|
getCookie,
|
|
51
|
-
|
|
70
|
+
getSignedCookie,
|
|
71
|
+
setCookie,
|
|
72
|
+
setSignedCookie
|
|
52
73
|
});
|
|
@@ -24,8 +24,11 @@ module.exports = __toCommonJS(pretty_json_exports);
|
|
|
24
24
|
const prettyJSON = (options = { space: 2 }) => {
|
|
25
25
|
return async (c, next) => {
|
|
26
26
|
const pretty = c.req.query("pretty") || c.req.query("pretty") === "" ? true : false;
|
|
27
|
-
c.pretty(pretty, options.space);
|
|
28
27
|
await next();
|
|
28
|
+
if (pretty && c.res.headers.get("Content-Type")?.startsWith("application/json")) {
|
|
29
|
+
const obj = await c.res.json();
|
|
30
|
+
c.res = new Response(JSON.stringify(obj, null, options.space), c.res);
|
|
31
|
+
}
|
|
29
32
|
};
|
|
30
33
|
};
|
|
31
34
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/cjs/utils/body.js
CHANGED
|
@@ -21,7 +21,7 @@ __export(body_exports, {
|
|
|
21
21
|
parseBody: () => parseBody
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(body_exports);
|
|
24
|
-
async
|
|
24
|
+
const parseBody = async (r) => {
|
|
25
25
|
let body = {};
|
|
26
26
|
const contentType = r.headers.get("Content-Type");
|
|
27
27
|
if (contentType && (contentType.startsWith("multipart/form-data") || contentType.startsWith("application/x-www-form-urlencoded"))) {
|
|
@@ -32,7 +32,7 @@ async function parseBody(r) {
|
|
|
32
32
|
body = form;
|
|
33
33
|
}
|
|
34
34
|
return body;
|
|
35
|
-
}
|
|
35
|
+
};
|
|
36
36
|
// Annotate the CommonJS export names for ESM import in node:
|
|
37
37
|
0 && (module.exports = {
|
|
38
38
|
parseBody
|
package/dist/cjs/utils/cookie.js
CHANGED
|
@@ -19,21 +19,62 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var cookie_exports = {};
|
|
20
20
|
__export(cookie_exports, {
|
|
21
21
|
parse: () => parse,
|
|
22
|
-
|
|
22
|
+
parseSigned: () => parseSigned,
|
|
23
|
+
serialize: () => serialize,
|
|
24
|
+
serializeSigned: () => serializeSigned
|
|
23
25
|
});
|
|
24
26
|
module.exports = __toCommonJS(cookie_exports);
|
|
25
27
|
var import_url = require("./url");
|
|
26
|
-
const
|
|
28
|
+
const makeSignature = async (value, secret) => {
|
|
29
|
+
const algorithm = { name: "HMAC", hash: "SHA-256" };
|
|
30
|
+
const encoder = new TextEncoder();
|
|
31
|
+
const key = await crypto.subtle.importKey("raw", encoder.encode(secret), algorithm, false, [
|
|
32
|
+
"sign",
|
|
33
|
+
"verify"
|
|
34
|
+
]);
|
|
35
|
+
const signature = await crypto.subtle.sign(algorithm.name, key, encoder.encode(value));
|
|
36
|
+
return btoa(String.fromCharCode(...new Uint8Array(signature)));
|
|
37
|
+
};
|
|
38
|
+
const _parseCookiePairs = (cookie, name) => {
|
|
27
39
|
const pairs = cookie.split(/;\s*/g);
|
|
40
|
+
const cookiePairs = pairs.map((pairStr) => pairStr.split(/\s*=\s*([^\s]+)/));
|
|
41
|
+
if (!name)
|
|
42
|
+
return cookiePairs;
|
|
43
|
+
return cookiePairs.filter((pair) => pair[0] === name);
|
|
44
|
+
};
|
|
45
|
+
const parse = (cookie, name) => {
|
|
28
46
|
const parsedCookie = {};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
47
|
+
const unsingedCookies = _parseCookiePairs(cookie, name).filter((pair) => {
|
|
48
|
+
if (pair[1].split(".").length === 2)
|
|
49
|
+
return false;
|
|
50
|
+
return true;
|
|
51
|
+
});
|
|
52
|
+
for (let [key, value] of unsingedCookies) {
|
|
53
|
+
value = (0, import_url.decodeURIComponent_)(value);
|
|
54
|
+
parsedCookie[key] = value;
|
|
32
55
|
}
|
|
33
56
|
return parsedCookie;
|
|
34
57
|
};
|
|
35
|
-
const
|
|
36
|
-
|
|
58
|
+
const parseSigned = async (cookie, secret, name) => {
|
|
59
|
+
const parsedCookie = {};
|
|
60
|
+
const signedCookies = _parseCookiePairs(cookie, name).filter((pair) => {
|
|
61
|
+
if (pair[1].split(".").length !== 2)
|
|
62
|
+
return false;
|
|
63
|
+
return true;
|
|
64
|
+
});
|
|
65
|
+
for (let [key, value] of signedCookies) {
|
|
66
|
+
value = (0, import_url.decodeURIComponent_)(value);
|
|
67
|
+
const signedPair = value.split(".");
|
|
68
|
+
const signatureToCompare = await makeSignature(signedPair[0], secret);
|
|
69
|
+
if (signedPair[1] !== signatureToCompare) {
|
|
70
|
+
parsedCookie[key] = false;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
parsedCookie[key] = signedPair[0];
|
|
74
|
+
}
|
|
75
|
+
return parsedCookie;
|
|
76
|
+
};
|
|
77
|
+
const _serialize = (name, value, opt = {}) => {
|
|
37
78
|
let cookie = `${name}=${value}`;
|
|
38
79
|
if (opt && typeof opt.maxAge === "number" && opt.maxAge >= 0) {
|
|
39
80
|
cookie += `; Max-Age=${Math.floor(opt.maxAge)}`;
|
|
@@ -58,8 +99,20 @@ const serialize = (name, value, opt = {}) => {
|
|
|
58
99
|
}
|
|
59
100
|
return cookie;
|
|
60
101
|
};
|
|
102
|
+
const serialize = (name, value, opt = {}) => {
|
|
103
|
+
value = encodeURIComponent(value);
|
|
104
|
+
return _serialize(name, value, opt);
|
|
105
|
+
};
|
|
106
|
+
const serializeSigned = async (name, value, secret, opt = {}) => {
|
|
107
|
+
const signature = await makeSignature(value, secret);
|
|
108
|
+
value = `${value}.${signature}`;
|
|
109
|
+
value = encodeURIComponent(value);
|
|
110
|
+
return _serialize(name, value, opt);
|
|
111
|
+
};
|
|
61
112
|
// Annotate the CommonJS export names for ESM import in node:
|
|
62
113
|
0 && (module.exports = {
|
|
63
114
|
parse,
|
|
64
|
-
|
|
115
|
+
parseSigned,
|
|
116
|
+
serialize,
|
|
117
|
+
serializeSigned
|
|
65
118
|
});
|
package/dist/cjs/utils/url.js
CHANGED
|
@@ -87,9 +87,8 @@ const getPattern = (label) => {
|
|
|
87
87
|
return null;
|
|
88
88
|
};
|
|
89
89
|
const getPath = (request) => {
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
return url.slice(url.indexOf("/", 8), queryIndex === -1 ? void 0 : queryIndex);
|
|
90
|
+
const match = request.url.match(/^https?:\/\/[^/]+(\/[^?]*)/);
|
|
91
|
+
return match ? match[1] : "";
|
|
93
92
|
};
|
|
94
93
|
const getQueryStrings = (url) => {
|
|
95
94
|
const queryIndex = url.indexOf("?", 8);
|
|
@@ -136,7 +135,7 @@ const _decodeURI = (value) => {
|
|
|
136
135
|
if (value.indexOf("+") !== -1) {
|
|
137
136
|
value = value.replace(/\+/g, " ");
|
|
138
137
|
}
|
|
139
|
-
return value
|
|
138
|
+
return /%/.test(value) ? decodeURIComponent_(value) : value;
|
|
140
139
|
};
|
|
141
140
|
const _getQueryParam = (url, key, multiple) => {
|
|
142
141
|
let encoded;
|
|
@@ -57,8 +57,8 @@ const validator = (target, validationFunc) => {
|
|
|
57
57
|
value = c.req.param();
|
|
58
58
|
break;
|
|
59
59
|
}
|
|
60
|
-
const res = validationFunc(value, c);
|
|
61
|
-
if (res instanceof Response
|
|
60
|
+
const res = await validationFunc(value, c);
|
|
61
|
+
if (res instanceof Response) {
|
|
62
62
|
return res;
|
|
63
63
|
}
|
|
64
64
|
c.req.addValidatedData(target, res);
|
package/dist/context.js
CHANGED
|
@@ -8,11 +8,10 @@ var Context = class {
|
|
|
8
8
|
this.finalized = false;
|
|
9
9
|
this.error = void 0;
|
|
10
10
|
this._status = 200;
|
|
11
|
-
this._pre = false;
|
|
12
|
-
this._preS = 2;
|
|
13
11
|
this._h = void 0;
|
|
14
12
|
this._pH = void 0;
|
|
15
13
|
this._path = "/";
|
|
14
|
+
this._init = true;
|
|
16
15
|
this.notFoundHandler = () => new Response();
|
|
17
16
|
this.header = (name, value, options) => {
|
|
18
17
|
if (value === void 0) {
|
|
@@ -28,6 +27,7 @@ var Context = class {
|
|
|
28
27
|
}
|
|
29
28
|
if (options?.append) {
|
|
30
29
|
if (!this._h) {
|
|
30
|
+
this._init = false;
|
|
31
31
|
this._h = new Headers(this._pH);
|
|
32
32
|
this._pH = {};
|
|
33
33
|
}
|
|
@@ -58,12 +58,8 @@ var Context = class {
|
|
|
58
58
|
this.get = (key) => {
|
|
59
59
|
return this._map ? this._map[key] : void 0;
|
|
60
60
|
};
|
|
61
|
-
this.pretty = (prettyJSON, space = 2) => {
|
|
62
|
-
this._pre = prettyJSON;
|
|
63
|
-
this._preS = space;
|
|
64
|
-
};
|
|
65
61
|
this.newResponse = (data, arg, headers) => {
|
|
66
|
-
if (
|
|
62
|
+
if (this._init && !headers && !arg && this._status === 200) {
|
|
67
63
|
return new Response(data, {
|
|
68
64
|
headers: this._pH
|
|
69
65
|
});
|
|
@@ -111,7 +107,7 @@ var Context = class {
|
|
|
111
107
|
};
|
|
112
108
|
this.text = (text, arg, headers) => {
|
|
113
109
|
if (!this._pH) {
|
|
114
|
-
if (
|
|
110
|
+
if (this._init && !headers && !arg) {
|
|
115
111
|
return new Response(text);
|
|
116
112
|
}
|
|
117
113
|
this._pH = {};
|
|
@@ -122,7 +118,7 @@ var Context = class {
|
|
|
122
118
|
return typeof arg === "number" ? this.newResponse(text, arg, headers) : this.newResponse(text, arg);
|
|
123
119
|
};
|
|
124
120
|
this.json = (object, arg, headers) => {
|
|
125
|
-
const body =
|
|
121
|
+
const body = JSON.stringify(object);
|
|
126
122
|
this._pH ?? (this._pH = {});
|
|
127
123
|
this._pH["content-type"] = "application/json; charset=UTF-8";
|
|
128
124
|
return typeof arg === "number" ? this.newResponse(body, arg, headers) : this.newResponse(body, arg);
|
|
@@ -187,9 +183,11 @@ var Context = class {
|
|
|
187
183
|
}
|
|
188
184
|
}
|
|
189
185
|
get res() {
|
|
186
|
+
this._init = false;
|
|
190
187
|
return this._res || (this._res = new Response("404 Not Found", { status: 404 }));
|
|
191
188
|
}
|
|
192
189
|
set res(_res) {
|
|
190
|
+
this._init = false;
|
|
193
191
|
if (this._res && _res) {
|
|
194
192
|
this._res.headers.delete("content-type");
|
|
195
193
|
this._res.headers.forEach((v, k) => {
|
package/dist/hono-base.js
CHANGED
|
@@ -37,21 +37,21 @@ var Hono = class extends defineDynamicClass() {
|
|
|
37
37
|
this.fetch = (request, Env, executionCtx) => {
|
|
38
38
|
return this.dispatch(request, executionCtx, Env, request.method);
|
|
39
39
|
};
|
|
40
|
-
this.request =
|
|
40
|
+
this.request = (input, requestInit) => {
|
|
41
41
|
if (input instanceof Request) {
|
|
42
42
|
if (requestInit !== void 0) {
|
|
43
43
|
input = new Request(input, requestInit);
|
|
44
44
|
}
|
|
45
|
-
return
|
|
45
|
+
return this.fetch(input);
|
|
46
46
|
}
|
|
47
47
|
input = input.toString();
|
|
48
48
|
const path = /^https?:\/\//.test(input) ? input : `http://localhost${mergePath("/", input)}`;
|
|
49
49
|
const req = new Request(path, requestInit);
|
|
50
|
-
return
|
|
50
|
+
return this.fetch(req);
|
|
51
51
|
};
|
|
52
52
|
this.fire = () => {
|
|
53
53
|
addEventListener("fetch", (event) => {
|
|
54
|
-
|
|
54
|
+
event.respondWith(this.dispatch(event.request, event, void 0, event.request.method));
|
|
55
55
|
});
|
|
56
56
|
};
|
|
57
57
|
const allMethods = [...METHODS, METHOD_NAME_ALL_LOWERCASE];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/middleware/cookie/index.ts
|
|
2
|
-
import { parse, serialize } from "../../utils/cookie.js";
|
|
2
|
+
import { parse, parseSigned, serialize, serializeSigned } from "../../utils/cookie.js";
|
|
3
3
|
var getCookie = (c, key) => {
|
|
4
4
|
const cookie = c.req.raw.headers.get("Cookie");
|
|
5
5
|
if (typeof key === "string") {
|
|
@@ -13,15 +13,34 @@ var getCookie = (c, key) => {
|
|
|
13
13
|
const obj = parse(cookie);
|
|
14
14
|
return obj;
|
|
15
15
|
};
|
|
16
|
+
var getSignedCookie = async (c, secret, key) => {
|
|
17
|
+
const cookie = c.req.raw.headers.get("Cookie");
|
|
18
|
+
if (typeof key === "string") {
|
|
19
|
+
if (!cookie)
|
|
20
|
+
return void 0;
|
|
21
|
+
const obj2 = await parseSigned(cookie, secret, key);
|
|
22
|
+
return obj2[key];
|
|
23
|
+
}
|
|
24
|
+
if (!cookie)
|
|
25
|
+
return {};
|
|
26
|
+
const obj = await parseSigned(cookie, secret);
|
|
27
|
+
return obj;
|
|
28
|
+
};
|
|
16
29
|
var setCookie = (c, name, value, opt) => {
|
|
17
30
|
const cookie = serialize(name, value, opt);
|
|
18
31
|
c.header("set-cookie", cookie, { append: true });
|
|
19
32
|
};
|
|
33
|
+
var setSignedCookie = async (c, name, value, secret, opt) => {
|
|
34
|
+
const cookie = await serializeSigned(name, value, secret, opt);
|
|
35
|
+
c.header("set-cookie", cookie, { append: true });
|
|
36
|
+
};
|
|
20
37
|
var deleteCookie = (c, name, opt) => {
|
|
21
38
|
setCookie(c, name, "", { ...opt, maxAge: 0 });
|
|
22
39
|
};
|
|
23
40
|
export {
|
|
24
41
|
deleteCookie,
|
|
25
42
|
getCookie,
|
|
26
|
-
|
|
43
|
+
getSignedCookie,
|
|
44
|
+
setCookie,
|
|
45
|
+
setSignedCookie
|
|
27
46
|
};
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
var prettyJSON = (options = { space: 2 }) => {
|
|
3
3
|
return async (c, next) => {
|
|
4
4
|
const pretty = c.req.query("pretty") || c.req.query("pretty") === "" ? true : false;
|
|
5
|
-
c.pretty(pretty, options.space);
|
|
6
5
|
await next();
|
|
6
|
+
if (pretty && c.res.headers.get("Content-Type")?.startsWith("application/json")) {
|
|
7
|
+
const obj = await c.res.json();
|
|
8
|
+
c.res = new Response(JSON.stringify(obj, null, options.space), c.res);
|
|
9
|
+
}
|
|
7
10
|
};
|
|
8
11
|
};
|
|
9
12
|
export {
|
|
@@ -46,4 +46,5 @@ interface APIGatewayProxyResult {
|
|
|
46
46
|
*/
|
|
47
47
|
export declare const handle: <E extends Env = Env, S = {}, BasePath extends string = "/">(app: Hono<E, S, BasePath>) => (event: APIGatewayProxyEvent | APIGatewayProxyEventV2 | LambdaFunctionUrlEvent) => Promise<APIGatewayProxyResult>;
|
|
48
48
|
export declare const isContentTypeBinary: (contentType: string) => boolean;
|
|
49
|
+
export declare const isContentEncodingBinary: (contentEncoding: string | null) => boolean;
|
|
49
50
|
export {};
|
package/dist/types/context.d.ts
CHANGED
|
@@ -57,14 +57,13 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
|
|
|
57
57
|
private _req?;
|
|
58
58
|
private _status;
|
|
59
59
|
private _exCtx;
|
|
60
|
-
private _pre;
|
|
61
|
-
private _preS;
|
|
62
60
|
private _map;
|
|
63
61
|
private _h;
|
|
64
62
|
private _pH;
|
|
65
63
|
private _res;
|
|
66
64
|
private _path;
|
|
67
65
|
private _params?;
|
|
66
|
+
private _init;
|
|
68
67
|
private rawRequest?;
|
|
69
68
|
private notFoundHandler;
|
|
70
69
|
constructor(req: Request, options?: ContextOptions<E>);
|
|
@@ -79,7 +78,6 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
|
|
|
79
78
|
status: (status: StatusCode) => void;
|
|
80
79
|
set: Set<E>;
|
|
81
80
|
get: Get<E>;
|
|
82
|
-
pretty: (prettyJSON: boolean, space?: number) => void;
|
|
83
81
|
newResponse: NewResponse;
|
|
84
82
|
body: BodyRespond;
|
|
85
83
|
text: TextRespond;
|
|
@@ -34,9 +34,10 @@ declare class Hono<E extends Env = Env, S = {}, BasePath extends string = '/'> e
|
|
|
34
34
|
private notFoundHandler;
|
|
35
35
|
private errorHandler;
|
|
36
36
|
route<SubPath extends string, SubEnv extends Env, SubSchema, SubBasePath extends string>(path: SubPath, app: Hono<SubEnv, SubSchema, SubBasePath>): Hono<E, RemoveBlankRecord<MergeSchemaPath<SubSchema, SubPath> | S>, BasePath>;
|
|
37
|
-
/** @
|
|
38
|
-
* Use `basePath` instead of `route`
|
|
39
|
-
* The `route` with one argument has been removed in v4.
|
|
37
|
+
/** @description
|
|
38
|
+
* Use `basePath` instead of `route` when passing **one** argument, such as `app.route('/api')`.
|
|
39
|
+
* The use of `route` with **one** argument has been removed in v4.
|
|
40
|
+
* However, you can still use `route` with **two** arguments, like `app.route('/api', subApp)`."
|
|
40
41
|
*/
|
|
41
42
|
route<SubPath extends string>(path: SubPath): Hono<E, RemoveBlankRecord<S>, BasePath>;
|
|
42
43
|
basePath<SubPath extends string>(path: SubPath): Hono<E, S, MergePath<BasePath, SubPath>>;
|
|
@@ -60,9 +61,14 @@ declare class Hono<E extends Env = Env, S = {}, BasePath extends string = '/'> e
|
|
|
60
61
|
private matchRoute;
|
|
61
62
|
private handleError;
|
|
62
63
|
private dispatch;
|
|
64
|
+
/**
|
|
65
|
+
* @deprecate
|
|
66
|
+
* `app.handleEvent()` will be removed in v4.
|
|
67
|
+
* Use `app.fetch()` instead of `app.handleEvent()`.
|
|
68
|
+
*/
|
|
63
69
|
handleEvent: (event: FetchEventLike) => Response | Promise<Response>;
|
|
64
70
|
fetch: (request: Request, Env?: E['Bindings'] | {}, executionCtx?: ExecutionContext) => Response | Promise<Response>;
|
|
65
|
-
request: (input: Request | string | URL, requestInit?: RequestInit) => Promise<Response>;
|
|
71
|
+
request: (input: Request | string | URL, requestInit?: RequestInit) => Response | Promise<Response>;
|
|
66
72
|
fire: () => void;
|
|
67
73
|
}
|
|
68
74
|
export { Hono as HonoBase };
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import type { Context } from '../../context';
|
|
2
|
-
import type { CookieOptions, Cookie } from '../../utils/cookie';
|
|
2
|
+
import type { CookieOptions, Cookie, SignedCookie } from '../../utils/cookie';
|
|
3
3
|
interface GetCookie {
|
|
4
4
|
(c: Context, key: string): string | undefined;
|
|
5
5
|
(c: Context): Cookie;
|
|
6
6
|
}
|
|
7
|
+
interface GetSignedCookie {
|
|
8
|
+
(c: Context, sercet: string, key: string): Promise<string | undefined | false>;
|
|
9
|
+
(c: Context, secret: string): Promise<SignedCookie>;
|
|
10
|
+
}
|
|
7
11
|
export declare const getCookie: GetCookie;
|
|
12
|
+
export declare const getSignedCookie: GetSignedCookie;
|
|
8
13
|
export declare const setCookie: (c: Context, name: string, value: string, opt?: CookieOptions) => void;
|
|
14
|
+
export declare const setSignedCookie: (c: Context, name: string, value: string, secret: string, opt?: CookieOptions) => Promise<void>;
|
|
9
15
|
export declare const deleteCookie: (c: Context, name: string, opt?: CookieOptions) => void;
|
|
10
16
|
export {};
|
package/dist/types/request.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
|
|
|
36
36
|
* app.get('/', (c) => c.json(getCookie(c)))
|
|
37
37
|
*/
|
|
38
38
|
cookie(): Cookie;
|
|
39
|
-
parseBody(): Promise<
|
|
39
|
+
parseBody<T extends BodyData = BodyData>(): Promise<T>;
|
|
40
40
|
json<T = any>(): Promise<T>;
|
|
41
41
|
text(): Promise<string>;
|
|
42
42
|
arrayBuffer(): Promise<ArrayBuffer>;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -36,7 +36,8 @@ export interface HandlerInterface<E extends Env = Env, M extends string = any, S
|
|
|
36
36
|
H<E, ExtractKey<S>, I5, O>
|
|
37
37
|
]): Hono<E, RemoveBlankRecord<S | Schema<M, ExtractKey<S>, I5['in'], O>>, BasePath>;
|
|
38
38
|
<I extends Input = {}, O = {}>(...handlers: Handler<E, ExtractKey<S>, I, O>[]): Hono<E, RemoveBlankRecord<S | Schema<M, ExtractKey<S>, I['in'], O>>, BasePath>;
|
|
39
|
-
<P extends string, O = {}, I extends Input = {}>(path: P,
|
|
39
|
+
<P extends string, O = {}, I extends Input = {}>(path: P, handler: H<E, MergePath<BasePath, P>, I, O>): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I['in'], O>>, BasePath>;
|
|
40
|
+
<P extends string, O = {}, I extends Input = {}>(path: P, ...handlers: [H<E, MergePath<BasePath, P>, I, O>, H<E, MergePath<BasePath, P>, I, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I['in'], O>>, BasePath>;
|
|
40
41
|
<P extends string, O = {}, I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2>(path: P, ...handlers: [
|
|
41
42
|
H<E, MergePath<BasePath, P>, I, O>,
|
|
42
43
|
H<E, MergePath<BasePath, P>, I2, O>,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare type BodyData = Record<string, string | File>;
|
|
2
|
-
export declare
|
|
2
|
+
export declare const parseBody: <T extends BodyData = BodyData>(r: Request | Response) => Promise<T>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare type Cookie = Record<string, string>;
|
|
2
|
+
export declare type SignedCookie = Record<string, string | false>;
|
|
2
3
|
export declare type CookieOptions = {
|
|
3
4
|
domain?: string;
|
|
4
5
|
expires?: Date;
|
|
@@ -6,8 +7,10 @@ export declare type CookieOptions = {
|
|
|
6
7
|
maxAge?: number;
|
|
7
8
|
path?: string;
|
|
8
9
|
secure?: boolean;
|
|
9
|
-
|
|
10
|
+
signingSecret?: string;
|
|
10
11
|
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
11
12
|
};
|
|
12
|
-
export declare const parse: (cookie: string) => Cookie;
|
|
13
|
+
export declare const parse: (cookie: string, name?: string) => Cookie;
|
|
14
|
+
export declare const parseSigned: (cookie: string, secret: string, name?: string) => Promise<SignedCookie>;
|
|
13
15
|
export declare const serialize: (name: string, value: string, opt?: CookieOptions) => string;
|
|
16
|
+
export declare const serializeSigned: (name: string, value: string, secret: string, opt?: CookieOptions) => Promise<string>;
|
|
@@ -2,7 +2,7 @@ import type { Context } from '../context';
|
|
|
2
2
|
import type { Env, ValidationTargets, MiddlewareHandler } from '../types';
|
|
3
3
|
declare type ValidationTargetKeysWithBody = 'form' | 'json';
|
|
4
4
|
declare type ValidationTargetByMethod<M> = M extends 'get' | 'head' ? Exclude<keyof ValidationTargets, ValidationTargetKeysWithBody> : keyof ValidationTargets;
|
|
5
|
-
export declare type ValidationFunction<InputType, OutputType, E extends Env = {}, P extends string = string> = (value: InputType, c: Context<E, P>) => OutputType | Response | Promise<Response>;
|
|
5
|
+
export declare type ValidationFunction<InputType, OutputType, E extends Env = {}, P extends string = string> = (value: InputType, c: Context<E, P>) => OutputType | Response | Promise<OutputType> | Promise<Response>;
|
|
6
6
|
export declare const validator: <InputType, P extends string, M extends string, U extends ValidationTargetByMethod<M>, OutputType = ValidationTargets[U], P2 extends string = P, V extends {
|
|
7
7
|
in: { [K in U]: unknown extends InputType ? OutputType : InputType; };
|
|
8
8
|
out: { [K_1 in U]: OutputType; };
|
package/dist/utils/body.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/utils/body.ts
|
|
2
|
-
async
|
|
2
|
+
var parseBody = async (r) => {
|
|
3
3
|
let body = {};
|
|
4
4
|
const contentType = r.headers.get("Content-Type");
|
|
5
5
|
if (contentType && (contentType.startsWith("multipart/form-data") || contentType.startsWith("application/x-www-form-urlencoded"))) {
|
|
@@ -10,7 +10,7 @@ async function parseBody(r) {
|
|
|
10
10
|
body = form;
|
|
11
11
|
}
|
|
12
12
|
return body;
|
|
13
|
-
}
|
|
13
|
+
};
|
|
14
14
|
export {
|
|
15
15
|
parseBody
|
|
16
16
|
};
|
package/dist/utils/cookie.js
CHANGED
|
@@ -1,16 +1,55 @@
|
|
|
1
1
|
// src/utils/cookie.ts
|
|
2
2
|
import { decodeURIComponent_ } from "./url.js";
|
|
3
|
-
var
|
|
3
|
+
var makeSignature = async (value, secret) => {
|
|
4
|
+
const algorithm = { name: "HMAC", hash: "SHA-256" };
|
|
5
|
+
const encoder = new TextEncoder();
|
|
6
|
+
const key = await crypto.subtle.importKey("raw", encoder.encode(secret), algorithm, false, [
|
|
7
|
+
"sign",
|
|
8
|
+
"verify"
|
|
9
|
+
]);
|
|
10
|
+
const signature = await crypto.subtle.sign(algorithm.name, key, encoder.encode(value));
|
|
11
|
+
return btoa(String.fromCharCode(...new Uint8Array(signature)));
|
|
12
|
+
};
|
|
13
|
+
var _parseCookiePairs = (cookie, name) => {
|
|
4
14
|
const pairs = cookie.split(/;\s*/g);
|
|
15
|
+
const cookiePairs = pairs.map((pairStr) => pairStr.split(/\s*=\s*([^\s]+)/));
|
|
16
|
+
if (!name)
|
|
17
|
+
return cookiePairs;
|
|
18
|
+
return cookiePairs.filter((pair) => pair[0] === name);
|
|
19
|
+
};
|
|
20
|
+
var parse = (cookie, name) => {
|
|
5
21
|
const parsedCookie = {};
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
22
|
+
const unsingedCookies = _parseCookiePairs(cookie, name).filter((pair) => {
|
|
23
|
+
if (pair[1].split(".").length === 2)
|
|
24
|
+
return false;
|
|
25
|
+
return true;
|
|
26
|
+
});
|
|
27
|
+
for (let [key, value] of unsingedCookies) {
|
|
28
|
+
value = decodeURIComponent_(value);
|
|
29
|
+
parsedCookie[key] = value;
|
|
9
30
|
}
|
|
10
31
|
return parsedCookie;
|
|
11
32
|
};
|
|
12
|
-
var
|
|
13
|
-
|
|
33
|
+
var parseSigned = async (cookie, secret, name) => {
|
|
34
|
+
const parsedCookie = {};
|
|
35
|
+
const signedCookies = _parseCookiePairs(cookie, name).filter((pair) => {
|
|
36
|
+
if (pair[1].split(".").length !== 2)
|
|
37
|
+
return false;
|
|
38
|
+
return true;
|
|
39
|
+
});
|
|
40
|
+
for (let [key, value] of signedCookies) {
|
|
41
|
+
value = decodeURIComponent_(value);
|
|
42
|
+
const signedPair = value.split(".");
|
|
43
|
+
const signatureToCompare = await makeSignature(signedPair[0], secret);
|
|
44
|
+
if (signedPair[1] !== signatureToCompare) {
|
|
45
|
+
parsedCookie[key] = false;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
parsedCookie[key] = signedPair[0];
|
|
49
|
+
}
|
|
50
|
+
return parsedCookie;
|
|
51
|
+
};
|
|
52
|
+
var _serialize = (name, value, opt = {}) => {
|
|
14
53
|
let cookie = `${name}=${value}`;
|
|
15
54
|
if (opt && typeof opt.maxAge === "number" && opt.maxAge >= 0) {
|
|
16
55
|
cookie += `; Max-Age=${Math.floor(opt.maxAge)}`;
|
|
@@ -35,7 +74,19 @@ var serialize = (name, value, opt = {}) => {
|
|
|
35
74
|
}
|
|
36
75
|
return cookie;
|
|
37
76
|
};
|
|
77
|
+
var serialize = (name, value, opt = {}) => {
|
|
78
|
+
value = encodeURIComponent(value);
|
|
79
|
+
return _serialize(name, value, opt);
|
|
80
|
+
};
|
|
81
|
+
var serializeSigned = async (name, value, secret, opt = {}) => {
|
|
82
|
+
const signature = await makeSignature(value, secret);
|
|
83
|
+
value = `${value}.${signature}`;
|
|
84
|
+
value = encodeURIComponent(value);
|
|
85
|
+
return _serialize(name, value, opt);
|
|
86
|
+
};
|
|
38
87
|
export {
|
|
39
88
|
parse,
|
|
40
|
-
|
|
89
|
+
parseSigned,
|
|
90
|
+
serialize,
|
|
91
|
+
serializeSigned
|
|
41
92
|
};
|
package/dist/utils/url.js
CHANGED
|
@@ -55,9 +55,8 @@ var getPattern = (label) => {
|
|
|
55
55
|
return null;
|
|
56
56
|
};
|
|
57
57
|
var getPath = (request) => {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
return url.slice(url.indexOf("/", 8), queryIndex === -1 ? void 0 : queryIndex);
|
|
58
|
+
const match = request.url.match(/^https?:\/\/[^/]+(\/[^?]*)/);
|
|
59
|
+
return match ? match[1] : "";
|
|
61
60
|
};
|
|
62
61
|
var getQueryStrings = (url) => {
|
|
63
62
|
const queryIndex = url.indexOf("?", 8);
|
|
@@ -104,7 +103,7 @@ var _decodeURI = (value) => {
|
|
|
104
103
|
if (value.indexOf("+") !== -1) {
|
|
105
104
|
value = value.replace(/\+/g, " ");
|
|
106
105
|
}
|
|
107
|
-
return value
|
|
106
|
+
return /%/.test(value) ? decodeURIComponent_(value) : value;
|
|
108
107
|
};
|
|
109
108
|
var _getQueryParam = (url, key, multiple) => {
|
|
110
109
|
let encoded;
|
|
@@ -35,8 +35,8 @@ var validator = (target, validationFunc) => {
|
|
|
35
35
|
value = c.req.param();
|
|
36
36
|
break;
|
|
37
37
|
}
|
|
38
|
-
const res = validationFunc(value, c);
|
|
39
|
-
if (res instanceof Response
|
|
38
|
+
const res = await validationFunc(value, c);
|
|
39
|
+
if (res instanceof Response) {
|
|
40
40
|
return res;
|
|
41
41
|
}
|
|
42
42
|
c.req.addValidatedData(target, res);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Ultrafast web framework for the Edges",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"test:deno": "env NAME=Deno deno test --allow-read --allow-env runtime_tests/deno",
|
|
15
15
|
"test:bun": "env NAME=Bun bun test --jsx-import-source ../../src/middleware/jsx runtime_tests/bun/index.test.tsx",
|
|
16
16
|
"test:fastly": "jest --config ./runtime_tests/fastly/jest.config.js",
|
|
17
|
-
"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 jest runtime_tests/lagon/index.test.ts --testMatch '**/*.test.ts'\"",
|
|
17
|
+
"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 jest runtime_tests/lagon/index.test.ts --roots runtime_tests/lagon --testMatch '**/*.test.ts'\"",
|
|
18
18
|
"test:node": "env NAME=Node jest --config ./runtime_tests/node/jest.config.js",
|
|
19
19
|
"test:wrangler": "jest --config ./runtime_tests/wrangler/jest.config.js",
|
|
20
20
|
"test:lambda": "env NAME=Node jest --config ./runtime_tests/lambda/jest.config.js",
|