hono 3.1.0 → 3.1.1

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.
@@ -39,6 +39,7 @@ class Context {
39
39
  if (options?.append) {
40
40
  if (!this._headers) {
41
41
  this._headers = new Headers(this._preparedHeaders);
42
+ this._preparedHeaders = {};
42
43
  }
43
44
  this._headers.append(name, value);
44
45
  } else {
@@ -87,11 +88,9 @@ class Context {
87
88
  }
88
89
  const status = arg ?? this._status;
89
90
  this._preparedHeaders ?? (this._preparedHeaders = {});
90
- if (!this._headers) {
91
- this._headers = new Headers();
92
- for (const [k, v] of Object.entries(this._preparedHeaders)) {
93
- this._headers.set(k, v);
94
- }
91
+ this._headers ?? (this._headers = new Headers());
92
+ for (const [k, v] of Object.entries(this._preparedHeaders)) {
93
+ this._headers.set(k, v);
95
94
  }
96
95
  if (this._res) {
97
96
  this._res.headers.forEach((v, k) => {
@@ -26,12 +26,13 @@ var import_buffer = require("../../utils/buffer");
26
26
  var import_encode = require("../../utils/encode");
27
27
  const CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
28
28
  const USER_PASS_REGEXP = /^([^:]*):(.*)$/;
29
+ const utf8Decoder = new TextDecoder();
29
30
  const auth = (req) => {
30
31
  const match = CREDENTIALS_REGEXP.exec(req.headers.get("Authorization") || "");
31
32
  if (!match) {
32
33
  return void 0;
33
34
  }
34
- const userPass = USER_PASS_REGEXP.exec((0, import_encode.decodeBase64)(match[1]));
35
+ const userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode((0, import_encode.decodeBase64)(match[1])));
35
36
  if (!userPass) {
36
37
  return void 0;
37
38
  }
@@ -18,65 +18,34 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var encode_exports = {};
20
20
  __export(encode_exports, {
21
- arrayBufferToBase64: () => arrayBufferToBase64,
22
- arrayBufferToBase64URL: () => arrayBufferToBase64URL,
23
21
  decodeBase64: () => decodeBase64,
24
- decodeBase64URL: () => decodeBase64URL,
22
+ decodeBase64Url: () => decodeBase64Url,
25
23
  encodeBase64: () => encodeBase64,
26
- encodeBase64URL: () => encodeBase64URL,
27
- utf8ToUint8Array: () => utf8ToUint8Array
24
+ encodeBase64Url: () => encodeBase64Url
28
25
  });
29
26
  module.exports = __toCommonJS(encode_exports);
30
- const encodeBase64 = (str) => {
31
- if (str === null) {
32
- throw new TypeError('1st argument of "encodeBase64" should not be null.');
33
- }
34
- const encoder = new TextEncoder();
35
- const bytes = encoder.encode(str);
36
- return btoa(String.fromCharCode(...bytes));
27
+ const decodeBase64Url = (str) => {
28
+ return decodeBase64(str.replace(/_|-/g, (m) => ({ _: "/", "-": "+" })[m] ?? m));
29
+ };
30
+ const encodeBase64Url = (buf) => encodeBase64(buf).replace(/\/|\+/g, (m) => ({ "/": "_", "+": "-" })[m] ?? m);
31
+ const encodeBase64 = (buf) => {
32
+ const binary = String.fromCharCode(...new Uint8Array(buf));
33
+ return btoa(binary);
37
34
  };
38
35
  const decodeBase64 = (str) => {
39
- if (str === null) {
40
- throw new TypeError('1st argument of "decodeBase64" should not be null.');
36
+ const binary = atob(str);
37
+ const bytes = new Uint8Array(new ArrayBuffer(binary.length));
38
+ const half = binary.length / 2;
39
+ for (let i = 0, j = binary.length - 1; i <= half; i++, j--) {
40
+ bytes[i] = binary.charCodeAt(i);
41
+ bytes[j] = binary.charCodeAt(j);
41
42
  }
42
- const text = atob(str);
43
- const bytes = new Uint8Array(text.split("").map((c) => c.charCodeAt(0)));
44
- const decoder = new TextDecoder();
45
- return decoder.decode(bytes);
46
- };
47
- const encodeBase64URL = (str) => {
48
- return encodeBase64(str).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
49
- };
50
- const decodeBase64URL = (str) => {
51
- const pad = (s) => {
52
- const diff = s.length % 4;
53
- if (diff === 2) {
54
- return `${s}==`;
55
- }
56
- if (diff === 3) {
57
- return `${s}=`;
58
- }
59
- return s;
60
- };
61
- return decodeBase64(pad(str).replace(/-/g, "+").replace("_", "/"));
62
- };
63
- const utf8ToUint8Array = (str) => {
64
- const encoder = new TextEncoder();
65
- return encoder.encode(str);
66
- };
67
- const arrayBufferToBase64 = async (buf) => {
68
- return btoa(String.fromCharCode(...new Uint8Array(buf)));
69
- };
70
- const arrayBufferToBase64URL = async (buf) => {
71
- return (await arrayBufferToBase64(buf)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
43
+ return bytes;
72
44
  };
73
45
  // Annotate the CommonJS export names for ESM import in node:
74
46
  0 && (module.exports = {
75
- arrayBufferToBase64,
76
- arrayBufferToBase64URL,
77
47
  decodeBase64,
78
- decodeBase64URL,
48
+ decodeBase64Url,
79
49
  encodeBase64,
80
- encodeBase64URL,
81
- utf8ToUint8Array
50
+ encodeBase64Url
82
51
  });
@@ -44,6 +44,11 @@ var CryptoKeyUsage = /* @__PURE__ */ ((CryptoKeyUsage2) => {
44
44
  CryptoKeyUsage2["UnwrapKey"] = "unwrapKey";
45
45
  return CryptoKeyUsage2;
46
46
  })(CryptoKeyUsage || {});
47
+ const utf8Encoder = new TextEncoder();
48
+ const utf8Decoder = new TextDecoder();
49
+ const encodeJwtPart = (part) => (0, import_encode.encodeBase64Url)(utf8Encoder.encode(JSON.stringify(part))).replace(/=/g, "");
50
+ const encodeSignaturePart = (buf) => (0, import_encode.encodeBase64Url)(buf).replace(/=/g, "");
51
+ const decodeJwtPart = (part) => JSON.parse(utf8Decoder.decode((0, import_encode.decodeBase64Url)(part)));
47
52
  const param = (name) => {
48
53
  switch (name.toUpperCase()) {
49
54
  case "HS256":
@@ -75,20 +80,22 @@ const signing = async (data, secret, alg = import_types.AlgorithmTypes.HS256) =>
75
80
  if (!crypto.subtle || !crypto.subtle.importKey) {
76
81
  throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");
77
82
  }
83
+ const utf8Encoder2 = new TextEncoder();
78
84
  const cryptoKey = await crypto.subtle.importKey(
79
85
  "raw" /* RAW */,
80
- (0, import_encode.utf8ToUint8Array)(secret),
86
+ utf8Encoder2.encode(secret),
81
87
  param(alg),
82
88
  false,
83
89
  ["sign" /* Sign */]
84
90
  );
85
- return await crypto.subtle.sign(param(alg), cryptoKey, (0, import_encode.utf8ToUint8Array)(data));
91
+ return await crypto.subtle.sign(param(alg), cryptoKey, utf8Encoder2.encode(data));
86
92
  };
87
93
  const sign = async (payload, secret, alg = import_types.AlgorithmTypes.HS256) => {
88
- const encodedPayload = await (0, import_encode.encodeBase64URL)(JSON.stringify(payload));
89
- const encodedHeader = await (0, import_encode.encodeBase64URL)(JSON.stringify({ alg, typ: "JWT" }));
94
+ const encodedPayload = encodeJwtPart(payload);
95
+ const encodedHeader = encodeJwtPart({ alg, typ: "JWT" });
90
96
  const partialToken = `${encodedHeader}.${encodedPayload}`;
91
- const signature = await (0, import_encode.arrayBufferToBase64URL)(await signing(partialToken, secret, alg));
97
+ const signaturePart = await signing(partialToken, secret, alg);
98
+ const signature = encodeSignaturePart(signaturePart);
92
99
  return `${partialToken}.${signature}`;
93
100
  };
94
101
  const verify = async (token, secret, alg = import_types.AlgorithmTypes.HS256) => {
@@ -103,10 +110,10 @@ const verify = async (token, secret, alg = import_types.AlgorithmTypes.HS256) =>
103
110
  if (payload.exp && payload.exp <= Math.floor(Date.now() / 1e3)) {
104
111
  throw new import_types2.JwtTokenExpired(token);
105
112
  }
106
- const signature = await (0, import_encode.arrayBufferToBase64URL)(
107
- await signing(tokenParts.slice(0, 2).join("."), secret, alg)
108
- );
109
- if (signature !== tokenParts[2]) {
113
+ const signaturePart = tokenParts.slice(0, 2).join(".");
114
+ const signature = await signing(signaturePart, secret, alg);
115
+ const encodedSignature = encodeSignaturePart(signature);
116
+ if (encodedSignature !== tokenParts[2]) {
110
117
  throw new import_types2.JwtTokenSignatureMismatched(token);
111
118
  }
112
119
  return true;
@@ -114,8 +121,8 @@ const verify = async (token, secret, alg = import_types.AlgorithmTypes.HS256) =>
114
121
  const decode = (token) => {
115
122
  try {
116
123
  const [h, p] = token.split(".");
117
- const header = JSON.parse((0, import_encode.decodeBase64URL)(h));
118
- const payload = JSON.parse((0, import_encode.decodeBase64URL)(p));
124
+ const header = decodeJwtPart(h);
125
+ const payload = decodeJwtPart(p);
119
126
  return {
120
127
  header,
121
128
  payload
package/dist/context.js CHANGED
@@ -25,6 +25,7 @@ var Context = class {
25
25
  if (options?.append) {
26
26
  if (!this._headers) {
27
27
  this._headers = new Headers(this._preparedHeaders);
28
+ this._preparedHeaders = {};
28
29
  }
29
30
  this._headers.append(name, value);
30
31
  } else {
@@ -73,11 +74,9 @@ var Context = class {
73
74
  }
74
75
  const status = arg ?? this._status;
75
76
  this._preparedHeaders ?? (this._preparedHeaders = {});
76
- if (!this._headers) {
77
- this._headers = new Headers();
78
- for (const [k, v] of Object.entries(this._preparedHeaders)) {
79
- this._headers.set(k, v);
80
- }
77
+ this._headers ?? (this._headers = new Headers());
78
+ for (const [k, v] of Object.entries(this._preparedHeaders)) {
79
+ this._headers.set(k, v);
81
80
  }
82
81
  if (this._res) {
83
82
  this._res.headers.forEach((v, k) => {
@@ -4,12 +4,13 @@ import { timingSafeEqual } from "../../utils/buffer.js";
4
4
  import { decodeBase64 } from "../../utils/encode.js";
5
5
  var CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
6
6
  var USER_PASS_REGEXP = /^([^:]*):(.*)$/;
7
+ var utf8Decoder = new TextDecoder();
7
8
  var auth = (req) => {
8
9
  const match = CREDENTIALS_REGEXP.exec(req.headers.get("Authorization") || "");
9
10
  if (!match) {
10
11
  return void 0;
11
12
  }
12
- const userPass = USER_PASS_REGEXP.exec(decodeBase64(match[1]));
13
+ const userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode(decodeBase64(match[1])));
13
14
  if (!userPass) {
14
15
  return void 0;
15
16
  }
@@ -31,7 +31,7 @@ export declare class Hono<E extends Env = Env, S = {}, BasePath extends string =
31
31
  private clone;
32
32
  private notFoundHandler;
33
33
  private errorHandler;
34
- route<SubPath extends string, SubEnv extends Env, SubSchema>(path: SubPath, app: Hono<SubEnv, SubSchema>): Hono<E, RemoveBlankRecord<MergeSchemaPath<SubSchema, SubPath> | S>, BasePath>;
34
+ 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>;
35
35
  /** @deprecated
36
36
  * Use `basePath` instead of `route` with one argument.
37
37
  * The `route` with one argument has been removed in v4.
@@ -1,7 +1,4 @@
1
- export declare const encodeBase64: (str: string) => string;
2
- export declare const decodeBase64: (str: string) => string;
3
- export declare const encodeBase64URL: (str: string) => string;
4
- export declare const decodeBase64URL: (str: string) => string;
5
- export declare const utf8ToUint8Array: (str: string) => Uint8Array;
6
- export declare const arrayBufferToBase64: (buf: ArrayBuffer) => Promise<string>;
7
- export declare const arrayBufferToBase64URL: (buf: ArrayBuffer) => Promise<string>;
1
+ export declare const decodeBase64Url: (str: string) => Uint8Array;
2
+ export declare const encodeBase64Url: (buf: ArrayBufferLike) => string;
3
+ export declare const encodeBase64: (buf: ArrayBufferLike) => string;
4
+ export declare const decodeBase64: (str: string) => Uint8Array;
@@ -1,53 +1,25 @@
1
1
  // src/utils/encode.ts
2
- var encodeBase64 = (str) => {
3
- if (str === null) {
4
- throw new TypeError('1st argument of "encodeBase64" should not be null.');
5
- }
6
- const encoder = new TextEncoder();
7
- const bytes = encoder.encode(str);
8
- return btoa(String.fromCharCode(...bytes));
2
+ var decodeBase64Url = (str) => {
3
+ return decodeBase64(str.replace(/_|-/g, (m) => ({ _: "/", "-": "+" })[m] ?? m));
4
+ };
5
+ var encodeBase64Url = (buf) => encodeBase64(buf).replace(/\/|\+/g, (m) => ({ "/": "_", "+": "-" })[m] ?? m);
6
+ var encodeBase64 = (buf) => {
7
+ const binary = String.fromCharCode(...new Uint8Array(buf));
8
+ return btoa(binary);
9
9
  };
10
10
  var decodeBase64 = (str) => {
11
- if (str === null) {
12
- throw new TypeError('1st argument of "decodeBase64" should not be null.');
11
+ const binary = atob(str);
12
+ const bytes = new Uint8Array(new ArrayBuffer(binary.length));
13
+ const half = binary.length / 2;
14
+ for (let i = 0, j = binary.length - 1; i <= half; i++, j--) {
15
+ bytes[i] = binary.charCodeAt(i);
16
+ bytes[j] = binary.charCodeAt(j);
13
17
  }
14
- const text = atob(str);
15
- const bytes = new Uint8Array(text.split("").map((c) => c.charCodeAt(0)));
16
- const decoder = new TextDecoder();
17
- return decoder.decode(bytes);
18
- };
19
- var encodeBase64URL = (str) => {
20
- return encodeBase64(str).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
21
- };
22
- var decodeBase64URL = (str) => {
23
- const pad = (s) => {
24
- const diff = s.length % 4;
25
- if (diff === 2) {
26
- return `${s}==`;
27
- }
28
- if (diff === 3) {
29
- return `${s}=`;
30
- }
31
- return s;
32
- };
33
- return decodeBase64(pad(str).replace(/-/g, "+").replace("_", "/"));
34
- };
35
- var utf8ToUint8Array = (str) => {
36
- const encoder = new TextEncoder();
37
- return encoder.encode(str);
38
- };
39
- var arrayBufferToBase64 = async (buf) => {
40
- return btoa(String.fromCharCode(...new Uint8Array(buf)));
41
- };
42
- var arrayBufferToBase64URL = async (buf) => {
43
- return (await arrayBufferToBase64(buf)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
18
+ return bytes;
44
19
  };
45
20
  export {
46
- arrayBufferToBase64,
47
- arrayBufferToBase64URL,
48
21
  decodeBase64,
49
- decodeBase64URL,
22
+ decodeBase64Url,
50
23
  encodeBase64,
51
- encodeBase64URL,
52
- utf8ToUint8Array
24
+ encodeBase64Url
53
25
  };
@@ -1,10 +1,5 @@
1
1
  // src/utils/jwt/jwt.ts
2
- import {
3
- utf8ToUint8Array,
4
- encodeBase64URL,
5
- arrayBufferToBase64URL,
6
- decodeBase64URL
7
- } from "../../utils/encode.js";
2
+ import { encodeBase64Url, decodeBase64Url } from "../../utils/encode.js";
8
3
  import { AlgorithmTypes } from "./types.js";
9
4
  import {
10
5
  JwtTokenInvalid,
@@ -13,6 +8,11 @@ import {
13
8
  JwtTokenSignatureMismatched,
14
9
  JwtAlgorithmNotImplemented
15
10
  } from "./types.js";
11
+ var utf8Encoder = new TextEncoder();
12
+ var utf8Decoder = new TextDecoder();
13
+ var encodeJwtPart = (part) => encodeBase64Url(utf8Encoder.encode(JSON.stringify(part))).replace(/=/g, "");
14
+ var encodeSignaturePart = (buf) => encodeBase64Url(buf).replace(/=/g, "");
15
+ var decodeJwtPart = (part) => JSON.parse(utf8Decoder.decode(decodeBase64Url(part)));
16
16
  var param = (name) => {
17
17
  switch (name.toUpperCase()) {
18
18
  case "HS256":
@@ -44,20 +44,22 @@ var signing = async (data, secret, alg = AlgorithmTypes.HS256) => {
44
44
  if (!crypto.subtle || !crypto.subtle.importKey) {
45
45
  throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");
46
46
  }
47
+ const utf8Encoder2 = new TextEncoder();
47
48
  const cryptoKey = await crypto.subtle.importKey(
48
49
  "raw" /* RAW */,
49
- utf8ToUint8Array(secret),
50
+ utf8Encoder2.encode(secret),
50
51
  param(alg),
51
52
  false,
52
53
  ["sign" /* Sign */]
53
54
  );
54
- return await crypto.subtle.sign(param(alg), cryptoKey, utf8ToUint8Array(data));
55
+ return await crypto.subtle.sign(param(alg), cryptoKey, utf8Encoder2.encode(data));
55
56
  };
56
57
  var sign = async (payload, secret, alg = AlgorithmTypes.HS256) => {
57
- const encodedPayload = await encodeBase64URL(JSON.stringify(payload));
58
- const encodedHeader = await encodeBase64URL(JSON.stringify({ alg, typ: "JWT" }));
58
+ const encodedPayload = encodeJwtPart(payload);
59
+ const encodedHeader = encodeJwtPart({ alg, typ: "JWT" });
59
60
  const partialToken = `${encodedHeader}.${encodedPayload}`;
60
- const signature = await arrayBufferToBase64URL(await signing(partialToken, secret, alg));
61
+ const signaturePart = await signing(partialToken, secret, alg);
62
+ const signature = encodeSignaturePart(signaturePart);
61
63
  return `${partialToken}.${signature}`;
62
64
  };
63
65
  var verify = async (token, secret, alg = AlgorithmTypes.HS256) => {
@@ -72,10 +74,10 @@ var verify = async (token, secret, alg = AlgorithmTypes.HS256) => {
72
74
  if (payload.exp && payload.exp <= Math.floor(Date.now() / 1e3)) {
73
75
  throw new JwtTokenExpired(token);
74
76
  }
75
- const signature = await arrayBufferToBase64URL(
76
- await signing(tokenParts.slice(0, 2).join("."), secret, alg)
77
- );
78
- if (signature !== tokenParts[2]) {
77
+ const signaturePart = tokenParts.slice(0, 2).join(".");
78
+ const signature = await signing(signaturePart, secret, alg);
79
+ const encodedSignature = encodeSignaturePart(signature);
80
+ if (encodedSignature !== tokenParts[2]) {
79
81
  throw new JwtTokenSignatureMismatched(token);
80
82
  }
81
83
  return true;
@@ -83,8 +85,8 @@ var verify = async (token, secret, alg = AlgorithmTypes.HS256) => {
83
85
  var decode = (token) => {
84
86
  try {
85
87
  const [h, p] = token.split(".");
86
- const header = JSON.parse(decodeBase64URL(h));
87
- const payload = JSON.parse(decodeBase64URL(p));
88
+ const header = decodeJwtPart(h);
89
+ const payload = decodeJwtPart(p);
88
90
  return {
89
91
  header,
90
92
  payload
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "Ultrafast web framework for the Edge",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",