前端转全栈 02:HTTP 与网络全链路——你和服务端对话的「普通话」
系列目录:本文是「前端转全栈: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": "很棒的文章" }
- 方法(Method):
GET(取数据)、POST(新建)、PUT/PATCH(更新)、DELETE(删除)。REST 风格靠方法表达「动作」。 - URL + 查询参数:
/api/comments?post_slug=xxx,查询参数适合过滤/分页。 - Headers:元数据。常见
Content-Type(body 格式)、Authorization(身份凭证)、Cookie(会话)。 - Body:请求体,POST/PUT 才需要,通常是 JSON。
对应到本站真实代码
src/app/api/comments/route.ts的POST:它从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.