Skip to content

Commit 345fda7

Browse files
authored
ref: Make beforeSend more strict (#3713)
1 parent 9cd2b7e commit 345fda7

File tree

2 files changed

+41
-23
lines changed

2 files changed

+41
-23
lines changed

packages/core/src/baseclient.ts

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
import {
1414
dateTimestampInSeconds,
1515
Dsn,
16+
isPlainObject,
1617
isPrimitive,
1718
isThenable,
1819
logger,
@@ -517,17 +518,7 @@ export abstract class BaseClient<B extends Backend, O extends Options> implement
517518
}
518519

519520
const beforeSendResult = beforeSend(prepared, hint);
520-
if (typeof beforeSendResult === 'undefined') {
521-
throw new SentryError('`beforeSend` method has to return `null` or a valid event.');
522-
} else if (isThenable(beforeSendResult)) {
523-
return (beforeSendResult as PromiseLike<Event | null>).then(
524-
event => event,
525-
e => {
526-
throw new SentryError(`beforeSend rejected with ${e}`);
527-
},
528-
);
529-
}
530-
return beforeSendResult;
521+
return this._ensureBeforeSendRv(beforeSendResult);
531522
})
532523
.then(processedEvent => {
533524
if (processedEvent === null) {
@@ -575,4 +566,29 @@ export abstract class BaseClient<B extends Backend, O extends Options> implement
575566
},
576567
);
577568
}
569+
570+
/**
571+
* Verifies that return value of configured `beforeSend` is of expected type.
572+
*/
573+
protected _ensureBeforeSendRv(
574+
rv: PromiseLike<Event | null> | Event | null,
575+
): PromiseLike<Event | null> | Event | null {
576+
const nullErr = '`beforeSend` method has to return `null` or a valid event.';
577+
if (isThenable(rv)) {
578+
return (rv as PromiseLike<Event | null>).then(
579+
event => {
580+
if (!(isPlainObject(event) || event === null)) {
581+
throw new SentryError(nullErr);
582+
}
583+
return event;
584+
},
585+
e => {
586+
throw new SentryError(`beforeSend rejected with ${e}`);
587+
},
588+
);
589+
} else if (!(isPlainObject(rv) || rv === null)) {
590+
throw new SentryError(nullErr);
591+
}
592+
return rv;
593+
}
578594
}

packages/core/test/lib/base.test.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -707,18 +707,20 @@ describe('BaseClient', () => {
707707
});
708708

709709
test('calls beforeSend and log info about invalid return value', () => {
710-
expect.assertions(3);
711-
const beforeSend = jest.fn(() => undefined);
712-
// @ts-ignore we need to test regular-js behavior
713-
const client = new TestClient({ dsn: PUBLIC_DSN, beforeSend });
714-
const captureExceptionSpy = jest.spyOn(client, 'captureException');
715-
const loggerErrorSpy = jest.spyOn(logger, 'error');
716-
client.captureEvent({ message: 'hello' });
717-
expect(TestBackend.instance!.event).toBeUndefined();
718-
expect(captureExceptionSpy).not.toBeCalled();
719-
expect(loggerErrorSpy).toBeCalledWith(
720-
new SentryError('`beforeSend` method has to return `null` or a valid event.'),
721-
);
710+
const invalidValues = [undefined, false, true, [], 1];
711+
expect.assertions(invalidValues.length * 2);
712+
713+
for (const val of invalidValues) {
714+
const beforeSend = jest.fn(() => val);
715+
// @ts-ignore we need to test regular-js behavior
716+
const client = new TestClient({ dsn: PUBLIC_DSN, beforeSend });
717+
const loggerErrorSpy = jest.spyOn(logger, 'error');
718+
client.captureEvent({ message: 'hello' });
719+
expect(TestBackend.instance!.event).toBeUndefined();
720+
expect(loggerErrorSpy).toBeCalledWith(
721+
new SentryError('`beforeSend` method has to return `null` or a valid event.'),
722+
);
723+
}
722724
});
723725

724726
test('calls async beforeSend and uses original event without any changes', done => {

0 commit comments

Comments
 (0)