Skip to content

Commit ba6de76

Browse files
authoredMay 17, 2022
feat(remix-server-runtime): strip body from request before calling loaders (#3207)
feat: strip body from request before calling loaders Since loaders map to "GET" and "HEAD" requests, those by definition can't have a body and therefore there is no reason to pass it in to use-code. This also avoids exclusive locks on the body when multiple loaders are executed in parallel. Changes: - Action recieves OG request and can choose to read the body. - handleDocumentRequest recieves OG request, if the action read the body it will be locked and `bodyUsed` will be true. Atempting to read the body again will throw - Loaders recieve a copy of the OG request without the body. - Updated docs
1 parent 97ed0e1 commit ba6de76

File tree

3 files changed

+10
-21
lines changed

3 files changed

+10
-21
lines changed
 

‎docs/decisions/0002-do-not-clone-request.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ Status: accepted
66

77
## Context
88

9-
To allow multiple loaders / actions to read the body of a request, we have been cloning the request before forwarding it to user-code. This is not the best thing to do as some runtimes will begin buffering the body to allow for multiple consumers. It is also goes against "the platform" that states a request body should only be consumed once.
9+
To allow multiple loaders / actions to read the body of a request, we have been cloning the request before forwarding it to user-code. This is not the best thing to do as some runtimes will begin buffering the body to allow for multiple consumers. It also goes against "the platform" that states a request body should only be consumed once.
1010

1111
## Decision
1212

13-
Do not clone requests before they are passed to user-code (loaders, actions, handleDocumentRequest, handleDataRequest, etc.).
13+
Do not clone requests before they are passed to user-code (actions, handleDocumentRequest, handleDataRequest), and remove body from request passed to loaders. Loaders should be thought of as a "GET" / "HEAD" request handler. These request methods are not allowed to have a body, therefore you should not be reading it in your Remix loader function.
1414

1515
## Consequences
1616

17-
If you are reading the request body in both an action and a loader this will now fail. Loaders should be thought of as a "GET" / "HEAD" request handler. These request methods are not allowed to have a body, therefore you should not be reading it in your Remix loader function.
17+
Loaders always receive a null body for the request.
1818

19-
If you wish to continue reading the request body in multiple places for a single request against recommendations, consider using `.clone()` before reading it; just know this comes with tradeoffs.
19+
If you are reading the request body in both an action and handleDocumentRequest or handleDataRequest this will now fail as the body will have already been read. If you wish to continue reading the request body in multiple places for a single request against recommendations, consider using `.clone()` before reading it; just know this comes with tradeoffs.

‎packages/remix-server-runtime/responses.ts

-16
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,3 @@ export function isRedirectResponse(response: Response): boolean {
6969
export function isCatchResponse(response: Response) {
7070
return response.headers.get("X-Remix-Catch") != null;
7171
}
72-
73-
export function extractData(response: Response): Promise<unknown> {
74-
let contentType = response.headers.get("Content-Type");
75-
76-
if (contentType && /\bapplication\/json\b/.test(contentType)) {
77-
return response.json();
78-
}
79-
80-
// What other data types do we need to handle here? What other kinds of
81-
// responses are people going to be returning from their loaders?
82-
// - application/x-www-form-urlencoded ?
83-
// - multipart/form-data ?
84-
// - binary (audio/video) ?
85-
86-
return response.text();
87-
}

‎packages/remix-server-runtime/server.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -293,13 +293,18 @@ async function handleDocumentRequest({
293293
);
294294
}
295295

296+
let loaderRequest = new Request(request.url, {
297+
...request,
298+
body: null,
299+
});
300+
296301
let routeLoaderResults = await Promise.allSettled(
297302
matchesToLoad.map((match) =>
298303
match.route.module.loader
299304
? callRouteLoader({
300305
loadContext,
301306
match,
302-
request,
307+
request: loaderRequest,
303308
})
304309
: Promise.resolve(undefined)
305310
)

0 commit comments

Comments
 (0)
Please sign in to comment.