# 模拟服务器 (/zh/docs/mocks)

模拟服务器运行在 Mac 的某个端口上，像 API 一样应答。前端、App 和测试可以在 API 还不存在时，或真实 API 停机时使用它。模拟服务器的应答有两个来源，可单独使用，也可一起使用：

- **手动创建的路由**：一个方法、一个路径，以及它应答的 JSON、XML 或文本。正文可以包含每次请求都会变化的示例数据（`{{$randomFullName}}`、`{{$randomEmail}}`），也可以引用请求的各个部分（`{{request.params.id}}`）。无需规范。参见[路由和示例数据](/docs/mocks/routes)。
- **OpenAPI 规范**：每个操作都用规范记录的响应、示例，或根据其 Schema 生成的正文来应答。违反规范的请求会得到一个说明原因的 `400`，因此客户端发送了错误内容时，模拟服务器也会告诉你。

如果应答需要代码或状态，模拟服务器还可以使用 [JavaScript 路由](/docs/mocks/scripted-routes)。

在边栏的模块切换器中选择**模拟服务器**，或按 <kbd>⌘</kbd><kbd>4</kbd>，即可打开该页面。

<Shot id="mocks-running" alt="一个正在运行的 Alpenglow 演示商店模拟服务器：顶部是它的地址，旁边有“在环境中使用”和“停止”；“设置”卡片显示它的规范；“路由”卡片有两个手动创建的路由；底部是已应答请求的日志，来自路由和规范" />

## 创建模拟服务器 [#creating-a-mock]

点按边栏**模拟服务器**标题中的 **+**，或使用空页面上的按钮：

- **新建模拟服务器**创建一个由路由构成的模拟服务器。它自带一个路由 `GET /users`，应答五个示例用户，因此你可以直接启动它，看看正文能做什么。可以修改它，或添加你自己的路由；参见[路由和示例数据](/docs/mocks/routes)。
- **规范的模拟服务器**（在 **+** 菜单中，或空页面上的**规范的模拟服务器**）为工作区中的一个规范创建模拟服务器，例如 **Alpenglow demo shop 的模拟服务器**。

新的模拟服务器使用从 `4010` 起的下一个空闲端口。它的设置和路由是工作区 `mocks` 文件夹中的一个文件，因此团队可以通过 Git 共享模拟服务器。

由路由构成的模拟服务器也可以根据规范提供服务，而规范的模拟服务器也可以有路由：**设置**卡片中的**根据规范提供服务**会添加一个规范，**更改** › **停止根据规范提供服务**则去掉它。

## 启动和停止 [#starting-and-stopping]

点按**开始**（<kbd>⌘</kbd><kbd>R</kbd>）。顶部的栏会显示模拟服务器的地址，例如 `http://127.0.0.1:4010`。如果模拟服务器提供服务的规范的服务器 URL 带有路径（`https://demo.echolot.dev/v1`），地址会以该路径结尾（`http://127.0.0.1:4010/v1`），模拟服务器也在该路径下应答；请求也可以省略该路径。地址旁边的拷贝按钮会拷贝地址。

在“终端”中试试：

```sh
curl http://127.0.0.1:4010/users
```

**停止**会停止它。边栏会显示哪些模拟服务器正在运行：一个绿点，以及规范标题旁的端口或路由数量（`Alpenglow demo shop · :4010`、`3 routes · stopped`）。右键点按模拟服务器可选择**开始**或**停止**以及**删除…**。删除前会先询问；设置文件会移到废纸篓，规范则保留。

模拟服务器在其工作区窗口打开期间运行。运行中的模拟服务器会在不停止的情况下采用对路由、规范和设置的更改。已被其他程序占用的端口无法使用：Echolot 会告知这一点，请另选一个端口。

### 向模拟服务器发送请求 [#sending-requests-to-the-mock]

- **路由**卡片中的**创建请求**会创建一个文件夹，其中的请求调用模拟服务器的路由，`{{baseUrl}}` 设为模拟服务器的地址。参见[从路由创建请求](/docs/mocks/routes#requests-from-routes)。
- **在环境中使用**（模拟服务器运行时）会创建一个名为 `Mock: <name>` 的环境，其 `{{baseUrl}}` 为模拟服务器的地址，并将其设为当前环境。以 `{{baseUrl}}` 开头的请求，例如[生成请求](/docs/specs#requests-that-follow-the-spec)根据规范生成的那些，随后会发往模拟服务器，直到你选择其他环境。参见[环境](/docs/workspaces/environments)。

## 设置 [#settings]

| 设置 | 作用 |
| --- | --- |
| **名称** | 模拟服务器在边栏中的名称。 |
| **规范** | 它提供服务的规范，或**无：只有其路由会应答**。**打开**会在“规范”页面中打开该规范；**根据规范提供服务**和**更改**用于选择规范或停止根据规范提供服务。 |
| **端口** | 它监听的端口，范围 1 到 65535。 |
| **应答网络上的其他设备** | 监听每个网络接口，便于从手机或容器中测试。关闭时：只有这台 Mac 能访问它。 |
| **延迟** | 每次应答前等待的毫秒数，最多 60,000，用于模拟较慢的 API。 |
| **失败率** | 被注入 `500` 的请求所占的百分比，用于试验客户端如何应对。 |
| **检查** | 有规范时：**拒绝违反规范的请求（返回 400 及原因）**。默认开启。 |

## 请求得到哪个响应 [#which-response-a-request-gets]

请求会交给下面第一个对其方法和路径有应答的来源：

1. 模拟服务器的 [JavaScript 路由](/docs/mocks/scripted-routes)。什么都不设置的路由会把请求传给下一个来源。
2. 它的[手动创建的路由](/docs/mocks/routes)。一个路由可以有多个响应；请求可以按名称或状态要求其中一个，请求上的规则会选择其他的，否则由路由的默认响应应答。
3. 规范的操作，见下文。

字面路径段优先于参数，因此无论是路由还是操作，`/pets/mine` 都会先于 `/pets/{id}` 被选中。

对于规范的某个操作，模拟服务器按以下顺序选择响应：

1. 请求所要求的：`Prefer: code=404, example=empty` 标头，或 Postman 的 `x-mock-response-code` 和 `x-mock-response-name` 标头。
2. 在**规范中的响应**卡片中为该操作选定的响应。
3. 该操作的第一个成功响应。

**规范中的响应**卡片以菜单列出每个操作：**第一个成功响应**，或某个已记录的状态；若某个状态有多个示例，则还可选择示例。这一选择随模拟服务器一起存储。

正文是响应中具名的示例（所要求的那个，或第一个）、它唯一的 `example`，否则是根据其 Schema 生成的正文：符合每个字段的类型、格式和名称的示例数据（格式为 `email` 的字段会得到电子邮件地址），在 Schema 的限制之内，每次请求都会重新生成。与路径参数同名的字段会重复该参数的值。如果规范记录了多种媒体类型，则由请求的 `Accept` 标头选择其一。已记录的标头和内容类型也会一并发送。`204`、`304` 以及对 `HEAD` 的应答没有正文。

模拟服务器给出的其他应答：

| 状态 | 何时 |
| --- | --- |
| `400` | 模拟服务器根据规范提供服务，检查已开启，且请求违反了规范：路径、查询、标头或 Cookie 参数缺失或类型错误、内容类型不对，或正文与其 JSON Schema 不符。正文会列出每个原因。 |
| `404` | 没有路由和操作拥有该路径。 |
| `405` | 路径存在，但不支持此方法。`Allow` 标头列出它接受的方法，路由和规范合并计算。 |
| `413` | 请求正文大于 32 MB。 |
| `500` | 注入的失败（参见**失败率**）。 |
| `501` | 该操作没有记录所要求状态的响应。 |

浏览器可能从另一个端口上的页面调用模拟服务器：它会应答预检请求并发送 CORS 标头。

## 日志 [#the-log]

页面底部列出所选模拟服务器应答过的请求，最新的在前：时间、状态、方法和路径、所用的响应（路由的响应名称、规范示例的名称，或正文由 Schema 生成时的 `generated`），以及耗时。问题显示在请求下方的行中：它在哪里违反了规范，或路由正文中无法生成的示例值。将指针停留在请求上，可查看响应正文、请求正文和内容类型；**拷贝响应**会拷贝正文。**清除**会清空日志。

如果 Apple 的设备端模型可用，**清除**旁边的按钮会为日志生成摘要。

## 把示例存入规范 [#saving-examples-into-the-spec]

对于规范的操作，规范是模拟服务器应答内容的唯一来源，因此你得到的真实响应要作为示例存储在规范中：在[历史记录](/docs/workspaces/history)中，右键点按遵循该规范的请求的某次交换，选择**存储为模拟示例…**。为它起个名字，例如 `two tents`，然后点按**存储**。

该响应会成为请求所遵循的规范中对应操作的响应的一个具名示例。可以在**规范中的响应**卡片中选择它，或用 `Prefer: example=two tents` 来要求它。

对于规范中没有的路径，或没有规范的模拟服务器，请创建一个[路由](/docs/mocks/routes)并粘贴正文。

## 在网络上共享 [#sharing-on-the-network]

打开**应答网络上的其他设备**，即可从手机、平板电脑或容器访问模拟服务器。其他设备使用你的 Mac 在本地网络上的地址，加上模拟服务器的端口。

第一次使用时，macOS 可能会询问是否允许 Echolot 查找本地网络上的设备并与其连接。请选择允许，否则其他设备无法访问模拟服务器。之后可以在**系统设置 › 隐私与安全性 › 本地网络**中更改这个选择。

网络上的任何人随后都可以调用该模拟服务器。不需要时请关闭共享。

## 通过命令行 [#from-the-command-line]

`echolot mock alpenglow.yaml` 提供规范文件的服务，`echolot mock -w <workspace> <mock>` 则提供工作区中某个模拟服务器的服务，带着它的设置和路由，无论有没有规范，适用于 CI 或容器。参见 [echolot mock](/docs/cli/mock)。[`echolot fake`](/docs/cli/fake) 根据相同的模板生成示例数据，用于测试夹具和种子数据。

智能体可以通过 Echolot 的 MCP 服务器启动模拟服务器并读取它们的日志；当**模拟服务器**工具集开启时，还可以创建模拟服务器、添加和更改路由、生成示例数据，并根据路由创建请求。参见[智能体](/docs/ai/agents)。
