CYBERSWAT / 开发部自由练习 · v0.4.1

U04 · 一个短地址怎样找到原来的页面

v0.4 · 先修:手册 15、17–20。工作台。参考:freeCodeCamp 起始项目。本节独立用 Nest/PG 制作本地实验。

先不要访问任何外站。我们只保存 https://example.com/docs?q=one#top 这样的合成映射,并查看服务是否返回正确 Location。重定向是服务告诉客户端下一步去哪里,不是服务器替你下载目标页面。

动手路线:每一步都有文件和结果

先完成 统一启动与恢复手册 的首次准备。以下命令均在自己的练习根目录执行;原文中的 api/web/desktop 概念对应本节列出的现成文件,不需要猜测如何搭空项目。

  1. 打开 u04/starter/model.ts,按 createLink → resolveLink 的顺序逐个实现。下面第1节起解释规则;每完成一个函数就重跑样例/测试。
  2. 执行以下三条,分别核对样例、行为和类型。未完成的 TODO 应失败,全部实现后测试应为 fail 0:
node tools/try.mjs u04
node tools/check.mjs u04
npm run check
  1. 打开 runtime/src/u04.ts、runtime/prisma/schema.prisma,找到对自己规则函数的调用。先用一句话记录输入从哪里来、结果写到哪里;读不懂的语法回到本节先修对应章节。

  2. 先运行 node tools/lab.mjs db up,等待迁移完成。构建并启动自己的作品:

node tools/build-app.mjs u04
node tools/lab.mjs start u04
  1. 实际操作:页面创建一个新短码,然后运行接口验收。302 必须保留完整 Location,重复短码为409;两个并发创建只能成功一个。

在第二个终端运行 node tools/probe.mjs u04。脚本会添加合成数据并报告每组检查;不清空自己的数据。 首次通过后停止并重新启动服务,再运行 node tools/probe.mjs u04 --resume;数据库单元同时按统一手册重启数据库。

  1. 解释与再做一次:唯一约束写在哪里?把插入前查重当作唯一保护为什么会失败? 在自己的 LEARNING.md 先写答案,再选本节末尾的变式,列一个新失败例子后修改。保持原用例通过。仅跑通配套界面、没有完成规则与解释,记录为“参考演示已观察”,不记录为自己完成作品。

卡在规则时按“函数输入→分支条件→返回值→参考实现”逐级看提示;卡在运行时按 故障表 定位。若想单独观察参考成品,在构建命令后加 --reference;页面会明确标出参考演示。观察完再去掉该参数重建,继续自己的 starter。

1. 先处理一条映射

在 u04/starter/model.ts 完成 createLink。code 限 1–32 个英数字、下划线或连字符,不能重复;用 URL 解析地址,只接收 http/https,拒绝带用户名密码的 URL。用 url.href 保存规范化结果,不丢路径、查询或片段。

resolveLink 找到返回 URL,找不到返回 null。运行 node tools/try.mjs u04,再跑核心测试。输入字段形状由接口层检查,不能把 TS 参数声明当成网络校验。

2. 先写契约,再写路由

在 api/contract.md 写三行约定:POST /api/links 接收 {code,url},成功 201;GET /s/:code 找到返回 302 与 Location,不存在 404;重复 code 为 409,非法输入 400。选择由使用者指定短码,让冲突可重复观察;随机生成短码是后续变式。

配套 Nest 控制器在 runtime/src/u04.ts;逐行跟踪 body 校验、规则函数和 Prisma 插入。先用本节规则数组理解契约,再运行附带的真实数据库接口。你无需重新搭 Nest 空项目。

3. 直接检查重定向

建立 probe.mjs,按工作台的 fetch 写法先 POST 固定样例,再请求 /s/a1,设置 redirect: 'manual'。输出状态和 response.headers.get('location')。预期 302 与完整原 URL;不要自动跟随而把 example.com 的状态误认成短链接接口状态。

再 POST 同一 code,预期 409,旧映射不变;以不存在的 code 请求,预期 404。若 Nest 默认回 200,检查是否明确配置重定向状态;若 url 丢参数,检查是否错误地只保存 hostname。

4. 将唯一性放到数据库

按启动手册建立专用实验库,打开 runtime/prisma/schema.prisma 找到 Link 的 code 主键与 url 字段,再对照 migrations 中 SQL。配套服务已经接入数据库;自己的工作是实现规则、追踪入库路径、验证并发并完成独立变式。数据库唯一冲突映射409,其他故障不冒充重复码。

连续发送两个相同 code 的创建请求,最后只能有一条记录。只在插入前查“是否存在”不够,两个请求可能一起查到不存在;唯一约束才是最后一道保证。核心数组测试没有证明这个并发条件。

5. 重启与失败检查

停止 API 再启动,原短码应仍返回同一 Location;按手册重启实验数据库,再验一次。临时让连接配置指向不可用的本地端口,检查 API 不会返回假成功,日志能定位数据库连接阶段;恢复配置,不接触其他服务。

6. 完成条件与变式

检查 预期
带路径、查询、片段 完整保存和返回
javascript/file 协议、带凭据 URL 400,未落库
重复短码/同时创建 409 冲突可见,数据库仅一条
不存在短码 404
API/数据库重启 记录仍在

独立变式:增加“停用短码”,停用后返回你在契约中写明的状态,重新启用仍指向原网址;补迁移与回归。默认只绑定本机,不提供公开匿名短链服务。记录类型、核心、真实接口与持久化四项;缺数据库时停在接口阶段,不把数组存储记成完成。下一步 U05。