首页
/ RealWorld 前端 API 接入指南:本地后端与 Demo API 两种测试方案及内容可见性限制

RealWorld 前端 API 接入指南:本地后端与 Demo API 两种测试方案及内容可见性限制

2026-09-04 16:50:35作者:毕习沙Eudora

本文围绕 RealWorld 前端实现的 API 测试展开:讲解如何把前端对接到官方后端(本地运行的 Nitro + Prisma + Zod 实现)或官方托管的 Demo API 上完成联调,并结合仓库中的 E2E 测试代码与 API 测试套件,说明 API 地址的配置方式、认证请求的实际格式,以及公共 API 自 2021 年起引入的用户内容可见性限制及其对测试设计的影响。

为什么前端实现需要一个统一的 API 契约

RealWorld 的核心设计是"同一个 Medium 克隆应用可以用任意前端框架 + 任意后端实现组合",前提是双方都遵守同一份 API 规范。仓库中的 OpenAPI 定义 就是这份契约的机器可读版本,其中 servers 字段直接指向官方 Demo API:

servers:
  - url: https://api.realworld.show/api

这意味着前端开发者不需要先写完一个后端才能开始开发——文档 docs/src/content/docs/specifications/frontend/api.md 给出了两条明确的联调路径:

  1. 本地运行官方后端实现,适合需要调试请求细节、断点排错的场景;
  2. 直接指向官方托管的 Demo API,零部署成本,适合快速启动一个纯前端实现。

两条路径共用同一套端点与请求/响应结构,因此前端代码在两者之间切换时通常只需改一个基地址配置。

方案一:本地运行官方后端实现

官方后端实现是开源的,技术栈为 Nitro + Prisma + Zod(TypeScript)。它是通过完整 API 规范测试套件的 spec-compliant backend 之一,仓库 README 在 "Spec-compliant backends" 一节中列出了它以及 Django Ninja 两个通过全部 API 测试的后端。

本地跑起来之后,默认监听 localhost:3000,这一点可以从仓库中 API 测试工具链的默认配置得到印证:Bruno 本地环境变量 定义如下

vars {
  host: http://localhost:3000
}

Hurl 测试脚本HOST 变量的默认值是 http://localhost:8000(Django 实现的默认端口),可用环境变量覆盖:

HOST=http://localhost:3000/api ./run-api-tests-hurl.sh

也就是说,本地联调的完整闭环是:启动官方后端 → 前端把 API 基地址指到 http://localhost:3000/api → 用仓库内置的 Hurl / Bruno 套件(见 specs/api/README.md)对后端本身做一次合规性验证。其中 Hurl 文件是 source of truth,Bruno 集合由 make bruno-generate 生成并经 make bruno-check 保持同步。

方案二:直接指向官方 Demo API

对于不想维护后端的纯前端实现,官方提供公共托管 API,接入方式就一行配置:

https://api.realworld.show/api

仓库的 E2E 测试正是以它作为默认后端。specs/e2e/helpers/config.ts 中定义:

export const API_BASE = process.env.API_BASE || 'https://api.realworld.show/api';

默认就是 Demo API,可通过 API_BASE 环境变量覆盖。例如联调本地后端时:

API_BASE=http://localhost:3000/api npx playwright test

Demo API 的使用边界

该 API 免费公开,但仅允许 RealWorld 场景使用:它不允许脱离前端应用被单独消费(即不能作为通用 API 服务被任意第三方直接调用)。同时,它无需 API Key,并内置了一批 demo 账号供测试跨用户场景使用。E2E 配置注释中明确提到,跨用户测试会复用 demo 后端预置的种子用户(如 johndoe):

seeded demo users (e.g. johndoe) for cross-user scenarios —— 摘自 specs/e2e/helpers/config.ts 头部注释

仓库 E2E 测试对 Demo API 的实际调用方式

以下三个代码事实展示了前端实现对接该 API 时的标准模式:

1. 注册与登录返回 JWT —— specs/e2e/helpers/api.ts 中:

export async function registerUserViaAPI(request: APIRequestContext, user: UserCredentials): Promise<string> {
  const response = await request.post(`${API_BASE}/users`, {
    data: { user: { username: user.username, email: user.email, password: user.password } },
  });
  ...
  return data.user.token;
}

请求体包裹在 user 字段下,响应中的 user.token 就是后续认证的 JWT。

2. 认证头格式为 Token <jwt> —— 创建文章时的写法:

headers: { Authorization: `Token ${token}` }

注意这不是 Bearer,而是 Token 前缀,这是 Conduit 风格 API 的约定,前端实现必须照此设置请求头。

3. 健康检查直接探测 API 可达性 —— specs/e2e/health.spec.ts 中有一条测试用例对 https://api.realworld.show/api/tags 发起 GET 请求并断言 response.ok(),且该用例通过 EXTERNAL_API 能力开关门控(见下文测试模式小节)。

测试模式(TEST_MODE)与 API 假设的关系

Demo API 的可用性还取决于前端实现的架构形态。specs/e2e/helpers/config.ts 定义了三种测试模式与两个正交的能力标志:

TEST_MODE 形态 BROWSER_API EXTERNAL_API
spa(默认) 浏览器直接调 REST API,JWT 存客户端 true true
ssr 服务端代为调用外部 REST API(如 SvelteKit/Next.js SSR,httpOnly cookie 认证) false true
fullstack 前端自带完整前后端栈 false false

这对应到 Demo API 使用上的差异:

  • spa 模式下浏览器自身发起 API 调用并持有 JWT,测试可以拦截 API 流量(page.route())、向 localStorage 注入 token,并等待浏览器侧的 API 响应;
  • ssr 模式下浏览器侧没有 API 流量可拦截,但测试运行器本身仍可直连 Demo API 做快速数据准备,种子 demo 用户同样可用;
  • fullstack 模式下不假设存在独立可达的 API,一切通过 UI 驱动,跨用户场景自建账号,因此 E2E 套件中依赖外部 API 的用例(如 health.spec.ts 中的 /tags 探测)会被自动跳过。

resolveMode() 还支持旧的 API_MODE 布尔变量做向后兼容(API_MODE=false 等价 fullstack,否则 spa)。对只想"前端 + Demo API"跑通联调的读者,保持默认的 spa 模式即可。

API 限制:用户内容可见性规则

文档特别强调的一条限制(自 2021 年引入,目的是避免公共 API 需要内容审核):

用户内容的可见性被限制:

  • 未登录用户只能看到 demo 账号创建的内容;
  • 已登录用户只能看到自己的内容和 demo 账号创建的内容。

README 用同样的语义复述了这一规则:

no API keys required — demo accounts are provided, and real accounts can't see each other

这条限制对前端开发和测试有三个直接影响:

  1. 首页/文章流断言:未登录状态下打开首页,列表内容应当只包含 demo 账号(如 johndoe 等种子用户)的文章;任何"看到其他真实注册用户文章"的断言在 Demo API 上必然失败,这并非 bug。
  2. Feed 场景设计:关注流测试必须基于 demo 账号或自注册账号构建。仓库的 feed 测试(specs/api/bruno/feed/ 系列,如 03-feed-for-new-user-returns-empty.bru)正是先注册新用户验证空 feed、再关注、发文章、最后断言 feed 内容的模式,这套模式在本地后端与 Demo API 上均可复现。
  3. 跨用户隔离验证:注册两个真实用户 A/B 后,A 发布的文章对 B 不可见(除非 B 通过 feed 关注了 A)。仓库的授权错误测试 specs/api/bruno/errors-authorization/ 覆盖了这类"用户 B 不能删除/更新 A 的内容"(403)场景。

因此,如果你的前端测试用例依赖"用户之间互相可见"这一假设,要么改用本地后端(无此可见性限制,行为更接近真实部署),要么将用例重构为"自见 + demo 账号"的可见性模型。

延伸阅读与仓库内相关资源

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
903
1.82 K
docsdocs
暂无描述
Markdown
888
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.51 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341