Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"@sentry-internal/eslint-config-sdk": "10.31.0",
"@sentry-internal/eslint-plugin-sdk": "10.31.0",
"@sentry-internal/typescript": "10.31.0",
"@sentry/wizard": "6.9.0",
"@sentry/wizard": "6.10.0",
"@testing-library/react-native": "^13.2.2",
"@types/jest": "^29.5.13",
"@types/node": "^20.9.3",
Expand Down
11 changes: 8 additions & 3 deletions packages/core/src/js/tools/metroMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const readFileAsync = promisify(readFile);
export const stackFramesContextMiddleware: Middleware = async (
request: IncomingMessage,
response: ServerResponse,
_next: () => void,
): Promise<void> => {
debug.log('[@sentry/react-native/metro] Received request for stack frames context.');
request.setEncoding('utf8');
Expand Down Expand Up @@ -89,11 +90,15 @@ const SENTRY_CONTEXT_REQUEST_PATH = `${SENTRY_MIDDLEWARE_PATH}/context`;
* Creates a middleware that adds source context to the Sentry formatted stack frames.
*/
export const createSentryMetroMiddleware = (middleware: Middleware): Middleware => {
return (request: IncomingMessage, response: ServerResponse, next: unknown) => {
return (request: IncomingMessage, response: ServerResponse, next: () => void) => {
if (request.url?.startsWith(SENTRY_CONTEXT_REQUEST_PATH)) {
return stackFramesContextMiddleware(request, response);
return stackFramesContextMiddleware(request, response, next);
}
return middleware(request, response, next);
return (middleware as (req: IncomingMessage, res: ServerResponse, next: () => void) => void)(
request,
response,
next,
);
};
};

Expand Down
23 changes: 12 additions & 11 deletions packages/core/test/tools/metroMiddleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe('metroMiddleware', () => {
} as any;
testedMiddleware(sentryRequest, response, next);
expect(defaultMiddleware).not.toHaveBeenCalled();
expect(spiedStackFramesContextMiddleware).toHaveBeenCalledWith(sentryRequest, response);
expect(spiedStackFramesContextMiddleware).toHaveBeenCalledWith(sentryRequest, response, next);
});

it('should call default middleware for non-sentry requests', () => {
Expand All @@ -97,6 +97,7 @@ describe('metroMiddleware', () => {
describe('stackFramesContextMiddleware', () => {
let request: any;
let response: any;
const next = jest.fn();

let testData: string = '';

Expand Down Expand Up @@ -124,43 +125,43 @@ describe('metroMiddleware', () => {
});

it('should set request encoding to utf8', async () => {
await stackFramesContextMiddleware(request, response);
await stackFramesContextMiddleware(request, response, next);

expect(request.setEncoding).toHaveBeenCalledWith('utf8');
});

it('should return 400 for missing request body', async () => {
await stackFramesContextMiddleware(request, response);
await stackFramesContextMiddleware(request, response, next);

expect(response.statusCode).toBe(400);
expect(response.end).toHaveBeenCalledWith('Invalid request body. Expected a JSON object.');
});

it('should return 400 for invalid request body', async () => {
testData = 'invalid';
await stackFramesContextMiddleware(request, response);
await stackFramesContextMiddleware(request, response, next);

expect(response.statusCode).toBe(400);
});

it('should return 400 when stack is not an array', async () => {
testData = '{"stack": "not an array"}';
await stackFramesContextMiddleware(request, response);
await stackFramesContextMiddleware(request, response, next);

expect(response.statusCode).toBe(400);
expect(response.end).toHaveBeenCalledWith('Invalid stack frames. Expected an array.');
});

it('should set content type to application/json for valid response', async () => {
testData = '{"stack":[]}';
await stackFramesContextMiddleware(request, response);
await stackFramesContextMiddleware(request, response, next);

expect(response.setHeader).toHaveBeenCalledWith('Content-Type', 'application/json');
});

it('should return 200 for valid empty stack', async () => {
testData = '{"stack":[]}';
await stackFramesContextMiddleware(request, response);
await stackFramesContextMiddleware(request, response, next);

expect(response.statusCode).toBe(200);
});
Expand All @@ -181,7 +182,7 @@ describe('metroMiddleware', () => {

mockReadFileOnce(readFileSpy, 'test.js', 'line1\nline2\nline3\nline4\nline5');

await stackFramesContextMiddleware(request, response);
await stackFramesContextMiddleware(request, response, next);

expect(response.statusCode).toBe(200);
expect(JSON.parse(response.end.mock.calls[0][0])).toEqual({
Expand Down Expand Up @@ -213,7 +214,7 @@ describe('metroMiddleware', () => {
],
} satisfies { stack: StackFrame[] });

await stackFramesContextMiddleware(request, response);
await stackFramesContextMiddleware(request, response, next);

expect(readFileSpy).not.toHaveBeenCalled();
expect(response.statusCode).toBe(200);
Expand Down Expand Up @@ -243,7 +244,7 @@ describe('metroMiddleware', () => {
],
} satisfies { stack: StackFrame[] });

await stackFramesContextMiddleware(request, response);
await stackFramesContextMiddleware(request, response, next);

expect(readFileSpy).not.toHaveBeenCalled();
expect(response.statusCode).toBe(200);
Expand Down Expand Up @@ -295,7 +296,7 @@ describe('metroMiddleware', () => {
],
} satisfies { stack: StackFrame[] });

await stackFramesContextMiddleware(request, response);
await stackFramesContextMiddleware(request, response, next);

expect(response.statusCode).toBe(200);
expect(JSON.parse(response.end.mock.calls[0][0])).toEqual({
Expand Down
Loading
Loading