Skip to content

Commit 603988d

Browse files
authored
fix(parser): allow VPC envelopes to handle non-JSON strings (#3534)
1 parent d18e03d commit 603988d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+372
-590
lines changed

Diff for: package-lock.json

-64
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/parser/package.json

-3
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,5 @@
379379
"@middy/core": {
380380
"optional": true
381381
}
382-
},
383-
"devDependencies": {
384-
"@anatine/zod-mock": "^3.13.3"
385382
}
386383
}

Diff for: packages/parser/src/envelopes/envelope.ts

+1-76
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,7 @@
1-
import type { ZodSchema, z } from 'zod';
2-
import { ParseError } from '../errors.js';
3-
import type { ParsedResult } from '../types/parser.js';
4-
5-
/* v8 ignore start */
6-
const Envelope = {
7-
/**
8-
* Abstract function to parse the content of the envelope using provided schema.
9-
* Both inputs are provided as unknown by the user.
10-
* We expect the data to be either string that can be parsed to json or object.
11-
* @internal
12-
* @param data data to parse
13-
* @param schema schema
14-
*/
15-
parse<T extends ZodSchema>(data: unknown, schema: T): z.infer<T> {
16-
if (typeof data !== 'object' && typeof data !== 'string') {
17-
throw new ParseError(
18-
`Invalid data type for envelope. Expected string or object, got ${typeof data}`
19-
);
20-
}
21-
try {
22-
if (typeof data === 'string') {
23-
return schema.parse(JSON.parse(data));
24-
}
25-
if (typeof data === 'object') {
26-
return schema.parse(data);
27-
}
28-
} catch (e) {
29-
throw new ParseError('Failed to parse envelope', { cause: e as Error });
30-
}
31-
},
32-
33-
/**
34-
* Abstract function to safely parse the content of the envelope using provided schema.
35-
* safeParse is used to avoid throwing errors, thus we catuch all errors and wrap them in the result.
36-
* @param input
37-
* @param schema
38-
*/
39-
safeParse<T extends ZodSchema>(
40-
input: unknown,
41-
schema: T
42-
): ParsedResult<unknown, z.infer<T>> {
43-
try {
44-
if (typeof input !== 'object' && typeof input !== 'string') {
45-
return {
46-
success: false,
47-
error: new Error(
48-
`Invalid data type for envelope. Expected string or object, got ${typeof input}`
49-
),
50-
};
51-
}
52-
53-
const parsed = schema.safeParse(
54-
typeof input === 'string' ? JSON.parse(input) : input
55-
);
56-
57-
return parsed.success
58-
? {
59-
success: true,
60-
data: parsed.data,
61-
}
62-
: {
63-
success: false,
64-
error: parsed.error,
65-
};
66-
} catch (e) {
67-
return {
68-
success: false,
69-
error: e as Error,
70-
};
71-
}
72-
},
73-
};
74-
751
/**
762
* This is a discriminator to differentiate whether an envelope returns an array or an object
773
* @hidden
784
*/
795
const envelopeDiscriminator = Symbol.for('returnType');
806

81-
export { Envelope, envelopeDiscriminator };
82-
/* v8 ignore stop */
7+
export { envelopeDiscriminator };

Diff for: packages/parser/src/envelopes/vpc-lattice.ts

+24-21
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { ZodSchema, z } from 'zod';
22
import { ParseError } from '../errors.js';
33
import { VpcLatticeSchema } from '../schemas/index.js';
44
import type { ParsedResult } from '../types/index.js';
5-
import { Envelope, envelopeDiscriminator } from './envelope.js';
5+
import { envelopeDiscriminator } from './envelope.js';
66

77
/**
88
* Amazon VPC Lattice envelope to extract data within body key
@@ -15,35 +15,38 @@ export const VpcLatticeEnvelope = {
1515
*/
1616
[envelopeDiscriminator]: 'object' as const,
1717
parse<T extends ZodSchema>(data: unknown, schema: T): z.infer<T> {
18-
const parsedEnvelope = VpcLatticeSchema.parse(data);
19-
20-
return Envelope.parse(parsedEnvelope.body, schema);
21-
},
22-
23-
safeParse<T extends ZodSchema>(data: unknown, schema: T): ParsedResult<unknown, z.infer<T>> {
24-
const parsedEnvelope = VpcLatticeSchema.safeParse(data);
25-
if (!parsedEnvelope.success) {
26-
return {
27-
success: false,
28-
error: new ParseError('Failed to parse VpcLattice envelope', {
29-
cause: parsedEnvelope.error,
30-
}),
31-
originalEvent: data,
32-
};
18+
try {
19+
return VpcLatticeSchema.extend({
20+
body: schema,
21+
}).parse(data).body;
22+
} catch (error) {
23+
throw new ParseError('Failed to parse VPC Lattice body', {
24+
cause: error as Error,
25+
});
3326
}
27+
},
3428

35-
const parsedBody = Envelope.safeParse(parsedEnvelope.data.body, schema);
29+
safeParse<T extends ZodSchema>(
30+
data: unknown,
31+
schema: T
32+
): ParsedResult<unknown, z.infer<T>> {
33+
const result = VpcLatticeSchema.extend({
34+
body: schema,
35+
}).safeParse(data);
3636

37-
if (!parsedBody.success) {
37+
if (!result.success) {
3838
return {
3939
success: false,
40-
error: new ParseError('Failed to parse VpcLattice envelope body', {
41-
cause: parsedBody.error,
40+
error: new ParseError('Failed to parse VPC Lattice body', {
41+
cause: result.error,
4242
}),
4343
originalEvent: data,
4444
};
4545
}
4646

47-
return parsedBody;
47+
return {
48+
success: true,
49+
data: result.data.body,
50+
};
4851
},
4952
};

Diff for: packages/parser/src/envelopes/vpc-latticev2.ts

+24-21
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { ZodSchema, z } from 'zod';
22
import { ParseError } from '../errors.js';
33
import { VpcLatticeV2Schema } from '../schemas/index.js';
44
import type { ParsedResult } from '../types/index.js';
5-
import { Envelope, envelopeDiscriminator } from './envelope.js';
5+
import { envelopeDiscriminator } from './envelope.js';
66

77
/**
88
* Amazon VPC Lattice envelope to extract data within body key
@@ -14,35 +14,38 @@ export const VpcLatticeV2Envelope = {
1414
*/
1515
[envelopeDiscriminator]: 'object' as const,
1616
parse<T extends ZodSchema>(data: unknown, schema: T): z.infer<T> {
17-
const parsedEnvelope = VpcLatticeV2Schema.parse(data);
18-
19-
return Envelope.parse(parsedEnvelope.body, schema);
20-
},
21-
22-
safeParse<T extends ZodSchema>(data: unknown, schema: T): ParsedResult<unknown, z.infer<T>> {
23-
const parsedEnvelope = VpcLatticeV2Schema.safeParse(data);
24-
if (!parsedEnvelope.success) {
25-
return {
26-
success: false,
27-
error: new ParseError('Failed to parse VpcLatticeV2 envelope.', {
28-
cause: parsedEnvelope.error,
29-
}),
30-
originalEvent: data,
31-
};
17+
try {
18+
return VpcLatticeV2Schema.extend({
19+
body: schema,
20+
}).parse(data).body;
21+
} catch (error) {
22+
throw new ParseError('Failed to parse VPC Lattice v2 body', {
23+
cause: error as Error,
24+
});
3225
}
26+
},
3327

34-
const parsedBody = Envelope.safeParse(parsedEnvelope.data.body, schema);
28+
safeParse<T extends ZodSchema>(
29+
data: unknown,
30+
schema: T
31+
): ParsedResult<unknown, z.infer<T>> {
32+
const result = VpcLatticeV2Schema.extend({
33+
body: schema,
34+
}).safeParse(data);
3535

36-
if (!parsedBody.success) {
36+
if (!result.success) {
3737
return {
3838
success: false,
39-
error: new ParseError('Failed to parse VpcLatticeV2 body.', {
40-
cause: parsedBody.error,
39+
error: new ParseError('Failed to parse VPC Lattice v2 body', {
40+
cause: result.error,
4141
}),
4242
originalEvent: data,
4343
};
4444
}
4545

46-
return parsedBody;
46+
return {
47+
success: true,
48+
data: result.data.body,
49+
};
4750
},
4851
};

Diff for: packages/parser/tests/events/vpcLatticeEvent.json renamed to packages/parser/tests/events/vpc-lattice/base.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
"query_string_parameters": {
1111
"order-id": "1"
1212
},
13-
"body": "eyJ0ZXN0IjogImV2ZW50In0=",
14-
"is_base64_encoded": true
15-
}
13+
"body": "{\"message\": \"Hello from Lambda!\"}",
14+
"is_base64_encoded": false
15+
}

Diff for: packages/parser/tests/events/vpcLatticeEventPathTrailingSlash.json

-15
This file was deleted.

Diff for: packages/parser/tests/events/vpcLatticeEventV2PathTrailingSlash.json

-30
This file was deleted.

0 commit comments

Comments
 (0)