Skip to content

Commit 9e84323

Browse files
authored
docs(event-handler): update custom middleware example to use Store API (#5145)
1 parent 705dfae commit 9e84323

2 files changed

Lines changed: 29 additions & 42 deletions

File tree

docs/features/event-handler/http.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -530,13 +530,14 @@ accepts configuration options and returns a middleware function.
530530

531531
=== "index.ts"
532532

533-
```ts hl_lines="20-21 36 41"
534-
--8<-- "examples/snippets/event-handler/http/advanced_mw_custom_middleware.ts:8"
533+
```ts hl_lines="23"
534+
--8<-- "examples/snippets/event-handler/http/advanced_mw_custom_middleware.ts:7"
535535
```
536536

537-
In this example we have a middleware that acts only in the post-processing stage as all
538-
the logic occurs after the `next` function has been called. This is so as to ensure that
539-
the handler has run and we have access to request body.
537+
In this example we have a middleware that extracts a correlation ID from a request header
538+
or generates a new one if absent. It stores the ID in the request context using
539+
`reqCtx.set()` so that route handlers can retrieve it with `reqCtx.get()`. This ensures
540+
each invocation has its own isolated state without relying on module-level variables.
540541

541542
#### Avoiding destructuring pitfalls
542543

examples/snippets/event-handler/http/advanced_mw_custom_middleware.ts

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,42 @@
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 }>;
75

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';
138
import type { Middleware } from '@aws-lambda-powertools/event-handler/types';
149
import { Logger } from '@aws-lambda-powertools/logger';
1510
import type { Context } from 'aws-lambda';
1611

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+
};
2117

2218
const logger = new Logger({});
23-
const app = new Router();
24-
const store: { userId: string; roles: string[] } = { userId: '', roles: [] };
19+
const app = new Router<AppEnv>();
2520

2621
// 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 });
4228

4329
await next();
4430
};
4531
};
4632

4733
// Use custom middleware globally
48-
app.use(verifyToken({ jwtSecret }));
34+
app.use(correlationId({ header: 'X-Correlation-Id' }));
4935

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 };
5440
});
5541

5642
export const handler = async (event: unknown, context: Context) =>

0 commit comments

Comments
 (0)