Skip to content

Commit 507035c

Browse files
committed
Wrap Hono request body parsing methods
1 parent 9bb042b commit 507035c

File tree

4 files changed

+58
-37
lines changed

4 files changed

+58
-37
lines changed

library/sources/Hono.test.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,21 @@ function getApp() {
9494
return c.json(getContext());
9595
});
9696

97+
app.post("/json", async (c) => {
98+
const json = await c.req.json();
99+
return c.json(getContext());
100+
});
101+
102+
app.post("/text", async (c) => {
103+
const text = await c.req.text();
104+
return c.json(getContext());
105+
});
106+
107+
app.post("/form", async (c) => {
108+
const form = await c.req.parseBody();
109+
return c.json(getContext());
110+
});
111+
97112
app.on(["GET"], ["/user", "/user/blocked"], (c) => {
98113
return c.json(getContext());
99114
});
@@ -140,7 +155,7 @@ t.test("it adds context from request for GET", opts, async (t) => {
140155
});
141156

142157
t.test("it adds JSON body to context", opts, async (t) => {
143-
const response = await getApp().request("/", {
158+
const response = await getApp().request("/json", {
144159
method: "POST",
145160
headers: {
146161
"content-type": "application/json",
@@ -153,12 +168,12 @@ t.test("it adds JSON body to context", opts, async (t) => {
153168
method: "POST",
154169
body: { title: "test" },
155170
source: "hono",
156-
route: "/",
171+
route: "/json",
157172
});
158173
});
159174

160175
t.test("it adds form body to context", opts, async (t) => {
161-
const response = await getApp().request("/", {
176+
const response = await getApp().request("/form", {
162177
method: "POST",
163178
headers: {
164179
"content-type": "application/x-www-form-urlencoded",
@@ -171,12 +186,12 @@ t.test("it adds form body to context", opts, async (t) => {
171186
method: "POST",
172187
body: { title: "test" },
173188
source: "hono",
174-
route: "/",
189+
route: "/form",
175190
});
176191
});
177192

178193
t.test("it adds text body to context", opts, async (t) => {
179-
const response = await getApp().request("/", {
194+
const response = await getApp().request("/text", {
180195
method: "POST",
181196
headers: {
182197
"content-type": "text/plain",
@@ -189,12 +204,12 @@ t.test("it adds text body to context", opts, async (t) => {
189204
method: "POST",
190205
body: "test",
191206
source: "hono",
192-
route: "/",
207+
route: "/text",
193208
});
194209
});
195210

196211
t.test("it adds xml body to context", opts, async (t) => {
197-
const response = await getApp().request("/", {
212+
const response = await getApp().request("/text", {
198213
method: "POST",
199214
headers: {
200215
"content-type": "application/xml",
@@ -207,7 +222,7 @@ t.test("it adds xml body to context", opts, async (t) => {
207222
method: "POST",
208223
body: "<test>test</test>",
209224
source: "hono",
210-
route: "/",
225+
route: "/text",
211226
});
212227
});
213228

library/sources/hono/contextFromRequest.ts

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,12 @@ import type { Context as HonoContext } from "hono";
22
import { Context } from "../../agent/Context";
33
import { buildRouteFromURL } from "../../helpers/buildRouteFromURL";
44
import { getIPAddressFromRequest } from "../../helpers/getIPAddressFromRequest";
5-
import { isJsonContentType } from "../../helpers/isJsonContentType";
65
import { parse } from "../../helpers/parseCookies";
76
import { getRemoteAddress } from "./getRemoteAddress";
87

98
export async function contextFromRequest(c: HonoContext): Promise<Context> {
109
const { req } = c;
1110

12-
let body = undefined;
13-
const contentType = req.header("content-type");
14-
if (contentType) {
15-
if (isJsonContentType(contentType)) {
16-
try {
17-
body = await req.json();
18-
} catch {
19-
// Ignore
20-
}
21-
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
22-
try {
23-
body = await req.parseBody();
24-
} catch {
25-
// Ignore
26-
}
27-
} else if (
28-
contentType.includes("text/plain") ||
29-
contentType.includes("xml")
30-
) {
31-
try {
32-
body = await req.text();
33-
} catch {
34-
// Ignore
35-
}
36-
}
37-
}
38-
3911
const cookieHeader = req.header("cookie");
4012

4113
return {
@@ -44,7 +16,7 @@ export async function contextFromRequest(c: HonoContext): Promise<Context> {
4416
headers: req.header(),
4517
remoteAddress: getRemoteAddress(c),
4618
}),
47-
body: body,
19+
body: undefined,
4820
url: req.url,
4921
headers: req.header(),
5022
routeParams: req.param(),
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type { Context } from "hono";
2+
import { getContext, updateContext } from "../../agent/Context";
3+
4+
export function wrapRequestBodyParsing(req: Context["req"]) {
5+
req.parseBody = wrapRequestHandler(req.parseBody);
6+
req.json = wrapRequestHandler(req.json);
7+
req.text = wrapRequestHandler(req.text);
8+
}
9+
10+
type BodyParseFunctions =
11+
| Context["req"]["parseBody"]
12+
| Context["req"]["json"]
13+
| Context["req"]["text"];
14+
15+
export function wrapRequestHandler<T extends BodyParseFunctions>(
16+
handler: T
17+
): T {
18+
return async function () {
19+
// @ts-expect-error No type for arguments
20+
const returnValue = await handler.apply(this, arguments);
21+
22+
if (returnValue) {
23+
const context = getContext();
24+
if (context) {
25+
updateContext(context, "body", returnValue);
26+
}
27+
}
28+
29+
return returnValue as ReturnType<T>;
30+
} as T;
31+
}

library/sources/hono/wrapRequestHandler.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Handler, MiddlewareHandler } from "hono";
22
import { runWithContext } from "../../agent/Context";
33
import { contextFromRequest } from "./contextFromRequest";
4+
import { wrapRequestBodyParsing } from "./wrapRequestBodyParsing";
45

56
export function wrapRequestHandler(
67
handler: Handler | MiddlewareHandler
@@ -9,6 +10,8 @@ export function wrapRequestHandler(
910
const context = await contextFromRequest(c);
1011

1112
return await runWithContext(context, async () => {
13+
wrapRequestBodyParsing(c.req);
14+
1215
return await handler(c, next);
1316
});
1417
};

0 commit comments

Comments
 (0)