@shware/http 1.1.13 → 1.2.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/package.json +1 -1
- package/dist/__tests__/index.test.cjs +0 -27
- package/dist/__tests__/index.test.cjs.map +0 -1
- package/dist/__tests__/index.test.d.cts +0 -2
- package/dist/__tests__/index.test.d.ts +0 -2
- package/dist/__tests__/index.test.mjs +0 -25
- package/dist/__tests__/index.test.mjs.map +0 -1
- package/dist/cache/index.cjs +0 -32
- package/dist/cache/index.cjs.map +0 -1
- package/dist/cache/index.d.cts +0 -9
- package/dist/cache/index.d.ts +0 -9
- package/dist/cache/index.mjs +0 -7
- package/dist/cache/index.mjs.map +0 -1
- package/dist/error/detail.cjs +0 -93
- package/dist/error/detail.cjs.map +0 -1
- package/dist/error/detail.d.cts +0 -99
- package/dist/error/detail.d.ts +0 -99
- package/dist/error/detail.mjs +0 -67
- package/dist/error/detail.mjs.map +0 -1
- package/dist/error/i18n/en-us.cjs +0 -31
- package/dist/error/i18n/en-us.cjs.map +0 -1
- package/dist/error/i18n/en-us.d.cts +0 -3
- package/dist/error/i18n/en-us.d.ts +0 -3
- package/dist/error/i18n/en-us.mjs +0 -6
- package/dist/error/i18n/en-us.mjs.map +0 -1
- package/dist/error/index.cjs +0 -63
- package/dist/error/index.cjs.map +0 -1
- package/dist/error/index.d.cts +0 -19
- package/dist/error/index.d.ts +0 -19
- package/dist/error/index.mjs +0 -35
- package/dist/error/index.mjs.map +0 -1
- package/dist/error/parse.cjs +0 -52
- package/dist/error/parse.cjs.map +0 -1
- package/dist/error/parse.d.cts +0 -16
- package/dist/error/parse.d.ts +0 -16
- package/dist/error/parse.mjs +0 -27
- package/dist/error/parse.mjs.map +0 -1
- package/dist/error/reason.cjs +0 -19
- package/dist/error/reason.cjs.map +0 -1
- package/dist/error/reason.d.cts +0 -66
- package/dist/error/reason.d.ts +0 -66
- package/dist/error/reason.mjs +0 -1
- package/dist/error/reason.mjs.map +0 -1
- package/dist/error/status.cjs +0 -266
- package/dist/error/status.cjs.map +0 -1
- package/dist/error/status.d.cts +0 -69
- package/dist/error/status.d.ts +0 -69
- package/dist/error/status.mjs +0 -237
- package/dist/error/status.mjs.map +0 -1
- package/dist/google-one-tap/index.cjs +0 -51
- package/dist/google-one-tap/index.cjs.map +0 -1
- package/dist/google-one-tap/index.d.cts +0 -17
- package/dist/google-one-tap/index.d.ts +0 -17
- package/dist/google-one-tap/index.mjs +0 -26
- package/dist/google-one-tap/index.mjs.map +0 -1
- package/dist/google-one-tap/types.cjs +0 -19
- package/dist/google-one-tap/types.cjs.map +0 -1
- package/dist/google-one-tap/types.d.cts +0 -155
- package/dist/google-one-tap/types.d.ts +0 -155
- package/dist/google-one-tap/types.mjs +0 -1
- package/dist/google-one-tap/types.mjs.map +0 -1
- package/dist/hono/__tests__/authorizer.test.cjs +0 -483
- package/dist/hono/__tests__/authorizer.test.cjs.map +0 -1
- package/dist/hono/__tests__/authorizer.test.d.cts +0 -2
- package/dist/hono/__tests__/authorizer.test.d.ts +0 -2
- package/dist/hono/__tests__/authorizer.test.mjs +0 -481
- package/dist/hono/__tests__/authorizer.test.mjs.map +0 -1
- package/dist/hono/__tests__/csrf.test.cjs +0 -162
- package/dist/hono/__tests__/csrf.test.cjs.map +0 -1
- package/dist/hono/__tests__/csrf.test.d.cts +0 -2
- package/dist/hono/__tests__/csrf.test.d.ts +0 -2
- package/dist/hono/__tests__/csrf.test.mjs +0 -160
- package/dist/hono/__tests__/csrf.test.mjs.map +0 -1
- package/dist/hono/authorizer.cjs +0 -99
- package/dist/hono/authorizer.cjs.map +0 -1
- package/dist/hono/authorizer.d.cts +0 -25
- package/dist/hono/authorizer.d.ts +0 -25
- package/dist/hono/authorizer.mjs +0 -73
- package/dist/hono/authorizer.mjs.map +0 -1
- package/dist/hono/csrf.cjs +0 -93
- package/dist/hono/csrf.cjs.map +0 -1
- package/dist/hono/csrf.d.cts +0 -65
- package/dist/hono/csrf.d.ts +0 -65
- package/dist/hono/csrf.mjs +0 -68
- package/dist/hono/csrf.mjs.map +0 -1
- package/dist/hono/geolocation.cjs +0 -75
- package/dist/hono/geolocation.cjs.map +0 -1
- package/dist/hono/geolocation.d.cts +0 -17
- package/dist/hono/geolocation.d.ts +0 -17
- package/dist/hono/geolocation.mjs +0 -50
- package/dist/hono/geolocation.mjs.map +0 -1
- package/dist/hono/handler.cjs +0 -68
- package/dist/hono/handler.cjs.map +0 -1
- package/dist/hono/handler.d.cts +0 -13
- package/dist/hono/handler.d.ts +0 -13
- package/dist/hono/handler.mjs +0 -42
- package/dist/hono/handler.mjs.map +0 -1
- package/dist/hono/index.cjs +0 -47
- package/dist/hono/index.cjs.map +0 -1
- package/dist/hono/index.d.cts +0 -12
- package/dist/hono/index.d.ts +0 -12
- package/dist/hono/index.mjs +0 -16
- package/dist/hono/index.mjs.map +0 -1
- package/dist/hono/validator.cjs +0 -64
- package/dist/hono/validator.cjs.map +0 -1
- package/dist/hono/validator.d.cts +0 -28
- package/dist/hono/validator.d.ts +0 -28
- package/dist/hono/validator.mjs +0 -38
- package/dist/hono/validator.mjs.map +0 -1
- package/dist/index-BnPgRQDl.d.cts +0 -129
- package/dist/index-BnPgRQDl.d.ts +0 -129
- package/dist/index.cjs +0 -91
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -18
- package/dist/index.d.ts +0 -18
- package/dist/index.mjs +0 -46
- package/dist/index.mjs.map +0 -1
- package/dist/iso/iso_3601_1.cjs +0 -292
- package/dist/iso/iso_3601_1.cjs.map +0 -1
- package/dist/iso/iso_3601_1.d.cts +0 -9
- package/dist/iso/iso_3601_1.d.ts +0 -9
- package/dist/iso/iso_3601_1.mjs +0 -267
- package/dist/iso/iso_3601_1.mjs.map +0 -1
- package/dist/max-length/index.cjs +0 -94
- package/dist/max-length/index.cjs.map +0 -1
- package/dist/max-length/index.d.cts +0 -1
- package/dist/max-length/index.d.ts +0 -1
- package/dist/max-length/index.mjs +0 -48
- package/dist/max-length/index.mjs.map +0 -1
- package/dist/message.cjs +0 -32
- package/dist/message.cjs.map +0 -1
- package/dist/message.d.cts +0 -3
- package/dist/message.d.ts +0 -3
- package/dist/message.mjs +0 -7
- package/dist/message.mjs.map +0 -1
- package/dist/polyfills/index.cjs +0 -7
- package/dist/polyfills/index.cjs.map +0 -1
- package/dist/polyfills/index.d.cts +0 -2
- package/dist/polyfills/index.d.ts +0 -2
- package/dist/polyfills/index.mjs +0 -5
- package/dist/polyfills/index.mjs.map +0 -1
- package/dist/response.cjs +0 -73
- package/dist/response.cjs.map +0 -1
- package/dist/response.d.cts +0 -65
- package/dist/response.d.ts +0 -65
- package/dist/response.mjs +0 -44
- package/dist/response.mjs.map +0 -1
- package/dist/snowflake.cjs +0 -75
- package/dist/snowflake.cjs.map +0 -1
- package/dist/snowflake.d.cts +0 -29
- package/dist/snowflake.d.ts +0 -29
- package/dist/snowflake.mjs +0 -49
- package/dist/snowflake.mjs.map +0 -1
- package/dist/utils/__tests__/ip.test.cjs +0 -38
- package/dist/utils/__tests__/ip.test.cjs.map +0 -1
- package/dist/utils/__tests__/ip.test.d.cts +0 -2
- package/dist/utils/__tests__/ip.test.d.ts +0 -2
- package/dist/utils/__tests__/ip.test.mjs +0 -36
- package/dist/utils/__tests__/ip.test.mjs.map +0 -1
- package/dist/utils/invariant.cjs +0 -37
- package/dist/utils/invariant.cjs.map +0 -1
- package/dist/utils/invariant.d.cts +0 -3
- package/dist/utils/invariant.d.ts +0 -3
- package/dist/utils/invariant.mjs +0 -12
- package/dist/utils/invariant.mjs.map +0 -1
- package/dist/utils/ip.cjs +0 -53
- package/dist/utils/ip.cjs.map +0 -1
- package/dist/utils/ip.d.cts +0 -3
- package/dist/utils/ip.d.ts +0 -3
- package/dist/utils/ip.mjs +0 -28
- package/dist/utils/ip.mjs.map +0 -1
- package/dist/utils/promise.cjs +0 -47
- package/dist/utils/promise.cjs.map +0 -1
- package/dist/utils/promise.d.cts +0 -3
- package/dist/utils/promise.d.ts +0 -3
- package/dist/utils/promise.mjs +0 -22
- package/dist/utils/promise.mjs.map +0 -1
- package/dist/utils/string.cjs +0 -33
- package/dist/utils/string.cjs.map +0 -1
- package/dist/utils/string.d.cts +0 -6
- package/dist/utils/string.d.ts +0 -6
- package/dist/utils/string.mjs +0 -8
- package/dist/utils/string.mjs.map +0 -1
- package/dist/utils/timing.cjs +0 -74
- package/dist/utils/timing.cjs.map +0 -1
- package/dist/utils/timing.d.cts +0 -13
- package/dist/utils/timing.d.ts +0 -13
- package/dist/utils/timing.mjs +0 -49
- package/dist/utils/timing.mjs.map +0 -1
- package/dist/utils/token-bucket.cjs +0 -73
- package/dist/utils/token-bucket.cjs.map +0 -1
- package/dist/utils/token-bucket.d.cts +0 -20
- package/dist/utils/token-bucket.d.ts +0 -20
- package/dist/utils/token-bucket.mjs +0 -48
- package/dist/utils/token-bucket.mjs.map +0 -1
- package/dist/vaild.cjs +0 -51
- package/dist/vaild.cjs.map +0 -1
- package/dist/vaild.d.cts +0 -13
- package/dist/vaild.d.ts +0 -13
- package/dist/vaild.mjs +0 -26
- package/dist/vaild.mjs.map +0 -1
- package/dist/webhook/index.cjs +0 -77
- package/dist/webhook/index.cjs.map +0 -1
- package/dist/webhook/index.d.cts +0 -10
- package/dist/webhook/index.d.ts +0 -10
- package/dist/webhook/index.mjs +0 -52
- package/dist/webhook/index.mjs.map +0 -1
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
// src/hono/__tests__/csrf.test.ts
|
|
4
|
-
var import_hono = require("hono");
|
|
5
|
-
var import_csrf = require("../csrf.cjs");
|
|
6
|
-
var import_handler = require("../handler.cjs");
|
|
7
|
-
describe("CSRF Protection", () => {
|
|
8
|
-
let app;
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
app = new import_hono.Hono();
|
|
11
|
-
app.onError(import_handler.errorHandler);
|
|
12
|
-
});
|
|
13
|
-
it("should allow GET requests without CSRF token", async () => {
|
|
14
|
-
app.use((0, import_csrf.csrf)());
|
|
15
|
-
app.get("/test", (c) => c.text("OK"));
|
|
16
|
-
const res = await app.request("/test");
|
|
17
|
-
expect(res.status).toBe(200);
|
|
18
|
-
expect(await res.text()).toBe("OK");
|
|
19
|
-
});
|
|
20
|
-
it("should allow HEAD requests without CSRF token", async () => {
|
|
21
|
-
app.use((0, import_csrf.csrf)());
|
|
22
|
-
app.all("/test", (c) => c.text("OK"));
|
|
23
|
-
const res = await app.request("/test", { method: "HEAD" });
|
|
24
|
-
expect(res.status).toBe(200);
|
|
25
|
-
});
|
|
26
|
-
it("should allow OPTIONS requests without CSRF token", async () => {
|
|
27
|
-
app.use((0, import_csrf.csrf)());
|
|
28
|
-
app.options("/test", (c) => c.text("OK"));
|
|
29
|
-
const res = await app.request("/test", { method: "OPTIONS" });
|
|
30
|
-
expect(res.status).toBe(200);
|
|
31
|
-
});
|
|
32
|
-
it("should reject POST requests without CSRF token", async () => {
|
|
33
|
-
app.use((0, import_csrf.csrf)());
|
|
34
|
-
app.post("/test", (c) => c.text("OK"));
|
|
35
|
-
const res = await app.request("/test", { method: "POST" });
|
|
36
|
-
expect(res.status).toBe(403);
|
|
37
|
-
});
|
|
38
|
-
it("should reject POST requests with mismatched tokens", async () => {
|
|
39
|
-
app.use((0, import_csrf.csrf)());
|
|
40
|
-
app.post("/test", (c) => c.text("OK"));
|
|
41
|
-
const res = await app.request("/test", {
|
|
42
|
-
method: "POST",
|
|
43
|
-
headers: { "X-XSRF-TOKEN": "header-token", Cookie: "XSRF-TOKEN=cookie-token" }
|
|
44
|
-
});
|
|
45
|
-
expect(res.status).toBe(403);
|
|
46
|
-
});
|
|
47
|
-
it("should allow POST requests with matching tokens", async () => {
|
|
48
|
-
app.use((0, import_csrf.csrf)());
|
|
49
|
-
app.post("/test", (c) => c.text("OK"));
|
|
50
|
-
const res = await app.request("/test", {
|
|
51
|
-
method: "POST",
|
|
52
|
-
headers: {
|
|
53
|
-
"X-XSRF-TOKEN": "matching-token",
|
|
54
|
-
Cookie: "XSRF-TOKEN=matching-token"
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
expect(res.status).toBe(200);
|
|
58
|
-
expect(await res.text()).toBe("OK");
|
|
59
|
-
});
|
|
60
|
-
it("should use custom cookie and header names", async () => {
|
|
61
|
-
app.use((0, import_csrf.csrf)({ cookieName: "csrf-token", headerName: "X-CSRF-Token" }));
|
|
62
|
-
app.post("/test", (c) => c.text("OK"));
|
|
63
|
-
const res = await app.request("/test", {
|
|
64
|
-
method: "POST",
|
|
65
|
-
headers: {
|
|
66
|
-
"X-CSRF-Token": "test-token",
|
|
67
|
-
Cookie: "csrf-token=test-token"
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
expect(res.status).toBe(200);
|
|
71
|
-
});
|
|
72
|
-
it("should ignore specified paths", async () => {
|
|
73
|
-
app.use((0, import_csrf.csrf)({ ignores: [{ path: "/webhook/*", methods: ["POST"] }] }));
|
|
74
|
-
app.post("/webhook/stripe", (c) => c.text("OK"));
|
|
75
|
-
app.post("/api/data", (c) => c.text("OK"));
|
|
76
|
-
const webhookRes = await app.request("/webhook/stripe", { method: "POST" });
|
|
77
|
-
expect(webhookRes.status).toBe(200);
|
|
78
|
-
const apiRes = await app.request("/api/data", { method: "POST" });
|
|
79
|
-
expect(apiRes.status).toBe(403);
|
|
80
|
-
});
|
|
81
|
-
it("should ignore all methods for a path when methods not specified", async () => {
|
|
82
|
-
app.use((0, import_csrf.csrf)({ ignores: [{ path: "/auth/apple/callback" }] }));
|
|
83
|
-
app.post("/auth/apple/callback", (c) => c.text("OK"));
|
|
84
|
-
app.put("/auth/apple/callback", (c) => c.text("OK"));
|
|
85
|
-
const postRes = await app.request("/auth/apple/callback", { method: "POST" });
|
|
86
|
-
expect(postRes.status).toBe(200);
|
|
87
|
-
const putRes = await app.request("/auth/apple/callback", { method: "PUT" });
|
|
88
|
-
expect(putRes.status).toBe(200);
|
|
89
|
-
});
|
|
90
|
-
it("should handle empty tokens safely", async () => {
|
|
91
|
-
app.use((0, import_csrf.csrf)());
|
|
92
|
-
app.post("/test", (c) => c.text("OK"));
|
|
93
|
-
const res = await app.request("/test", {
|
|
94
|
-
method: "POST",
|
|
95
|
-
headers: { "X-XSRF-TOKEN": "", Cookie: "XSRF-TOKEN=" }
|
|
96
|
-
});
|
|
97
|
-
expect(res.status).toBe(403);
|
|
98
|
-
});
|
|
99
|
-
it("should handle missing cookie", async () => {
|
|
100
|
-
app.use((0, import_csrf.csrf)());
|
|
101
|
-
app.post("/test", (c) => c.text("OK"));
|
|
102
|
-
const res = await app.request("/test", {
|
|
103
|
-
method: "POST",
|
|
104
|
-
headers: { "X-XSRF-TOKEN": "token" }
|
|
105
|
-
});
|
|
106
|
-
expect(res.status).toBe(403);
|
|
107
|
-
});
|
|
108
|
-
it("should handle missing header", async () => {
|
|
109
|
-
app.use((0, import_csrf.csrf)());
|
|
110
|
-
app.post("/test", (c) => c.text("OK"));
|
|
111
|
-
const res = await app.request("/test", {
|
|
112
|
-
method: "POST",
|
|
113
|
-
headers: { Cookie: "XSRF-TOKEN=token" }
|
|
114
|
-
});
|
|
115
|
-
expect(res.status).toBe(403);
|
|
116
|
-
});
|
|
117
|
-
it("should use custom error message", async () => {
|
|
118
|
-
app.use((0, import_csrf.csrf)({ errorMessage: "Custom CSRF error" }));
|
|
119
|
-
app.post("/test", (c) => c.text("OK"));
|
|
120
|
-
const res = await app.request("/test", { method: "POST" });
|
|
121
|
-
expect(res.status).toBe(403);
|
|
122
|
-
const body = await res.json();
|
|
123
|
-
expect(body.error.message).toBe("Custom CSRF error");
|
|
124
|
-
});
|
|
125
|
-
it("should work with custom safe methods", async () => {
|
|
126
|
-
app.use((0, import_csrf.csrf)({ safeMethods: ["GET"] }));
|
|
127
|
-
app.all("/test", (c) => c.text("OK"));
|
|
128
|
-
const res = await app.request("/test", { method: "HEAD" });
|
|
129
|
-
expect(res.status).toBe(403);
|
|
130
|
-
});
|
|
131
|
-
it("should handle complex ignore patterns", async () => {
|
|
132
|
-
app.use(
|
|
133
|
-
(0, import_csrf.csrf)({
|
|
134
|
-
ignores: [
|
|
135
|
-
{ path: "/api/v1/*", methods: ["GET", "POST"] },
|
|
136
|
-
{ path: "/api/v2/*", methods: ["POST"] },
|
|
137
|
-
{ path: "/public/*" }
|
|
138
|
-
// All methods
|
|
139
|
-
]
|
|
140
|
-
})
|
|
141
|
-
);
|
|
142
|
-
app.get("/api/v1/users", (c) => c.text("OK"));
|
|
143
|
-
app.post("/api/v1/users", (c) => c.text("OK"));
|
|
144
|
-
app.put("/api/v1/users", (c) => c.text("OK"));
|
|
145
|
-
app.post("/api/v2/users", (c) => c.text("OK"));
|
|
146
|
-
app.get("/api/v2/users", (c) => c.text("OK"));
|
|
147
|
-
app.post("/public/data", (c) => c.text("OK"));
|
|
148
|
-
let res = await app.request("/api/v1/users", { method: "GET" });
|
|
149
|
-
expect(res.status).toBe(200);
|
|
150
|
-
res = await app.request("/api/v1/users", { method: "POST" });
|
|
151
|
-
expect(res.status).toBe(200);
|
|
152
|
-
res = await app.request("/api/v1/users", { method: "PUT" });
|
|
153
|
-
expect(res.status).toBe(403);
|
|
154
|
-
res = await app.request("/api/v2/users", { method: "POST" });
|
|
155
|
-
expect(res.status).toBe(200);
|
|
156
|
-
res = await app.request("/api/v2/users", { method: "GET" });
|
|
157
|
-
expect(res.status).toBe(200);
|
|
158
|
-
res = await app.request("/public/data", { method: "POST" });
|
|
159
|
-
expect(res.status).toBe(200);
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
//# sourceMappingURL=csrf.test.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hono/__tests__/csrf.test.ts"],"sourcesContent":["import { Hono } from 'hono';\nimport { csrf } from '../csrf';\nimport { errorHandler, type Env } from '../handler';\n\ndescribe('CSRF Protection', () => {\n let app: Hono<Env>;\n\n beforeEach(() => {\n app = new Hono();\n app.onError(errorHandler);\n });\n\n it('should allow GET requests without CSRF token', async () => {\n app.use(csrf());\n app.get('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test');\n expect(res.status).toBe(200);\n expect(await res.text()).toBe('OK');\n });\n\n it('should allow HEAD requests without CSRF token', async () => {\n app.use(csrf());\n app.all('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', { method: 'HEAD' });\n expect(res.status).toBe(200);\n });\n\n it('should allow OPTIONS requests without CSRF token', async () => {\n app.use(csrf());\n app.options('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', { method: 'OPTIONS' });\n expect(res.status).toBe(200);\n });\n\n it('should reject POST requests without CSRF token', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', { method: 'POST' });\n expect(res.status).toBe(403);\n });\n\n it('should reject POST requests with mismatched tokens', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: { 'X-XSRF-TOKEN': 'header-token', Cookie: 'XSRF-TOKEN=cookie-token' },\n });\n expect(res.status).toBe(403);\n });\n\n it('should allow POST requests with matching tokens', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: {\n 'X-XSRF-TOKEN': 'matching-token',\n Cookie: 'XSRF-TOKEN=matching-token',\n },\n });\n expect(res.status).toBe(200);\n expect(await res.text()).toBe('OK');\n });\n\n it('should use custom cookie and header names', async () => {\n app.use(csrf({ cookieName: 'csrf-token', headerName: 'X-CSRF-Token' }));\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: {\n 'X-CSRF-Token': 'test-token',\n Cookie: 'csrf-token=test-token',\n },\n });\n expect(res.status).toBe(200);\n });\n\n it('should ignore specified paths', async () => {\n app.use(csrf({ ignores: [{ path: '/webhook/*', methods: ['POST'] }] }));\n app.post('/webhook/stripe', (c) => c.text('OK'));\n app.post('/api/data', (c) => c.text('OK'));\n\n // Ignored path should work without CSRF token\n const webhookRes = await app.request('/webhook/stripe', { method: 'POST' });\n expect(webhookRes.status).toBe(200);\n\n // Non-ignored path should require CSRF token\n const apiRes = await app.request('/api/data', { method: 'POST' });\n expect(apiRes.status).toBe(403);\n });\n\n it('should ignore all methods for a path when methods not specified', async () => {\n app.use(csrf({ ignores: [{ path: '/auth/apple/callback' }] }));\n app.post('/auth/apple/callback', (c) => c.text('OK'));\n app.put('/auth/apple/callback', (c) => c.text('OK'));\n\n const postRes = await app.request('/auth/apple/callback', { method: 'POST' });\n expect(postRes.status).toBe(200);\n\n const putRes = await app.request('/auth/apple/callback', { method: 'PUT' });\n expect(putRes.status).toBe(200);\n });\n\n it('should handle empty tokens safely', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: { 'X-XSRF-TOKEN': '', Cookie: 'XSRF-TOKEN=' },\n });\n expect(res.status).toBe(403);\n });\n\n it('should handle missing cookie', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: { 'X-XSRF-TOKEN': 'token' },\n });\n expect(res.status).toBe(403);\n });\n\n it('should handle missing header', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: { Cookie: 'XSRF-TOKEN=token' },\n });\n expect(res.status).toBe(403);\n });\n\n it('should use custom error message', async () => {\n app.use(csrf({ errorMessage: 'Custom CSRF error' }));\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', { method: 'POST' });\n expect(res.status).toBe(403);\n const body = await res.json();\n expect(body.error.message).toBe('Custom CSRF error');\n });\n\n it('should work with custom safe methods', async () => {\n app.use(csrf({ safeMethods: ['GET'] }));\n app.all('/test', (c) => c.text('OK'));\n\n // HEAD is no longer safe, should require CSRF token\n const res = await app.request('/test', { method: 'HEAD' });\n expect(res.status).toBe(403);\n });\n\n it('should handle complex ignore patterns', async () => {\n app.use(\n csrf({\n ignores: [\n { path: '/api/v1/*', methods: ['GET', 'POST'] },\n { path: '/api/v2/*', methods: ['POST'] },\n { path: '/public/*' }, // All methods\n ],\n })\n );\n\n app.get('/api/v1/users', (c) => c.text('OK'));\n app.post('/api/v1/users', (c) => c.text('OK'));\n app.put('/api/v1/users', (c) => c.text('OK'));\n app.post('/api/v2/users', (c) => c.text('OK'));\n app.get('/api/v2/users', (c) => c.text('OK'));\n app.post('/public/data', (c) => c.text('OK'));\n\n // Ignored GET and POST for /api/v1/*\n let res = await app.request('/api/v1/users', { method: 'GET' });\n expect(res.status).toBe(200);\n\n res = await app.request('/api/v1/users', { method: 'POST' });\n expect(res.status).toBe(200);\n\n // PUT not ignored for /api/v1/*\n res = await app.request('/api/v1/users', { method: 'PUT' });\n expect(res.status).toBe(403);\n\n // Only POST ignored for /api/v2/*\n res = await app.request('/api/v2/users', { method: 'POST' });\n expect(res.status).toBe(200);\n\n // GET not ignored for /api/v2/* (but GET is safe by default)\n res = await app.request('/api/v2/users', { method: 'GET' });\n expect(res.status).toBe(200);\n\n // All methods ignored for /public/*\n res = await app.request('/public/data', { method: 'POST' });\n expect(res.status).toBe(200);\n });\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
// src/hono/__tests__/csrf.test.ts
|
|
2
|
-
import { Hono } from "hono";
|
|
3
|
-
import { csrf } from "../csrf.mjs";
|
|
4
|
-
import { errorHandler } from "../handler.mjs";
|
|
5
|
-
describe("CSRF Protection", () => {
|
|
6
|
-
let app;
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
app = new Hono();
|
|
9
|
-
app.onError(errorHandler);
|
|
10
|
-
});
|
|
11
|
-
it("should allow GET requests without CSRF token", async () => {
|
|
12
|
-
app.use(csrf());
|
|
13
|
-
app.get("/test", (c) => c.text("OK"));
|
|
14
|
-
const res = await app.request("/test");
|
|
15
|
-
expect(res.status).toBe(200);
|
|
16
|
-
expect(await res.text()).toBe("OK");
|
|
17
|
-
});
|
|
18
|
-
it("should allow HEAD requests without CSRF token", async () => {
|
|
19
|
-
app.use(csrf());
|
|
20
|
-
app.all("/test", (c) => c.text("OK"));
|
|
21
|
-
const res = await app.request("/test", { method: "HEAD" });
|
|
22
|
-
expect(res.status).toBe(200);
|
|
23
|
-
});
|
|
24
|
-
it("should allow OPTIONS requests without CSRF token", async () => {
|
|
25
|
-
app.use(csrf());
|
|
26
|
-
app.options("/test", (c) => c.text("OK"));
|
|
27
|
-
const res = await app.request("/test", { method: "OPTIONS" });
|
|
28
|
-
expect(res.status).toBe(200);
|
|
29
|
-
});
|
|
30
|
-
it("should reject POST requests without CSRF token", async () => {
|
|
31
|
-
app.use(csrf());
|
|
32
|
-
app.post("/test", (c) => c.text("OK"));
|
|
33
|
-
const res = await app.request("/test", { method: "POST" });
|
|
34
|
-
expect(res.status).toBe(403);
|
|
35
|
-
});
|
|
36
|
-
it("should reject POST requests with mismatched tokens", async () => {
|
|
37
|
-
app.use(csrf());
|
|
38
|
-
app.post("/test", (c) => c.text("OK"));
|
|
39
|
-
const res = await app.request("/test", {
|
|
40
|
-
method: "POST",
|
|
41
|
-
headers: { "X-XSRF-TOKEN": "header-token", Cookie: "XSRF-TOKEN=cookie-token" }
|
|
42
|
-
});
|
|
43
|
-
expect(res.status).toBe(403);
|
|
44
|
-
});
|
|
45
|
-
it("should allow POST requests with matching tokens", async () => {
|
|
46
|
-
app.use(csrf());
|
|
47
|
-
app.post("/test", (c) => c.text("OK"));
|
|
48
|
-
const res = await app.request("/test", {
|
|
49
|
-
method: "POST",
|
|
50
|
-
headers: {
|
|
51
|
-
"X-XSRF-TOKEN": "matching-token",
|
|
52
|
-
Cookie: "XSRF-TOKEN=matching-token"
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
expect(res.status).toBe(200);
|
|
56
|
-
expect(await res.text()).toBe("OK");
|
|
57
|
-
});
|
|
58
|
-
it("should use custom cookie and header names", async () => {
|
|
59
|
-
app.use(csrf({ cookieName: "csrf-token", headerName: "X-CSRF-Token" }));
|
|
60
|
-
app.post("/test", (c) => c.text("OK"));
|
|
61
|
-
const res = await app.request("/test", {
|
|
62
|
-
method: "POST",
|
|
63
|
-
headers: {
|
|
64
|
-
"X-CSRF-Token": "test-token",
|
|
65
|
-
Cookie: "csrf-token=test-token"
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
expect(res.status).toBe(200);
|
|
69
|
-
});
|
|
70
|
-
it("should ignore specified paths", async () => {
|
|
71
|
-
app.use(csrf({ ignores: [{ path: "/webhook/*", methods: ["POST"] }] }));
|
|
72
|
-
app.post("/webhook/stripe", (c) => c.text("OK"));
|
|
73
|
-
app.post("/api/data", (c) => c.text("OK"));
|
|
74
|
-
const webhookRes = await app.request("/webhook/stripe", { method: "POST" });
|
|
75
|
-
expect(webhookRes.status).toBe(200);
|
|
76
|
-
const apiRes = await app.request("/api/data", { method: "POST" });
|
|
77
|
-
expect(apiRes.status).toBe(403);
|
|
78
|
-
});
|
|
79
|
-
it("should ignore all methods for a path when methods not specified", async () => {
|
|
80
|
-
app.use(csrf({ ignores: [{ path: "/auth/apple/callback" }] }));
|
|
81
|
-
app.post("/auth/apple/callback", (c) => c.text("OK"));
|
|
82
|
-
app.put("/auth/apple/callback", (c) => c.text("OK"));
|
|
83
|
-
const postRes = await app.request("/auth/apple/callback", { method: "POST" });
|
|
84
|
-
expect(postRes.status).toBe(200);
|
|
85
|
-
const putRes = await app.request("/auth/apple/callback", { method: "PUT" });
|
|
86
|
-
expect(putRes.status).toBe(200);
|
|
87
|
-
});
|
|
88
|
-
it("should handle empty tokens safely", async () => {
|
|
89
|
-
app.use(csrf());
|
|
90
|
-
app.post("/test", (c) => c.text("OK"));
|
|
91
|
-
const res = await app.request("/test", {
|
|
92
|
-
method: "POST",
|
|
93
|
-
headers: { "X-XSRF-TOKEN": "", Cookie: "XSRF-TOKEN=" }
|
|
94
|
-
});
|
|
95
|
-
expect(res.status).toBe(403);
|
|
96
|
-
});
|
|
97
|
-
it("should handle missing cookie", async () => {
|
|
98
|
-
app.use(csrf());
|
|
99
|
-
app.post("/test", (c) => c.text("OK"));
|
|
100
|
-
const res = await app.request("/test", {
|
|
101
|
-
method: "POST",
|
|
102
|
-
headers: { "X-XSRF-TOKEN": "token" }
|
|
103
|
-
});
|
|
104
|
-
expect(res.status).toBe(403);
|
|
105
|
-
});
|
|
106
|
-
it("should handle missing header", async () => {
|
|
107
|
-
app.use(csrf());
|
|
108
|
-
app.post("/test", (c) => c.text("OK"));
|
|
109
|
-
const res = await app.request("/test", {
|
|
110
|
-
method: "POST",
|
|
111
|
-
headers: { Cookie: "XSRF-TOKEN=token" }
|
|
112
|
-
});
|
|
113
|
-
expect(res.status).toBe(403);
|
|
114
|
-
});
|
|
115
|
-
it("should use custom error message", async () => {
|
|
116
|
-
app.use(csrf({ errorMessage: "Custom CSRF error" }));
|
|
117
|
-
app.post("/test", (c) => c.text("OK"));
|
|
118
|
-
const res = await app.request("/test", { method: "POST" });
|
|
119
|
-
expect(res.status).toBe(403);
|
|
120
|
-
const body = await res.json();
|
|
121
|
-
expect(body.error.message).toBe("Custom CSRF error");
|
|
122
|
-
});
|
|
123
|
-
it("should work with custom safe methods", async () => {
|
|
124
|
-
app.use(csrf({ safeMethods: ["GET"] }));
|
|
125
|
-
app.all("/test", (c) => c.text("OK"));
|
|
126
|
-
const res = await app.request("/test", { method: "HEAD" });
|
|
127
|
-
expect(res.status).toBe(403);
|
|
128
|
-
});
|
|
129
|
-
it("should handle complex ignore patterns", async () => {
|
|
130
|
-
app.use(
|
|
131
|
-
csrf({
|
|
132
|
-
ignores: [
|
|
133
|
-
{ path: "/api/v1/*", methods: ["GET", "POST"] },
|
|
134
|
-
{ path: "/api/v2/*", methods: ["POST"] },
|
|
135
|
-
{ path: "/public/*" }
|
|
136
|
-
// All methods
|
|
137
|
-
]
|
|
138
|
-
})
|
|
139
|
-
);
|
|
140
|
-
app.get("/api/v1/users", (c) => c.text("OK"));
|
|
141
|
-
app.post("/api/v1/users", (c) => c.text("OK"));
|
|
142
|
-
app.put("/api/v1/users", (c) => c.text("OK"));
|
|
143
|
-
app.post("/api/v2/users", (c) => c.text("OK"));
|
|
144
|
-
app.get("/api/v2/users", (c) => c.text("OK"));
|
|
145
|
-
app.post("/public/data", (c) => c.text("OK"));
|
|
146
|
-
let res = await app.request("/api/v1/users", { method: "GET" });
|
|
147
|
-
expect(res.status).toBe(200);
|
|
148
|
-
res = await app.request("/api/v1/users", { method: "POST" });
|
|
149
|
-
expect(res.status).toBe(200);
|
|
150
|
-
res = await app.request("/api/v1/users", { method: "PUT" });
|
|
151
|
-
expect(res.status).toBe(403);
|
|
152
|
-
res = await app.request("/api/v2/users", { method: "POST" });
|
|
153
|
-
expect(res.status).toBe(200);
|
|
154
|
-
res = await app.request("/api/v2/users", { method: "GET" });
|
|
155
|
-
expect(res.status).toBe(200);
|
|
156
|
-
res = await app.request("/public/data", { method: "POST" });
|
|
157
|
-
expect(res.status).toBe(200);
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
//# sourceMappingURL=csrf.test.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hono/__tests__/csrf.test.ts"],"sourcesContent":["import { Hono } from 'hono';\nimport { csrf } from '../csrf';\nimport { errorHandler, type Env } from '../handler';\n\ndescribe('CSRF Protection', () => {\n let app: Hono<Env>;\n\n beforeEach(() => {\n app = new Hono();\n app.onError(errorHandler);\n });\n\n it('should allow GET requests without CSRF token', async () => {\n app.use(csrf());\n app.get('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test');\n expect(res.status).toBe(200);\n expect(await res.text()).toBe('OK');\n });\n\n it('should allow HEAD requests without CSRF token', async () => {\n app.use(csrf());\n app.all('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', { method: 'HEAD' });\n expect(res.status).toBe(200);\n });\n\n it('should allow OPTIONS requests without CSRF token', async () => {\n app.use(csrf());\n app.options('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', { method: 'OPTIONS' });\n expect(res.status).toBe(200);\n });\n\n it('should reject POST requests without CSRF token', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', { method: 'POST' });\n expect(res.status).toBe(403);\n });\n\n it('should reject POST requests with mismatched tokens', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: { 'X-XSRF-TOKEN': 'header-token', Cookie: 'XSRF-TOKEN=cookie-token' },\n });\n expect(res.status).toBe(403);\n });\n\n it('should allow POST requests with matching tokens', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: {\n 'X-XSRF-TOKEN': 'matching-token',\n Cookie: 'XSRF-TOKEN=matching-token',\n },\n });\n expect(res.status).toBe(200);\n expect(await res.text()).toBe('OK');\n });\n\n it('should use custom cookie and header names', async () => {\n app.use(csrf({ cookieName: 'csrf-token', headerName: 'X-CSRF-Token' }));\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: {\n 'X-CSRF-Token': 'test-token',\n Cookie: 'csrf-token=test-token',\n },\n });\n expect(res.status).toBe(200);\n });\n\n it('should ignore specified paths', async () => {\n app.use(csrf({ ignores: [{ path: '/webhook/*', methods: ['POST'] }] }));\n app.post('/webhook/stripe', (c) => c.text('OK'));\n app.post('/api/data', (c) => c.text('OK'));\n\n // Ignored path should work without CSRF token\n const webhookRes = await app.request('/webhook/stripe', { method: 'POST' });\n expect(webhookRes.status).toBe(200);\n\n // Non-ignored path should require CSRF token\n const apiRes = await app.request('/api/data', { method: 'POST' });\n expect(apiRes.status).toBe(403);\n });\n\n it('should ignore all methods for a path when methods not specified', async () => {\n app.use(csrf({ ignores: [{ path: '/auth/apple/callback' }] }));\n app.post('/auth/apple/callback', (c) => c.text('OK'));\n app.put('/auth/apple/callback', (c) => c.text('OK'));\n\n const postRes = await app.request('/auth/apple/callback', { method: 'POST' });\n expect(postRes.status).toBe(200);\n\n const putRes = await app.request('/auth/apple/callback', { method: 'PUT' });\n expect(putRes.status).toBe(200);\n });\n\n it('should handle empty tokens safely', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: { 'X-XSRF-TOKEN': '', Cookie: 'XSRF-TOKEN=' },\n });\n expect(res.status).toBe(403);\n });\n\n it('should handle missing cookie', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: { 'X-XSRF-TOKEN': 'token' },\n });\n expect(res.status).toBe(403);\n });\n\n it('should handle missing header', async () => {\n app.use(csrf());\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', {\n method: 'POST',\n headers: { Cookie: 'XSRF-TOKEN=token' },\n });\n expect(res.status).toBe(403);\n });\n\n it('should use custom error message', async () => {\n app.use(csrf({ errorMessage: 'Custom CSRF error' }));\n app.post('/test', (c) => c.text('OK'));\n\n const res = await app.request('/test', { method: 'POST' });\n expect(res.status).toBe(403);\n const body = await res.json();\n expect(body.error.message).toBe('Custom CSRF error');\n });\n\n it('should work with custom safe methods', async () => {\n app.use(csrf({ safeMethods: ['GET'] }));\n app.all('/test', (c) => c.text('OK'));\n\n // HEAD is no longer safe, should require CSRF token\n const res = await app.request('/test', { method: 'HEAD' });\n expect(res.status).toBe(403);\n });\n\n it('should handle complex ignore patterns', async () => {\n app.use(\n csrf({\n ignores: [\n { path: '/api/v1/*', methods: ['GET', 'POST'] },\n { path: '/api/v2/*', methods: ['POST'] },\n { path: '/public/*' }, // All methods\n ],\n })\n );\n\n app.get('/api/v1/users', (c) => c.text('OK'));\n app.post('/api/v1/users', (c) => c.text('OK'));\n app.put('/api/v1/users', (c) => c.text('OK'));\n app.post('/api/v2/users', (c) => c.text('OK'));\n app.get('/api/v2/users', (c) => c.text('OK'));\n app.post('/public/data', (c) => c.text('OK'));\n\n // Ignored GET and POST for /api/v1/*\n let res = await app.request('/api/v1/users', { method: 'GET' });\n expect(res.status).toBe(200);\n\n res = await app.request('/api/v1/users', { method: 'POST' });\n expect(res.status).toBe(200);\n\n // PUT not ignored for /api/v1/*\n res = await app.request('/api/v1/users', { method: 'PUT' });\n expect(res.status).toBe(403);\n\n // Only POST ignored for /api/v2/*\n res = await app.request('/api/v2/users', { method: 'POST' });\n expect(res.status).toBe(200);\n\n // GET not ignored for /api/v2/* (but GET is safe by default)\n res = await app.request('/api/v2/users', { method: 'GET' });\n expect(res.status).toBe(200);\n\n // All methods ignored for /public/*\n res = await app.request('/public/data', { method: 'POST' });\n expect(res.status).toBe(200);\n });\n});\n"],"mappings":"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","names":[]}
|
package/dist/hono/authorizer.cjs
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
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
|
-
|
|
20
|
-
// src/hono/authorizer.ts
|
|
21
|
-
var authorizer_exports = {};
|
|
22
|
-
__export(authorizer_exports, {
|
|
23
|
-
Authorizer: () => Authorizer,
|
|
24
|
-
authorizer: () => authorizer
|
|
25
|
-
});
|
|
26
|
-
module.exports = __toCommonJS(authorizer_exports);
|
|
27
|
-
var import_router = require("hono/router");
|
|
28
|
-
var import_reg_exp_router = require("hono/router/reg-exp-router");
|
|
29
|
-
var import_smart_router = require("hono/router/smart-router");
|
|
30
|
-
var import_trie_router = require("hono/router/trie-router");
|
|
31
|
-
var import_status = require("../error/status.cjs");
|
|
32
|
-
var Authorizer = class _Authorizer {
|
|
33
|
-
router = new import_smart_router.SmartRouter({
|
|
34
|
-
routers: [new import_reg_exp_router.RegExpRouter(), new import_trie_router.TrieRouter()]
|
|
35
|
-
});
|
|
36
|
-
auth;
|
|
37
|
-
constructor(auth) {
|
|
38
|
-
this.auth = auth;
|
|
39
|
-
}
|
|
40
|
-
static create = (auth) => new _Authorizer(auth);
|
|
41
|
-
match(path, methods) {
|
|
42
|
-
if (methods) {
|
|
43
|
-
for (const method of methods) {
|
|
44
|
-
this.router.add(method, path, null);
|
|
45
|
-
}
|
|
46
|
-
} else {
|
|
47
|
-
this.router.add(import_router.METHOD_NAME_ALL, path, null);
|
|
48
|
-
}
|
|
49
|
-
return this;
|
|
50
|
-
}
|
|
51
|
-
build = () => {
|
|
52
|
-
return async (c, next) => {
|
|
53
|
-
if (c.req.method === "OPTIONS") {
|
|
54
|
-
await next();
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
const [matched] = this.router.match(c.req.method, c.req.path);
|
|
58
|
-
if (matched.length === 0) {
|
|
59
|
-
await next();
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
const authenticated = await this.auth.isAuthenticated(c.req.raw);
|
|
63
|
-
if (!authenticated) throw import_status.Status.unauthorized().error();
|
|
64
|
-
await next();
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
};
|
|
68
|
-
function authorizer({
|
|
69
|
-
auth,
|
|
70
|
-
errorMessage = "Unauthorized, please login to continue.",
|
|
71
|
-
rules = []
|
|
72
|
-
}) {
|
|
73
|
-
const router = new import_smart_router.SmartRouter({ routers: [new import_reg_exp_router.RegExpRouter(), new import_trie_router.TrieRouter()] });
|
|
74
|
-
for (const { path, methods = [import_router.METHOD_NAME_ALL] } of rules) {
|
|
75
|
-
for (const method of methods) {
|
|
76
|
-
router.add(method, path, null);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return async (c, next) => {
|
|
80
|
-
if (c.req.method === "OPTIONS") {
|
|
81
|
-
await next();
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const [matched] = router.match(c.req.method, c.req.path);
|
|
85
|
-
if (matched.length === 0) {
|
|
86
|
-
await next();
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
const authenticated = await auth.isAuthenticated(c.req.raw);
|
|
90
|
-
if (!authenticated) throw import_status.Status.unauthorized(errorMessage).error();
|
|
91
|
-
await next();
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
95
|
-
0 && (module.exports = {
|
|
96
|
-
Authorizer,
|
|
97
|
-
authorizer
|
|
98
|
-
});
|
|
99
|
-
//# sourceMappingURL=authorizer.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hono/authorizer.ts"],"sourcesContent":["import { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\nimport type { MiddlewareHandler } from 'hono';\n\ntype Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\ntype Auth = { isAuthenticated: (request: Request) => Promise<boolean> };\n\nexport class Authorizer {\n private readonly router = new SmartRouter<null>({\n routers: [new RegExpRouter(), new TrieRouter()],\n });\n\n private readonly auth: Auth;\n\n private constructor(auth: Auth) {\n this.auth = auth;\n }\n\n static create = (auth: Auth) => new Authorizer(auth);\n\n match(path: string, methods?: [Methods, ...Methods[]]) {\n if (methods) {\n for (const method of methods) {\n this.router.add(method, path, null);\n }\n } else {\n this.router.add(METHOD_NAME_ALL, path, null);\n }\n return this;\n }\n\n build = (): MiddlewareHandler => {\n return async (c, next) => {\n if (c.req.method === 'OPTIONS') {\n await next();\n return;\n }\n\n const [matched] = this.router.match(c.req.method, c.req.path);\n if (matched.length === 0) {\n await next();\n return;\n }\n\n const authenticated = await this.auth.isAuthenticated(c.req.raw);\n if (!authenticated) throw Status.unauthorized().error();\n await next();\n };\n };\n}\n\nexport interface AuthorizerConfig {\n auth: Auth;\n errorMessage?: string;\n rules?: { path: string; methods?: [Methods, ...Methods[]] }[];\n}\n\nexport function authorizer({\n auth,\n errorMessage = 'Unauthorized, please login to continue.',\n rules = [],\n}: AuthorizerConfig): MiddlewareHandler {\n const router = new SmartRouter<null>({ routers: [new RegExpRouter(), new TrieRouter()] });\n\n for (const { path, methods = [METHOD_NAME_ALL] } of rules) {\n for (const method of methods) {\n router.add(method, path, null);\n }\n }\n\n return async (c, next) => {\n if (c.req.method === 'OPTIONS') {\n await next();\n return;\n }\n\n const [matched] = router.match(c.req.method, c.req.path);\n if (matched.length === 0) {\n await next();\n return;\n }\n\n const authenticated = await auth.isAuthenticated(c.req.raw);\n if (!authenticated) throw Status.unauthorized(errorMessage).error();\n await next();\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAgC;AAChC,4BAA6B;AAC7B,0BAA4B;AAC5B,yBAA2B;AAC3B,oBAAuB;AAOhB,IAAM,aAAN,MAAM,YAAW;AAAA,EACL,SAAS,IAAI,gCAAkB;AAAA,IAC9C,SAAS,CAAC,IAAI,mCAAa,GAAG,IAAI,8BAAW,CAAC;AAAA,EAChD,CAAC;AAAA,EAEgB;AAAA,EAET,YAAY,MAAY;AAC9B,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,OAAO,SAAS,CAAC,SAAe,IAAI,YAAW,IAAI;AAAA,EAEnD,MAAM,MAAc,SAAmC;AACrD,QAAI,SAAS;AACX,iBAAW,UAAU,SAAS;AAC5B,aAAK,OAAO,IAAI,QAAQ,MAAM,IAAI;AAAA,MACpC;AAAA,IACF,OAAO;AACL,WAAK,OAAO,IAAI,+BAAiB,MAAM,IAAI;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,MAAyB;AAC/B,WAAO,OAAO,GAAG,SAAS;AACxB,UAAI,EAAE,IAAI,WAAW,WAAW;AAC9B,cAAM,KAAK;AACX;AAAA,MACF;AAEA,YAAM,CAAC,OAAO,IAAI,KAAK,OAAO,MAAM,EAAE,IAAI,QAAQ,EAAE,IAAI,IAAI;AAC5D,UAAI,QAAQ,WAAW,GAAG;AACxB,cAAM,KAAK;AACX;AAAA,MACF;AAEA,YAAM,gBAAgB,MAAM,KAAK,KAAK,gBAAgB,EAAE,IAAI,GAAG;AAC/D,UAAI,CAAC,cAAe,OAAM,qBAAO,aAAa,EAAE,MAAM;AACtD,YAAM,KAAK;AAAA,IACb;AAAA,EACF;AACF;AAQO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,eAAe;AAAA,EACf,QAAQ,CAAC;AACX,GAAwC;AACtC,QAAM,SAAS,IAAI,gCAAkB,EAAE,SAAS,CAAC,IAAI,mCAAa,GAAG,IAAI,8BAAW,CAAC,EAAE,CAAC;AAExF,aAAW,EAAE,MAAM,UAAU,CAAC,6BAAe,EAAE,KAAK,OAAO;AACzD,eAAW,UAAU,SAAS;AAC5B,aAAO,IAAI,QAAQ,MAAM,IAAI;AAAA,IAC/B;AAAA,EACF;AAEA,SAAO,OAAO,GAAG,SAAS;AACxB,QAAI,EAAE,IAAI,WAAW,WAAW;AAC9B,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,CAAC,OAAO,IAAI,OAAO,MAAM,EAAE,IAAI,QAAQ,EAAE,IAAI,IAAI;AACvD,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,gBAAgB,MAAM,KAAK,gBAAgB,EAAE,IAAI,GAAG;AAC1D,QAAI,CAAC,cAAe,OAAM,qBAAO,aAAa,YAAY,EAAE,MAAM;AAClE,UAAM,KAAK;AAAA,EACb;AACF;","names":[]}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { MiddlewareHandler } from 'hono';
|
|
2
|
-
|
|
3
|
-
type Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
4
|
-
type Auth = {
|
|
5
|
-
isAuthenticated: (request: Request) => Promise<boolean>;
|
|
6
|
-
};
|
|
7
|
-
declare class Authorizer {
|
|
8
|
-
private readonly router;
|
|
9
|
-
private readonly auth;
|
|
10
|
-
private constructor();
|
|
11
|
-
static create: (auth: Auth) => Authorizer;
|
|
12
|
-
match(path: string, methods?: [Methods, ...Methods[]]): this;
|
|
13
|
-
build: () => MiddlewareHandler;
|
|
14
|
-
}
|
|
15
|
-
interface AuthorizerConfig {
|
|
16
|
-
auth: Auth;
|
|
17
|
-
errorMessage?: string;
|
|
18
|
-
rules?: {
|
|
19
|
-
path: string;
|
|
20
|
-
methods?: [Methods, ...Methods[]];
|
|
21
|
-
}[];
|
|
22
|
-
}
|
|
23
|
-
declare function authorizer({ auth, errorMessage, rules, }: AuthorizerConfig): MiddlewareHandler;
|
|
24
|
-
|
|
25
|
-
export { Authorizer, type AuthorizerConfig, authorizer };
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { MiddlewareHandler } from 'hono';
|
|
2
|
-
|
|
3
|
-
type Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
4
|
-
type Auth = {
|
|
5
|
-
isAuthenticated: (request: Request) => Promise<boolean>;
|
|
6
|
-
};
|
|
7
|
-
declare class Authorizer {
|
|
8
|
-
private readonly router;
|
|
9
|
-
private readonly auth;
|
|
10
|
-
private constructor();
|
|
11
|
-
static create: (auth: Auth) => Authorizer;
|
|
12
|
-
match(path: string, methods?: [Methods, ...Methods[]]): this;
|
|
13
|
-
build: () => MiddlewareHandler;
|
|
14
|
-
}
|
|
15
|
-
interface AuthorizerConfig {
|
|
16
|
-
auth: Auth;
|
|
17
|
-
errorMessage?: string;
|
|
18
|
-
rules?: {
|
|
19
|
-
path: string;
|
|
20
|
-
methods?: [Methods, ...Methods[]];
|
|
21
|
-
}[];
|
|
22
|
-
}
|
|
23
|
-
declare function authorizer({ auth, errorMessage, rules, }: AuthorizerConfig): MiddlewareHandler;
|
|
24
|
-
|
|
25
|
-
export { Authorizer, type AuthorizerConfig, authorizer };
|
package/dist/hono/authorizer.mjs
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
// src/hono/authorizer.ts
|
|
2
|
-
import { METHOD_NAME_ALL } from "hono/router";
|
|
3
|
-
import { RegExpRouter } from "hono/router/reg-exp-router";
|
|
4
|
-
import { SmartRouter } from "hono/router/smart-router";
|
|
5
|
-
import { TrieRouter } from "hono/router/trie-router";
|
|
6
|
-
import { Status } from "../error/status.mjs";
|
|
7
|
-
var Authorizer = class _Authorizer {
|
|
8
|
-
router = new SmartRouter({
|
|
9
|
-
routers: [new RegExpRouter(), new TrieRouter()]
|
|
10
|
-
});
|
|
11
|
-
auth;
|
|
12
|
-
constructor(auth) {
|
|
13
|
-
this.auth = auth;
|
|
14
|
-
}
|
|
15
|
-
static create = (auth) => new _Authorizer(auth);
|
|
16
|
-
match(path, methods) {
|
|
17
|
-
if (methods) {
|
|
18
|
-
for (const method of methods) {
|
|
19
|
-
this.router.add(method, path, null);
|
|
20
|
-
}
|
|
21
|
-
} else {
|
|
22
|
-
this.router.add(METHOD_NAME_ALL, path, null);
|
|
23
|
-
}
|
|
24
|
-
return this;
|
|
25
|
-
}
|
|
26
|
-
build = () => {
|
|
27
|
-
return async (c, next) => {
|
|
28
|
-
if (c.req.method === "OPTIONS") {
|
|
29
|
-
await next();
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const [matched] = this.router.match(c.req.method, c.req.path);
|
|
33
|
-
if (matched.length === 0) {
|
|
34
|
-
await next();
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
const authenticated = await this.auth.isAuthenticated(c.req.raw);
|
|
38
|
-
if (!authenticated) throw Status.unauthorized().error();
|
|
39
|
-
await next();
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
function authorizer({
|
|
44
|
-
auth,
|
|
45
|
-
errorMessage = "Unauthorized, please login to continue.",
|
|
46
|
-
rules = []
|
|
47
|
-
}) {
|
|
48
|
-
const router = new SmartRouter({ routers: [new RegExpRouter(), new TrieRouter()] });
|
|
49
|
-
for (const { path, methods = [METHOD_NAME_ALL] } of rules) {
|
|
50
|
-
for (const method of methods) {
|
|
51
|
-
router.add(method, path, null);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return async (c, next) => {
|
|
55
|
-
if (c.req.method === "OPTIONS") {
|
|
56
|
-
await next();
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
const [matched] = router.match(c.req.method, c.req.path);
|
|
60
|
-
if (matched.length === 0) {
|
|
61
|
-
await next();
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const authenticated = await auth.isAuthenticated(c.req.raw);
|
|
65
|
-
if (!authenticated) throw Status.unauthorized(errorMessage).error();
|
|
66
|
-
await next();
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
export {
|
|
70
|
-
Authorizer,
|
|
71
|
-
authorizer
|
|
72
|
-
};
|
|
73
|
-
//# sourceMappingURL=authorizer.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hono/authorizer.ts"],"sourcesContent":["import { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\nimport type { MiddlewareHandler } from 'hono';\n\ntype Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\ntype Auth = { isAuthenticated: (request: Request) => Promise<boolean> };\n\nexport class Authorizer {\n private readonly router = new SmartRouter<null>({\n routers: [new RegExpRouter(), new TrieRouter()],\n });\n\n private readonly auth: Auth;\n\n private constructor(auth: Auth) {\n this.auth = auth;\n }\n\n static create = (auth: Auth) => new Authorizer(auth);\n\n match(path: string, methods?: [Methods, ...Methods[]]) {\n if (methods) {\n for (const method of methods) {\n this.router.add(method, path, null);\n }\n } else {\n this.router.add(METHOD_NAME_ALL, path, null);\n }\n return this;\n }\n\n build = (): MiddlewareHandler => {\n return async (c, next) => {\n if (c.req.method === 'OPTIONS') {\n await next();\n return;\n }\n\n const [matched] = this.router.match(c.req.method, c.req.path);\n if (matched.length === 0) {\n await next();\n return;\n }\n\n const authenticated = await this.auth.isAuthenticated(c.req.raw);\n if (!authenticated) throw Status.unauthorized().error();\n await next();\n };\n };\n}\n\nexport interface AuthorizerConfig {\n auth: Auth;\n errorMessage?: string;\n rules?: { path: string; methods?: [Methods, ...Methods[]] }[];\n}\n\nexport function authorizer({\n auth,\n errorMessage = 'Unauthorized, please login to continue.',\n rules = [],\n}: AuthorizerConfig): MiddlewareHandler {\n const router = new SmartRouter<null>({ routers: [new RegExpRouter(), new TrieRouter()] });\n\n for (const { path, methods = [METHOD_NAME_ALL] } of rules) {\n for (const method of methods) {\n router.add(method, path, null);\n }\n }\n\n return async (c, next) => {\n if (c.req.method === 'OPTIONS') {\n await next();\n return;\n }\n\n const [matched] = router.match(c.req.method, c.req.path);\n if (matched.length === 0) {\n await next();\n return;\n }\n\n const authenticated = await auth.isAuthenticated(c.req.raw);\n if (!authenticated) throw Status.unauthorized(errorMessage).error();\n await next();\n };\n}\n"],"mappings":";AAAA,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AAOhB,IAAM,aAAN,MAAM,YAAW;AAAA,EACL,SAAS,IAAI,YAAkB;AAAA,IAC9C,SAAS,CAAC,IAAI,aAAa,GAAG,IAAI,WAAW,CAAC;AAAA,EAChD,CAAC;AAAA,EAEgB;AAAA,EAET,YAAY,MAAY;AAC9B,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,OAAO,SAAS,CAAC,SAAe,IAAI,YAAW,IAAI;AAAA,EAEnD,MAAM,MAAc,SAAmC;AACrD,QAAI,SAAS;AACX,iBAAW,UAAU,SAAS;AAC5B,aAAK,OAAO,IAAI,QAAQ,MAAM,IAAI;AAAA,MACpC;AAAA,IACF,OAAO;AACL,WAAK,OAAO,IAAI,iBAAiB,MAAM,IAAI;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,MAAyB;AAC/B,WAAO,OAAO,GAAG,SAAS;AACxB,UAAI,EAAE,IAAI,WAAW,WAAW;AAC9B,cAAM,KAAK;AACX;AAAA,MACF;AAEA,YAAM,CAAC,OAAO,IAAI,KAAK,OAAO,MAAM,EAAE,IAAI,QAAQ,EAAE,IAAI,IAAI;AAC5D,UAAI,QAAQ,WAAW,GAAG;AACxB,cAAM,KAAK;AACX;AAAA,MACF;AAEA,YAAM,gBAAgB,MAAM,KAAK,KAAK,gBAAgB,EAAE,IAAI,GAAG;AAC/D,UAAI,CAAC,cAAe,OAAM,OAAO,aAAa,EAAE,MAAM;AACtD,YAAM,KAAK;AAAA,IACb;AAAA,EACF;AACF;AAQO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,eAAe;AAAA,EACf,QAAQ,CAAC;AACX,GAAwC;AACtC,QAAM,SAAS,IAAI,YAAkB,EAAE,SAAS,CAAC,IAAI,aAAa,GAAG,IAAI,WAAW,CAAC,EAAE,CAAC;AAExF,aAAW,EAAE,MAAM,UAAU,CAAC,eAAe,EAAE,KAAK,OAAO;AACzD,eAAW,UAAU,SAAS;AAC5B,aAAO,IAAI,QAAQ,MAAM,IAAI;AAAA,IAC/B;AAAA,EACF;AAEA,SAAO,OAAO,GAAG,SAAS;AACxB,QAAI,EAAE,IAAI,WAAW,WAAW;AAC9B,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,CAAC,OAAO,IAAI,OAAO,MAAM,EAAE,IAAI,QAAQ,EAAE,IAAI,IAAI;AACvD,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,gBAAgB,MAAM,KAAK,gBAAgB,EAAE,IAAI,GAAG;AAC1D,QAAI,CAAC,cAAe,OAAM,OAAO,aAAa,YAAY,EAAE,MAAM;AAClE,UAAM,KAAK;AAAA,EACb;AACF;","names":[]}
|