> Discover all available pages from the documentation index: https://mastra.zisheng.pro/ko/llms.txt # 미들웨어 Mastra 서버는 API 전후에 맞춤형 미들웨어 기능을 실행할 수 있습니다. 경로 처리기가 호출됩니다. 이는 인증, 로깅, 요청별 컨텍스트 삽입 또는 CORS 헤더 추가. 미들웨어는[Hono](https://hono.dev) `Context` (`c`) 그리고`next`기능. 그것이 반환하는 경우`Response`요청이 단락되었습니다. 부름`next()`다음 미들웨어 또는 경로 처리기를 계속 처리합니다. ```typescript import { Mastra } from '@mastra/core' export const mastra = new Mastra({ server: { middleware: [ { handler: async (c, next) => { // Example: Add authentication check const authHeader = c.req.header('Authorization') if (!authHeader) { return new Response('Unauthorized', { status: 401 }) } await next() }, path: '/api/*', }, // Add a global request logger async (c, next) => { console.log(`${c.req.method} ${c.req.url}`) await next() }, ], }, }) ``` 단일 경로에 미들웨어를 연결하려면 `middleware` 옵션을 `registerApiRoute`에 전달합니다. ```typescript registerApiRoute('/my-custom-route', { method: 'GET', middleware: [ async (c, next) => { console.log(`${c.req.method} ${c.req.url}`) await next() }, ], handler: async c => { const mastra = c.get('mastra') return c.json({ message: 'Hello, world!' }) }, }) ``` ## 일반적인 예 ### 사용`RequestContext` 요청에서 정보를 추출하여 런타임 서버 미들웨어에서 `RequestContext`를 채울 수 있습니다. 이 예제에서는 응답이 사용자의 로캘과 일치하도록 Cloudflare `CF-IPCountry` 헤더를 기반으로 `temperature-unit`을 설정합니다. ```typescript import { Mastra } from '@mastra/core' import { RequestContext } from '@mastra/core/request-context' import { testWeatherAgent } from './agents/test-weather-agent' export const mastra = new Mastra({ agents: { testWeatherAgent }, server: { middleware: [ async (context, next) => { const country = context.req.header('CF-IPCountry') const requestContext = context.get('requestContext') requestContext.set('temperature-unit', country === 'US' ? 'fahrenheit' : 'celsius') await next() }, ], }, }) ``` ### 입증 ```typescript { handler: async (c, next) => { const authHeader = c.req.header('Authorization'); if (!authHeader || !authHeader.startsWith('Bearer ')) { return new Response('Unauthorized', { status: 401 }); } // Validate token here await next(); }, path: '/api/*', } ``` ### 승인(사용자 격리) 인증은 사용자가 누구인지 확인합니다. 승인은 액세스할 수 있는 항목을 제어합니다. 리소스 ID 범위 지정이 없으면 인증된 사용자는 ID를 추측하거나 조작하여 다른 사용자의 스레드에 액세스할 수 있습니다.`resourceId` parameter. Memory와 스레드의 범위를 인증된 사용자로 지정하는 가장 간단한 방법은 인증 구성의 `mapUserToResourceId` 콜백을 사용하는 것입니다. ```typescript import { Mastra } from '@mastra/core' export const mastra = new Mastra({ server: { auth: { authenticateToken: async token => { return verifyToken(token) // { id: 'user-123', orgId: 'org-456', ... } }, mapUserToResourceId: user => user.id, }, }, }) ``` 인증에 성공하면 인증된 사용자 객체와 함께 `mapUserToResourceId`가 호출됩니다. 반환된 값은 요청 컨텍스트의 `MASTRA_RESOURCE_ID_KEY`로 설정되며, 모든 서버 어댑터(Hono, Express, Next.js 등)에서 작동합니다. 리소스 ID는 반드시 그럴 필요는 없습니다.`user.id`. Common patterns: ```typescript // Org-scoped mapUserToResourceId: user => `${user.orgId}:${user.id}` // From a JWT claim mapUserToResourceId: user => user.tenantId // Composite key mapUserToResourceId: user => `${user.workspaceId}:${user.projectId}:${user.id}` ``` 리소스 ID가 설정되면 서버는 자동으로 다음을 수행합니다. - **스레드 목록을 필터링합니다.**사용자가 소유한 스레드만 반환하려면 - **스레드 액세스 유효성을 검사합니다.**다른 사용자의 스레드에 액세스하면 403을 반환합니다. - **스레드 생성을 강제합니다.**인증된 사용자의 ID를 사용하려면 - **메시지 작업 유효성을 검사합니다.**삭제를 포함하여 메시지가 소유한 스레드에 속하는지 확인 클라이언트가 `?resourceId=other-user-id`를 전달하더라도 인증에서 설정된 값이 우선합니다. 다른 사용자가 소유한 스레드나 메시지에 접근하려고 하면 403 오류가 반환됩니다. #### 고급: 미들웨어에서 리소스 ID 설정 데이터베이스에서 리소스 ID를 조회하는 경우처럼 더 복잡한 시나리오에서는 미들웨어에서 `MASTRA_RESOURCE_ID_KEY`를 직접 설정할 수 있습니다. ```typescript import { Mastra } from '@mastra/core' import { MASTRA_RESOURCE_ID_KEY } from '@mastra/core/request-context' import { getAuthenticatedUser } from '@mastra/server/auth' export const mastra = new Mastra({ server: { auth: { authenticateToken: async token => verifyToken(token), }, middleware: [ { path: '/api/*', handler: async (c, next) => { const token = c.req.header('Authorization') if (!token) { return c.json({ error: 'Unauthorized' }, 401) } const user = await getAuthenticatedUser<{ id: string }>({ mastra: c.get('mastra'), token, request: c.req.raw, }) const requestContext = c.get('requestContext') if (!user) { return c.json({ error: 'Unauthorized' }, 401) } requestContext.set(MASTRA_RESOURCE_ID_KEY, user.id) return next() }, }, ], }, }) ``` `server.middleware`는 Mastra의 경로별 인증 확인 전에 실행됩니다. 미들웨어에 인증된 사용자가 필요한 경우 `getAuthenticatedUser()`를 호출하여 기본 경로 인증 흐름을 변경하지 않고 구성된 인증 Provider에서 사용자를 확인하세요. #### 사용`MASTRA_THREAD_ID_KEY` 클라이언트가 제공한 스레드 ID를 재정의하도록 `MASTRA_THREAD_ID_KEY`를 설정할 수도 있습니다. ```typescript import { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY } from '@mastra/core/request-context' // Force operations to use a specific thread requestContext.set(MASTRA_THREAD_ID_KEY, validatedThreadId) ``` 이는 다른 수단을 통해 검증한 특정 스레드로 작업을 제한하려는 경우에 유용합니다. ### CORS 지원 ```typescript { handler: async (c, next) => { c.header('Access-Control-Allow-Origin', '*'); c.header( 'Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS', ); c.header( 'Access-Control-Allow-Headers', 'Content-Type, Authorization', ); if (c.req.method === 'OPTIONS') { return new Response(null, { status: 204 }); } await next(); }, } ``` ### 요청 로깅 ```typescript { handler: async (c, next) => { const start = Date.now(); await next(); const duration = Date.now() - start; console.log(`${c.req.method} ${c.req.url} - ${duration}ms`); }, } ``` # 관련된 - [요청 컨텍스트](https://mastra.zisheng.pro/ko/docs/server/request-context) - [예약된 키](https://mastra.zisheng.pro/ko/docs/server/request-context)