hono 4.12.9 → 4.12.12

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.
@@ -20,9 +20,45 @@ export interface IPRestrictionRules {
20
20
  allowList?: IPRestrictionRule[];
21
21
  }
22
22
  /**
23
- * IP Restriction Middleware
23
+ * IP Restriction Middleware for Hono.
24
24
  *
25
- * @param getIP function to get IP Address
25
+ * @see {@link https://hono.dev/docs/middleware/builtin/ip-restriction}
26
+ *
27
+ * @param {GetConnInfo | ((c: Context) => string)} getIP - A function to retrieve the client IP address. Use `getConnInfo` from the appropriate runtime adapter.
28
+ * @param {IPRestrictionRules} rules - An object with optional `denyList` and `allowList` arrays of IP rules. Each rule can be a static IP, a CIDR range, or a custom function.
29
+ * @param {(remote: { addr: string; type: AddressType }, c: Context) => Response | Promise<Response>} [onError] - Optional custom handler invoked when a request is blocked. Defaults to returning a 403 Forbidden response.
30
+ * @returns {MiddlewareHandler} The middleware handler function.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * import { Hono } from 'hono'
35
+ * import { ipRestriction } from 'hono/ip-restriction'
36
+ * import { getConnInfo } from 'hono/cloudflare-workers'
37
+ *
38
+ * const app = new Hono()
39
+ *
40
+ * app.use(
41
+ * '*',
42
+ * ipRestriction(getConnInfo, {
43
+ * // Block a specific IP and an entire subnet
44
+ * denyList: ['192.168.0.5', '10.0.0.0/8'],
45
+ * // Only allow requests from localhost and a private range
46
+ * allowList: ['127.0.0.1', '::1', '192.168.1.0/24'],
47
+ * })
48
+ * )
49
+ *
50
+ * // With a custom error handler
51
+ * app.use(
52
+ * '/admin/*',
53
+ * ipRestriction(
54
+ * getConnInfo,
55
+ * { allowList: ['203.0.113.0/24'] },
56
+ * (remote, c) => c.text(`Access denied for ${remote.addr}`, 403)
57
+ * )
58
+ * )
59
+ *
60
+ * app.get('/', (c) => c.text('Hello!'))
61
+ * ```
26
62
  */
27
63
  export declare const ipRestriction: (getIP: GetIPAddr, { denyList, allowList }: IPRestrictionRules, onError?: (remote: {
28
64
  addr: string;
@@ -32,6 +32,18 @@ export declare const convertIPv6ToBinary: (ipv6: string) => bigint;
32
32
  * @return IPv4 Address in string
33
33
  */
34
34
  export declare const convertIPv4BinaryToString: (ipV4: bigint) => string;
35
+ /**
36
+ * Check if a binary IPv6 address is an IPv4-mapped IPv6 address (::ffff:x.x.x.x)
37
+ * @param ipv6binary binary IPv6 Address
38
+ * @return true if the address is an IPv4-mapped IPv6 address
39
+ */
40
+ export declare const isIPv4MappedIPv6: (ipv6binary: bigint) => boolean;
41
+ /**
42
+ * Extract the IPv4 portion from an IPv4-mapped IPv6 address
43
+ * @param ipv6binary binary IPv4-mapped IPv6 Address
44
+ * @return binary IPv4 Address
45
+ */
46
+ export declare const convertIPv4MappedIPv6ToIPv4: (ipv6binary: bigint) => bigint;
35
47
  /**
36
48
  * Convert a binary representation of an IPv6 address to a string.
37
49
  * @param ipV6 binary IPv6 Address
@@ -24,23 +24,41 @@ var verifySignature = async (base64Signature, value, secret) => {
24
24
  };
25
25
  var validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/;
26
26
  var validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/;
27
+ var trimCookieWhitespace = (value) => {
28
+ let start = 0;
29
+ let end = value.length;
30
+ while (start < end) {
31
+ const charCode = value.charCodeAt(start);
32
+ if (charCode !== 32 && charCode !== 9) {
33
+ break;
34
+ }
35
+ start++;
36
+ }
37
+ while (end > start) {
38
+ const charCode = value.charCodeAt(end - 1);
39
+ if (charCode !== 32 && charCode !== 9) {
40
+ break;
41
+ }
42
+ end--;
43
+ }
44
+ return start === 0 && end === value.length ? value : value.slice(start, end);
45
+ };
27
46
  var parse = (cookie, name) => {
28
47
  if (name && cookie.indexOf(name) === -1) {
29
48
  return {};
30
49
  }
31
- const pairs = cookie.trim().split(";");
50
+ const pairs = cookie.split(";");
32
51
  const parsedCookie = {};
33
- for (let pairStr of pairs) {
34
- pairStr = pairStr.trim();
52
+ for (const pairStr of pairs) {
35
53
  const valueStartPos = pairStr.indexOf("=");
36
54
  if (valueStartPos === -1) {
37
55
  continue;
38
56
  }
39
- const cookieName = pairStr.substring(0, valueStartPos).trim();
57
+ const cookieName = trimCookieWhitespace(pairStr.substring(0, valueStartPos));
40
58
  if (name && name !== cookieName || !validCookieNameRegEx.test(cookieName)) {
41
59
  continue;
42
60
  }
43
- let cookieValue = pairStr.substring(valueStartPos + 1).trim();
61
+ let cookieValue = trimCookieWhitespace(pairStr.substring(valueStartPos + 1));
44
62
  if (cookieValue.startsWith('"') && cookieValue.endsWith('"')) {
45
63
  cookieValue = cookieValue.slice(1, -1);
46
64
  }
@@ -72,6 +90,9 @@ var parseSigned = async (cookie, secret, name) => {
72
90
  return parsedCookie;
73
91
  };
74
92
  var _serialize = (name, value, opt = {}) => {
93
+ if (!validCookieNameRegEx.test(name)) {
94
+ throw new Error("Invalid cookie name");
95
+ }
75
96
  let cookie = `${name}=${value}`;
76
97
  if (name.startsWith("__Secure-") && !opt.secure) {
77
98
  throw new Error("__Secure- Cookie must have Secure attributes");
@@ -55,9 +55,11 @@ var convertIPv4BinaryToString = (ipV4) => {
55
55
  }
56
56
  return sections.join(".");
57
57
  };
58
+ var isIPv4MappedIPv6 = (ipv6binary) => ipv6binary >> 32n === 0xffffn;
59
+ var convertIPv4MappedIPv6ToIPv4 = (ipv6binary) => ipv6binary & 0xffffffffn;
58
60
  var convertIPv6BinaryToString = (ipV6) => {
59
- if (ipV6 >> 32n === 0xffffn) {
60
- return `::ffff:${convertIPv4BinaryToString(ipV6 & 0xffffffffn)}`;
61
+ if (isIPv4MappedIPv6(ipV6)) {
62
+ return `::ffff:${convertIPv4BinaryToString(convertIPv4MappedIPv6ToIPv4(ipV6))}`;
61
63
  }
62
64
  const sections = [];
63
65
  for (let i = 0; i < 8; i++) {
@@ -94,9 +96,11 @@ var convertIPv6BinaryToString = (ipV6) => {
94
96
  };
95
97
  export {
96
98
  convertIPv4BinaryToString,
99
+ convertIPv4MappedIPv6ToIPv4,
97
100
  convertIPv4ToBinary,
98
101
  convertIPv6BinaryToString,
99
102
  convertIPv6ToBinary,
100
103
  distinctRemoteAddr,
101
- expandIPv6
104
+ expandIPv6,
105
+ isIPv4MappedIPv6
102
106
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "4.12.9",
3
+ "version": "4.12.12",
4
4
  "description": "Web framework built on Web Standards",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",