Skip to content

Commit d795830

Browse files
authored
fix: improve error handling for webhook v2 (#4062)
2 parents 68497f9 + 5d1e1bd commit d795830

File tree

12 files changed

+77
-24
lines changed

12 files changed

+77
-24
lines changed

src/constants/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ const HTTP_CUSTOM_STATUS_CODES = {
5555
FILTERED: 298,
5656
};
5757

58+
const ErrorMessages = {
59+
JSONParseError: 'Malformed JSON in request body',
60+
};
61+
5862
module.exports = {
5963
EventType,
6064
GENERIC_TRUE_VALUES,
@@ -64,4 +68,5 @@ module.exports = {
6468
TraitsMapping,
6569
WhiteListedTraits,
6670
HTTP_CUSTOM_STATUS_CODES,
71+
ErrorMessages,
6772
};
Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
1+
import { TransformationError } from '@rudderstack/integrations-lib';
12
import { SourceInputConversionResult, SourceInputV2 } from '../../../types';
23
import { VersionConversionStrategy } from './abstractions';
4+
import { ErrorMessages } from '../../../constants';
35

46
export class StrategyV2ToV0 extends VersionConversionStrategy<SourceInputV2, NonNullable<unknown>> {
57
convert(sourceEvents: SourceInputV2[]): SourceInputConversionResult<NonNullable<unknown>>[] {
6-
return sourceEvents.map((sourceEvent) => {
7-
try {
8-
const v0Event = JSON.parse(sourceEvent.request.body);
9-
return { output: v0Event };
10-
} catch (err) {
11-
const conversionError =
12-
err instanceof Error ? err : new Error('error converting v2 to v0 spec');
13-
return { conversionError };
14-
}
15-
});
8+
return sourceEvents.map((sourceEvent) => this.convertSingleEvent(sourceEvent));
9+
}
10+
11+
private convertSingleEvent(
12+
sourceEvent: SourceInputV2,
13+
): SourceInputConversionResult<NonNullable<unknown>> {
14+
try {
15+
const v0Event = this.parseRequestBody(sourceEvent.request.body);
16+
return { output: v0Event };
17+
} catch (err) {
18+
const conversionError =
19+
err instanceof TransformationError ? err : new Error('error converting v2 to v0 spec');
20+
21+
return { conversionError };
22+
}
23+
}
24+
25+
private parseRequestBody(body: string): NonNullable<unknown> {
26+
try {
27+
return JSON.parse(body);
28+
} catch (err) {
29+
throw new TransformationError(ErrorMessages.JSONParseError);
30+
}
1631
}
1732
}
Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
1+
import { TransformationError } from '@rudderstack/integrations-lib';
12
import { SourceInput, SourceInputConversionResult, SourceInputV2 } from '../../../types';
23
import { VersionConversionStrategy } from './abstractions';
34

45
export class StrategyV2ToV1 extends VersionConversionStrategy<SourceInputV2, SourceInput> {
56
convert(sourceEvents: SourceInputV2[]): SourceInputConversionResult<SourceInput>[] {
6-
return sourceEvents.map((sourceEvent) => {
7-
try {
8-
const v1Event = { event: JSON.parse(sourceEvent.request.body), source: sourceEvent.source };
9-
return { output: v1Event };
10-
} catch (err) {
11-
const conversionError =
12-
err instanceof Error ? err : new Error('error converting v2 to v1 spec');
13-
return { conversionError };
14-
}
15-
});
7+
return sourceEvents.map((sourceEvent) => this.convertSingleEvent(sourceEvent));
8+
}
9+
10+
private convertSingleEvent(sourceEvent: SourceInputV2): SourceInputConversionResult<SourceInput> {
11+
try {
12+
const v1Event = {
13+
event: this.parseRequestBody(sourceEvent.request.body),
14+
source: sourceEvent.source,
15+
};
16+
return { output: v1Event };
17+
} catch (err) {
18+
const conversionError =
19+
err instanceof TransformationError ? err : new Error('error converting v2 to v1 spec');
20+
return { conversionError };
21+
}
22+
}
23+
24+
private parseRequestBody(body: string): NonNullable<unknown> {
25+
try {
26+
return JSON.parse(body);
27+
} catch (err) {
28+
throw new TransformationError('Malformed JSON in request body');
29+
}
1630
}
1731
}

src/controllers/util/index.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { TransformationError } from '@rudderstack/integrations-lib';
2+
import { ErrorMessages } from '../../constants';
13
import {
24
Destination,
35
Metadata,
@@ -222,7 +224,7 @@ describe('adaptInputToVersion', () => {
222224
implementationVersion: 'v0',
223225
input: [
224226
{
225-
conversionError: new SyntaxError('Unexpected end of JSON input'),
227+
conversionError: new TransformationError(ErrorMessages.JSONParseError),
226228
},
227229
],
228230
};
@@ -321,7 +323,7 @@ describe('adaptInputToVersion', () => {
321323
implementationVersion: 'v1',
322324
input: [
323325
{
324-
conversionError: new SyntaxError('Unexpected end of JSON input'),
326+
conversionError: new TransformationError(ErrorMessages.JSONParseError),
325327
},
326328
],
327329
};

src/services/source/nativeIntegration.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { FetchHandler } from '../../helpers/fetchHandlers';
22
import { SourceService } from '../../interfaces/SourceService';
33
import {
44
ErrorDetailer,
5+
ErrorDetailerOptions,
56
MetaTransferObject,
67
RudderMessage,
78
SourceInputConversionResult,
@@ -15,13 +16,14 @@ import { SourcePostTransformationService } from './postTransformation';
1516
import logger from '../../logger';
1617

1718
export class NativeIntegrationSourceService implements SourceService {
18-
public getTags(): MetaTransferObject {
19+
public getTags(extraErrorDetails: ErrorDetailerOptions = {}): MetaTransferObject {
1920
const metaTO = {
2021
errorDetails: {
2122
module: tags.MODULES.SOURCE,
2223
implementation: tags.IMPLEMENTATIONS.NATIVE,
2324
destinationId: 'Non determinable',
2425
workspaceId: 'Non determinable',
26+
...extraErrorDetails,
2527
} as ErrorDetailer,
2628
errorContext: '[Native Integration Service] Failure During Source Transform',
2729
} as MetaTransferObject;
@@ -36,7 +38,7 @@ export class NativeIntegrationSourceService implements SourceService {
3638
_requestMetadata: NonNullable<unknown>,
3739
): Promise<SourceTransformationResponse[]> {
3840
const sourceHandler = FetchHandler.getSourceHandler(sourceType, version);
39-
const metaTO = this.getTags();
41+
const metaTO = this.getTags({ srcType: sourceType });
4042
const respList: SourceTransformationResponse[] = await Promise.all<FixMe>(
4143
sourceEvents.map(async (sourceEvent) => {
4244
try {

src/types/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ type ErrorDetailer = {
270270
module: string;
271271
implementation: string;
272272
feature: string;
273+
} & ErrorDetailerOptions;
274+
275+
type ErrorDetailerOptions = {
273276
errorCategory?: string;
274277
errorType?: string;
275278
meta?: string;
@@ -390,6 +393,7 @@ export {
390393
Connection,
391394
Destination,
392395
ErrorDetailer,
396+
ErrorDetailerOptions,
393397
MessageIdMetadataMap,
394398
MetaTransferObject,
395399
Metadata,

test/integrations/sources/adjust/data.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ export const data = [
120120
errorCategory: 'transformation',
121121
implementation: 'native',
122122
module: 'source',
123+
srcType: 'adjust',
123124
workspaceId: 'Non determinable',
124125
},
125126
statusCode: 400,
@@ -176,6 +177,7 @@ export const data = [
176177
errorCategory: 'transformation',
177178
implementation: 'native',
178179
module: 'source',
180+
srcType: 'adjust',
179181
workspaceId: 'Non determinable',
180182
},
181183
statusCode: 400,

test/integrations/sources/appsflyer/data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ export const data = [
687687
errorCategory: 'transformation',
688688
implementation: 'native',
689689
module: 'source',
690+
srcType: 'appsflyer',
690691
workspaceId: 'Non determinable',
691692
},
692693
statusCode: 400,

test/integrations/sources/canny/data.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,7 @@ export const data = [
15731573
errorCategory: 'transformation',
15741574
implementation: 'native',
15751575
module: 'source',
1576+
srcType: 'canny',
15761577
workspaceId: 'Non determinable',
15771578
},
15781579
},
@@ -1650,6 +1651,7 @@ export const data = [
16501651
errorCategory: 'transformation',
16511652
implementation: 'native',
16521653
module: 'source',
1654+
srcType: 'canny',
16531655
workspaceId: 'Non determinable',
16541656
},
16551657
},

test/integrations/sources/gainsightpx/data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,7 @@ export const data = [
853853
errorCategory: 'transformation',
854854
implementation: 'native',
855855
module: 'source',
856+
srcType: 'gainsightpx',
856857
workspaceId: 'Non determinable',
857858
},
858859
statusCode: 400,

0 commit comments

Comments
 (0)