---
id: start-middleware
track: learn
product: start
locale: zh-CN
order: 11
revision: 2
sourceCheckedOn: "2026-08-03"
versionRange: "Start ^1"
verifiedAgainst: "@tanstack/react-start@1.168.34"
contentModel: 2
prerequisites:
  - "已理解 Server Function 与 Server Route"
sourceRefs:
  - "https://tanstack.com/start/latest/docs/framework/react/guide/middleware"
  - "https://tanstack.com/start/latest/docs/framework/react/guide/server-functions"
---

# 用 Middleware 组合请求边界

> 区分请求中间件与 Server Function 中间件，并用 next() 组合日志、上下文和安全检查。

**Outcome:** 能选择正确的中间件作用域，理解执行链，并避免把客户端传入 context 当作可信授权信息。

## 先选择作用域

请求中间件可以覆盖 SSR、Server Route 和 Server Function；type: 'function' 的中间件只包装 Server Function，并额外支持客户端阶段和数据验证。将规则放在最窄但完整的作用域，避免一次局部需求影响所有请求。

## 调用 next 才会继续执行

中间件可以在 next() 前执行逻辑、向下游追加 context，并在 next() 返回后检查结果。故意不调用 next() 表示提前结束；如果只是忘记调用，下游 handler 将永远不会运行。

> **Note:** 客户端发送的 context 必须在服务端验证；身份应从服务端可信来源重新建立。

File: `src/server/timing-middleware.ts`

```ts
import { createMiddleware } from '@tanstack/react-start'

export const timingMiddleware = createMiddleware({ type: 'function' })
  .server(async ({ next }) => {
    const startedAt = performance.now()
    const result = await next()
    console.info('server function ms', performance.now() - startedAt)
    return result
  })
```

## 实践与验证

### 完成检查点

请求级与函数级 Middleware 的范围明确，Context 按声明顺序传递。

### 动手练习

组合 requestId 与函数计时 Middleware，在处理器中读取 requestId 并输出结构化日志。

### 验证方法

并发发出两个请求；每个请求应有独立 ID，计时日志应覆盖完整处理链。

### 常见错误

- 忘记返回或等待 next()。
- 在模块级可变对象中保存请求数据。

## Official sources

- https://tanstack.com/start/latest/docs/framework/react/guide/middleware
- https://tanstack.com/start/latest/docs/framework/react/guide/server-functions
