Skip to content

Commit 297f3ad

Browse files
committed
fix(validateResponse): handle responses created with aResponse
1 parent 10983a2 commit 297f3ad

File tree

2 files changed

+45
-12
lines changed

2 files changed

+45
-12
lines changed

src/validateResponse.spec.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,48 @@
1+
import { HttpStatusCode } from '@hello.nrfcloud.com/proto/hello'
12
import middy from '@middy/core'
23
import { Type } from '@sinclair/typebox'
34
import type { Context } from 'aws-lambda'
45
import assert from 'node:assert'
56
import { describe, it } from 'node:test'
7+
import { aResponse } from './aResponse.js'
68
import {
79
ResponseValidationFailedError,
810
validateResponse,
911
} from './validateResponse.js'
1012

1113
void describe('validateResponse()', () => {
1214
void it('should validate the response', async () =>
13-
assert.equal(
15+
assert.deepEqual(
1416
await middy()
15-
.use(validateResponse(Type.Boolean({ title: 'A boolean' })))
16-
.handler(async () => true)('Some event', {} as Context),
17-
true,
17+
.use(validateResponse(Type.Object({ value: Type.Boolean() })))
18+
.handler(async () =>
19+
aResponse(HttpStatusCode.OK, {
20+
'@context': new URL('https://example.com'),
21+
value: true,
22+
}),
23+
)('Some event', {} as Context),
24+
{
25+
body: '{"@context":"https://example.com/","value":true}',
26+
headers: {
27+
'Cache-Control': 'public, max-age=60',
28+
'content-length': '48',
29+
'content-type': 'application/json',
30+
},
31+
statusCode: 200,
32+
},
1833
))
1934

2035
void it('should throw an Error in case the response is invalid', async () =>
2136
assert.rejects(
2237
async () =>
2338
middy()
24-
.use(validateResponse(Type.Boolean()))
25-
.handler(async () => 42)('Some event', {} as Context),
39+
.use(validateResponse(Type.Object({ value: Type.Boolean() })))
40+
.handler(async () =>
41+
aResponse(HttpStatusCode.OK, {
42+
'@context': new URL('https://example.com'),
43+
value: 42,
44+
}),
45+
)('Some event', {} as Context),
2646
ResponseValidationFailedError,
2747
))
2848
})

src/validateResponse.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
import type middy from '@middy/core'
66
import type { TSchema } from '@sinclair/typebox'
77
import type { ValueError } from '@sinclair/typebox/errors'
8+
import { tryAsJSON } from './tryAsJSON.js'
89
import { ValidationFailedError } from './validateInput.js'
910

1011
export class ResponseValidationFailedError extends ValidationFailedError {
@@ -14,25 +15,37 @@ export class ResponseValidationFailedError extends ValidationFailedError {
1415
}
1516
}
1617

18+
/**
19+
* Validate responses created with `aResponse`
20+
*/
1721
export const validateResponse = <ResponseSchema extends TSchema>(
1822
schema: ResponseSchema,
1923
): middy.MiddlewareObj => {
2024
const validator = validateWithTypeBox(schema)
2125
return {
2226
after: async (req) => {
23-
const maybeValid = validator(req.response)
27+
const body = req.response?.body
28+
if ((body?.length ?? 0) === 0) {
29+
console.debug(`[validateResponse]`, `Response body is empty`)
30+
}
31+
if (
32+
(req.response.headers['content-type']?.includes('application/json') ??
33+
false) === false
34+
) {
35+
console.debug(`[validateResponse]`, `Response body is not JSON`)
36+
}
37+
const maybeValid = validator(tryAsJSON(req.response.body))
2438
if ('errors' in maybeValid) {
2539
console.error(
2640
`[validateResponse]`,
2741
`Response validation failed`,
28-
JSON.stringify({
29-
response: req.response,
30-
errors: formatTypeBoxErrors(maybeValid.errors),
31-
}),
42+
req.response.body,
43+
formatTypeBoxErrors(maybeValid.errors),
44+
schema.title,
3245
)
3346
throw new ResponseValidationFailedError(maybeValid.errors)
3447
}
35-
console.debug(`[validateResponse]`, `Response is`, schema.title)
48+
console.debug(`[validateResponse]`, `Response is valid`, schema.title)
3649
return undefined
3750
},
3851
}

0 commit comments

Comments
 (0)