Skip to content

Commit 5d00848

Browse files
committed
feat: add requestLogger and validateInput middlewares
1 parent 0731bac commit 5d00848

File tree

4 files changed

+89
-2
lines changed

4 files changed

+89
-2
lines changed

package-lock.json

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
"peerDependencies": {
8484
"@aws-lambda-powertools/metrics": "^2.6.0",
8585
"@hello.nrfcloud.com/proto": "^14.2.8",
86-
"@middy/core": "^5.4.5"
86+
"@middy/core": "^5.4.5",
87+
"@middy/input-output-logger": "^5.4.5"
8788
}
8889
}

src/middleware/requestLogger.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import inputOutputLogger from '@middy/input-output-logger'
2+
3+
export const requestLogger = (): ReturnType<typeof inputOutputLogger> =>
4+
inputOutputLogger({
5+
logger: (message) => console.debug(JSON.stringify(message)),
6+
})

src/middleware/validateInput.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import type {
2+
APIGatewayProxyEventV2,
3+
APIGatewayProxyStructuredResultV2,
4+
Context,
5+
} from 'aws-lambda'
6+
import type { MiddlewareObj } from '@middy/core'
7+
import type { Static, TSchema } from '@sinclair/typebox'
8+
import {
9+
formatTypeBoxErrors,
10+
validateWithTypeBox,
11+
} from '@hello.nrfcloud.com/proto'
12+
import { HttpStatusCode } from '@hello.nrfcloud.com/proto/hello'
13+
import { tryAsJSON } from '../tryAsJSON.js'
14+
import { aProblem } from '../aProblem.js'
15+
16+
export const validateInput = <Schema extends TSchema>(
17+
schema: Schema,
18+
mapInput?: (e: APIGatewayProxyEventV2) => unknown,
19+
): MiddlewareObj<
20+
APIGatewayProxyEventV2,
21+
APIGatewayProxyStructuredResultV2,
22+
Error,
23+
Context & ValidInput<Schema>
24+
> => {
25+
const v = validateWithTypeBox(schema)
26+
return {
27+
before: async (req) => {
28+
let reqBody = {}
29+
if (
30+
(req.event.headers?.['content-type'] ?? '').includes(
31+
'application/json',
32+
) &&
33+
parseInt(req.event.headers?.['content-length'] ?? '0', 10) > 0
34+
) {
35+
reqBody = tryAsJSON(req.event.body) ?? {}
36+
}
37+
const input = mapInput?.(req.event) ?? {
38+
...(req.event.pathParameters ?? {}),
39+
...(req.event.queryStringParameters ?? {}),
40+
...reqBody,
41+
}
42+
console.debug(`[validateInput]`, 'input', JSON.stringify(input))
43+
const maybeValidInput = v(input)
44+
if ('errors' in maybeValidInput) {
45+
console.debug(
46+
`[validateInput]`,
47+
`Input not valid`,
48+
JSON.stringify(maybeValidInput.errors),
49+
)
50+
return aProblem({
51+
title: 'Validation failed',
52+
status: HttpStatusCode.BAD_REQUEST,
53+
detail: formatTypeBoxErrors(maybeValidInput.errors),
54+
})
55+
}
56+
console.debug(`[validateInput]`, `Input valid`)
57+
req.context.validInput = maybeValidInput.value
58+
return undefined
59+
},
60+
}
61+
}
62+
63+
export type ValidInput<Schema extends TSchema> = {
64+
validInput: Static<Schema>
65+
}

0 commit comments

Comments
 (0)