Skip to content

Commit 0c0ae91

Browse files
authored
fix(remix): Return response if detected in root loader (#5558)
This patch updates the remix root loader wrapper to return a response when possible. This allows user set headers to be propogated. We do this by vendoring in Remix's `json` utility and using it accordingly. We also now return the response directly instead of the data in cases where the data is not an object.
1 parent 7d338b4 commit 0c0ae91

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

packages/remix/src/utils/instrumentServer.ts

+28-3
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,29 @@ function getTraceAndBaggage(): { sentryTrace?: string; sentryBaggage?: string }
269269
return {};
270270
}
271271

272+
// https://github.com/remix-run/remix/blob/7688da5c75190a2e29496c78721456d6e12e3abe/packages/remix-server-runtime/responses.ts#L1-L4
273+
export type JsonFunction = <Data>(data: Data, init?: number | ResponseInit) => Response;
274+
275+
/**
276+
* This is a shortcut for creating `application/json` responses. Converts `data`
277+
* to JSON and sets the `Content-Type` header.
278+
*
279+
* @see https://remix.run/api/remix#json
280+
*
281+
* https://github.com/remix-run/remix/blob/7688da5c75190a2e29496c78721456d6e12e3abe/packages/remix-server-runtime/responses.ts#L12-L24
282+
*/
283+
const json: JsonFunction = (data, init = {}) => {
284+
const responseInit = typeof init === 'number' ? { status: init } : init;
285+
const headers = new Headers(responseInit.headers);
286+
if (!headers.has('Content-Type')) {
287+
headers.set('Content-Type', 'application/json; charset=utf-8');
288+
}
289+
return new Response(JSON.stringify(data), {
290+
...responseInit,
291+
headers,
292+
});
293+
};
294+
272295
function makeWrappedRootLoader(origLoader: DataFunction): DataFunction {
273296
return async function (this: unknown, args: DataFunctionArgs): Promise<Response | AppData> {
274297
const res = await origLoader.call(this, args);
@@ -277,12 +300,14 @@ function makeWrappedRootLoader(origLoader: DataFunction): DataFunction {
277300
// Note: `redirect` and `catch` responses do not have bodies to extract
278301
if (isResponse(res) && !isRedirectResponse(res) && !isCatchResponse(res)) {
279302
const data = await extractData(res);
280-
281303
if (typeof data === 'object') {
282-
return { ...data, ...traceAndBaggage };
304+
return json(
305+
{ ...data, ...traceAndBaggage },
306+
{ headers: res.headers, statusText: res.statusText, status: res.status },
307+
);
283308
} else {
284309
__DEBUG_BUILD__ && logger.warn('Skipping injection of trace and baggage as the response body is not an object');
285-
return data;
310+
return res;
286311
}
287312
}
288313

packages/remix/test/integration/tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"lib": ["DOM", "DOM.Iterable", "ES2019"],
55
"isolatedModules": true,
66
"esModuleInterop": true,
7-
"jsx": "react",
7+
"jsx": "react-jsx",
88
"moduleResolution": "node",
99
"resolveJsonModule": true,
1010
"target": "ES2019",

0 commit comments

Comments
 (0)