|
1 | | -declare const getUserTodos: ( |
2 | | - userId: string |
3 | | -) => Promise<Record<string, string>[]>; |
4 | | -declare const jwt: { |
5 | | - verify(token: string, secret: string): { sub: string; roles: string[] }; |
6 | | -}; |
| 1 | +declare const processOrder: ( |
| 2 | + orderId: string, |
| 3 | + correlationId: string |
| 4 | +) => Promise<{ status: string }>; |
7 | 5 |
|
8 | | -import { getStringFromEnv } from '@aws-lambda-powertools/commons/utils/env'; |
9 | | -import { |
10 | | - Router, |
11 | | - UnauthorizedError, |
12 | | -} from '@aws-lambda-powertools/event-handler/http'; |
| 6 | +import { randomUUID } from 'node:crypto'; |
| 7 | +import { Router } from '@aws-lambda-powertools/event-handler/http'; |
13 | 8 | import type { Middleware } from '@aws-lambda-powertools/event-handler/types'; |
14 | 9 | import { Logger } from '@aws-lambda-powertools/logger'; |
15 | 10 | import type { Context } from 'aws-lambda'; |
16 | 11 |
|
17 | | -const jwtSecret = getStringFromEnv({ |
18 | | - key: 'JWT_SECRET', |
19 | | - errorMessage: 'JWT_SECRET is not set', |
20 | | -}); |
| 12 | +type AppEnv = { |
| 13 | + store: { |
| 14 | + request: { correlationId: string }; |
| 15 | + }; |
| 16 | +}; |
21 | 17 |
|
22 | 18 | const logger = new Logger({}); |
23 | | -const app = new Router(); |
24 | | -const store: { userId: string; roles: string[] } = { userId: '', roles: [] }; |
| 19 | +const app = new Router<AppEnv>(); |
25 | 20 |
|
26 | 21 | // Factory function that returns middleware |
27 | | -const verifyToken = (options: { jwtSecret: string }): Middleware => { |
28 | | - return async ({ reqCtx: { req }, next }) => { |
29 | | - const auth = req.headers.get('Authorization'); |
30 | | - if (!auth || !auth.startsWith('Bearer ')) |
31 | | - throw new UnauthorizedError('Missing or invalid Authorization header'); |
32 | | - |
33 | | - const token = auth.slice(7); |
34 | | - try { |
35 | | - const payload = jwt.verify(token, options.jwtSecret); |
36 | | - store.userId = payload.sub; |
37 | | - store.roles = payload.roles; |
38 | | - } catch (error) { |
39 | | - logger.error('Token verification failed', { error }); |
40 | | - throw new UnauthorizedError('Invalid token'); |
41 | | - } |
| 22 | +const correlationId = (options: { header: string }): Middleware<AppEnv> => { |
| 23 | + return async ({ reqCtx, next }) => { |
| 24 | + const id = reqCtx.req.headers.get(options.header) ?? randomUUID(); |
| 25 | + |
| 26 | + reqCtx.set('correlationId', id); |
| 27 | + logger.appendKeys({ correlationId: id }); |
42 | 28 |
|
43 | 29 | await next(); |
44 | 30 | }; |
45 | 31 | }; |
46 | 32 |
|
47 | 33 | // Use custom middleware globally |
48 | | -app.use(verifyToken({ jwtSecret })); |
| 34 | +app.use(correlationId({ header: 'X-Correlation-Id' })); |
49 | 35 |
|
50 | | -app.post('/todos', async () => { |
51 | | - const { userId } = store; |
52 | | - const todos = await getUserTodos(userId); |
53 | | - return { todos }; |
| 36 | +app.post('/orders', async (reqCtx) => { |
| 37 | + const id = reqCtx.get('correlationId') ?? randomUUID(); |
| 38 | + const result = await processOrder('order-123', id); |
| 39 | + return { correlationId: id, ...result }; |
54 | 40 | }); |
55 | 41 |
|
56 | 42 | export const handler = async (event: unknown, context: Context) => |
|
0 commit comments