前端转全栈 02:HTTP 与网络全链路——你和服务端对话的「普通话」

前端全栈tutorialhttp网络corsfetch

系列目录:本文是「前端转全栈:Next.js + Supabase 实战」系列的第 2 篇。上一篇我们建立了「请求 → 响应 → 存储」的心智模型,这一篇把链路最前端的 HTTP 拆开讲透。


前端写 fetch('/api/comments') 习惯了,但你要做全栈,必须知道这一行代码背后到底发生了什么——否则排错时你会像盲人摸象。


一、一次 HTTP 请求的完整旅程

你在浏览器点了一下
   │
   ▼
① 浏览器组装 HTTP 请求(方法/URL/headers/body)
   │  网络传输(TCP → TLS 加密 → IP 路由)
   ▼
② 服务端收到,路由到对应处理函数
   │  处理逻辑、读写数据库
   ▼
③ 服务端组装 HTTP 响应(状态码/headers/body)
   │  网络传回
   ▼
④ 浏览器解析响应,渲染 / 执行回调

关键点:HTTP 是「无状态」的文本协议。每次请求都是独立的,服务端默认不记得你是谁(这也是为什么需要 cookie/session 来「记住」你,见第 7 篇)。


二、请求的四个要素

一个 HTTP 请求由四部分组成:

POST /api/comments HTTP/1.1
Host: example.com
Content-Type: application/json
Authorization: Bearer <token>

{ "post_slug": "xxx", "content": "很棒的文章" }
  1. 方法(Method)GET(取数据)、POST(新建)、PUT/PATCH(更新)、DELETE(删除)。REST 风格靠方法表达「动作」。
  2. URL + 查询参数/api/comments?post_slug=xxx,查询参数适合过滤/分页。
  3. Headers:元数据。常见 Content-Type(body 格式)、Authorization(身份凭证)、Cookie(会话)。
  4. Body:请求体,POST/PUT 才需要,通常是 JSON。

对应到本站真实代码 src/app/api/comments/route.tsPOST:它从 request.json() 读 body,从 supabase.auth.getUser() 读身份(本质是从 cookie 解析出用户)。这就是「请求四要素」在服务端的落地。


三、状态码:服务端的「表情」

别只盯 200,学会读状态码能秒懂问题在哪:

| 范围 | 含义 | 常见 | |------|------|------| | 2xx | 成功 | 200 正常、201 已创建 | | 3xx | 重定向 | 301/302 跳转(登录回调常用,见第 7 篇) | | 4xx | 客户端错 | 400 参数错、401 未登录、403 无权限、404 找不到 | | 5xx | 服务端崩 | 500 代码报错、502 网关错 |

本站 route.ts 里就用了 400(缺参数)、401(未登录)、500(数据库报错)、201(创建成功)——用状态码准确告诉前端「发生了什么」,而不是所有情况都返回 200 + 一个 error 字段。


四、Headers 里最该懂的三个

1. Content-Type

告诉对方 body 是什么格式。application/json 是当下最主流。服务端要根据它决定怎么解析。

2. Cookie

客户端存身份的小纸条,每次请求自动带上。它是「无状态 HTTP」记住用户的机制之一。本站用 Supabase Auth,登录后会话 token 就存在 cookie 里,服务端 createClient()src/lib/supabase/server.ts)读取这些 cookie 还原用户。

3. CORS(跨域)

这是前端转全栈第一个必踩的坑。

浏览器页面对着 a.com,却请求 b.com/api  → 浏览器拦截!

浏览器出于安全,默认禁止「跨源」请求。解决办法是服务端在响应头加:

Access-Control-Allow-Origin: https://a.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type

实战提示:用 Next.js 同域部署时几乎不碰 CORS;只有「前端域名」和「API 域名」不同时才需要配。别一上来就写 Access-Control-Allow-Origin: *(允许所有源),那是安全隐患。


五、fetch 在服务端也一样用

你以为 fetch 只是浏览器 API?在 Next.js 服务端、Node 18+ 里,fetch 也是原生的:

// 服务端也能发请求
const res = await fetch("https://api.github.com/user", {
  headers: { Authorization: `Bearer ${token}` },
})
const user = await res.json()

区别只在:浏览器 fetch 会自动带 cookie、有 CORS 限制;服务端 fetch 没有这些浏览器安全策略,更「自由」也更需你自觉守规矩。


六、调试 HTTP 的三件套

| 工具 | 用途 | |------|------| | 浏览器 DevTools → Network | 看前端发出的请求/响应全貌 | | curl | 命令行直接打接口,排除前端干扰 | | Postman / Hoppscotch | 图形化组织请求、环境变量 |

curl 验证本站接口(需先有登录态,这里仅演示结构):

curl -X POST https://你的域名/api/comments \
  -H "Content-Type: application/json" \
  -d '{"post_slug":"xxx","content":"测试"}'

如果返回 401,说明身份没带对——立刻去查 cookie / token,而不是怀疑代码逻辑。


总结

  • HTTP 主线:请求(方法/URL/headers/body)→ 服务端处理 → 响应(状态码/headers/body)。
  • 状态码是服务端的「表情」,用对了排错快十倍。
  • Cookie 是「记住用户」的钥匙,CORS 是跨域的安全闸门。
  • 服务端也能用 fetch,但别拿浏览器那套安全假设套它。

下一篇我们走进「存储」环节——数据库与 SQL 入门,把数据真正落下来。


练习:打开浏览器 DevTools 的 Network 面板,刷新本博客任意一页,找到对 /api/comments/api/views 的请求,对照本文看它的方法、状态码、请求/响应头分别是什么。

Comments

Sign in to leave a comment.