从浏览器点击“发送”,请求是怎么到服务器的?

专栏:AI 全栈开发|06

|----------------------------------------------------------------------------------------------------------------------------|
| 上一章我们把 frontend/ 和 backend/ 分开了。现在真正要看懂它们中间那条线:浏览器里的一次 fetch,为什么能跑到 FastAPI?这一篇只建立完整链路,不提前把 HTTP 报文、SSE、WebSocket、并发全部塞进来。 |

一、先从我们自己的 AI Chat 页面出发

假设页面已经打开,用户在输入框里写"你好",然后点击发送。前端代码里可能只有一句:

复制代码
const res = await fetch("https://api.example.com/api/chat", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ message: "你好" }),
});

看起来只是一个函数调用,但浏览器要真的把这段数据送到服务器,至少要解决几个问题:服务器在哪?怎么建立连接?数据用什么规则表达?服务器处理完以后,响应又怎么回来?

图 1 一行 fetch 背后的基础路线:找地址 → 建连接 → 发请求 → 服务端处理 → 收响应

二、第一步:浏览器先得知道"api.example.com 在哪"

代码里写的是域名 `api.example.com`,网络通信最终需要找到目标主机的网络地址。DNS 就是负责"名字 → 地址"这件事的系统。

浏览器/操作系统会优先利用已有缓存;没有可用结果时,才继续向 DNS 解析体系查询。

对小白来说,这一篇不需要背递归、迭代和权威 DNS 的完整过程。先记住:

域名不是服务器本身,它只是一个方便人记的名字;请求要发出去,系统必须先知道这个名字应该去哪里。

三、第二步:找到地址以后,还要建立一条可用的连接

如果使用常见的 HTTPS + HTTP/1.1 或 HTTP/2,浏览器通常会在 TCP 连接之上建立 TLS 加密连接。

TCP 负责可靠传输;TLS 负责加密通信并验证服务器身份。

但这里要纠正一种非常常见的"固定流程背诵":

|------------------------------------------------------------------------------------------------------------------|
| 不是每一次 fetch 都一定重新做 DNS → TCP → TLS。浏览器会缓存 DNS 结果,也会尽量复用已经建立的连接。现代 HTTP/3 还使用 QUIC,不再是传统的"TCP + 独立 TLS 握手"这套连接方式。 |

所以这篇真正要建立的是"职责地图",不是死记每次请求一定发生几次握手。

四、第三步:连接有了,HTTP 才开始表达"我想要什么"

现在浏览器终于可以发送 HTTP 请求。

我们的代码想表达的是:

• 目标:`/api/chat`

• 动作:POST

• 内容类型:JSON

• 正文:`{"message":"你好"}`

至于 Method、URL、Header、Body、Status Code 分别是什么,下一篇 07 会专门拆。这里先把 HTTP 理解成:

在已经可通信的连接上,客户端和服务器约定一套"请求什么、返回什么"的应用层规则。

五、第四步:请求到的"服务器"不一定直接就是 FastAPI

线上部署时,域名后面可能先经过 CDN、负载均衡器、云网关或 Nginx,再转发到真正的 FastAPI 进程。

但无论中间有多少层,最终都会把一个 HTTP 请求交给某个应用入口。FastAPI 根据路径和方法找到对应路由:

复制代码
from fastapi import FastAPI

app = FastAPI()

@app.post("/api/chat")
async def chat():
    return {"reply": "你好"}

这一刻才真正进入我们平时写的后端业务代码。

|-------------------------------------------------------------------------------------------|
| 所以"请求慢"不一定等于 FastAPI 代码慢。DNS、连接、TLS、网关、应用、下游模型等很多位置都可能耗时。后面做 Observability 时,会把这些耗时逐层串起来。 |

六、第五步:服务器返回响应,浏览器拿到以后做什么

FastAPI 返回的数据会沿着网络路径回到浏览器。

如果这是一个普通 JSON API,前端 JavaScript 会读取响应,再更新页面状态:

复制代码
const data = await res.json();
setReply(data.reply);

然后 React 根据新的 State 更新需要变化的 UI。

这和"第一次打开网页"并不完全一样。

图 2 打开网页会经历 HTML/CSS/JS 的加载与渲染;页面里的 API 请求通常只是拿数据,再由前端更新局部 UI

第一次访问网页时,浏览器拿到 HTML 后还要解析,并继续请求 CSS、JavaScript、图片等资源。页面脚本运行以后,点击"发送"通常只是再次发 API 请求,并不会重新加载整张页面。

七、把整条链路压成一张小白能记住的图

|--------------------|---------------|----------------|
| 阶段 | 它解决的问题 | 你以后会在哪里深入 |
| URL / DNS | 服务器在哪里 | 域名与部署专题 |
| 连接:TCP/TLS 或 QUIC | 怎么安全、可靠地通信 | 部署 / 性能专题 |
| HTTP | 请求和响应怎么表达 | 07~10 |
| Server / FastAPI | 请求由哪段后端代码处理 | 41~54 |
| Browser / Frontend | 数据回来后 UI 怎么变化 | 25~40 |
| Streaming | 结果还没结束时怎样持续返回 | 11~12、19、47~49 |

现在不需要掌握每一个协议细节。只要能指出"问题大概出在哪一层",F06 就达到目的了。

八、请求失败时,先别一句话都归结成"后端挂了"

图 3 常见报错落在不同层:先定位层,再处理具体问题

例如:

• 域名解析失败:FastAPI 甚至还没机会收到请求。

• connection refused:通常说明地址/端口可达性或服务监听有问题。

• 证书错误:连接卡在 TLS 层。

• 404 / 500:说明 HTTP 请求通常已经到达某个服务器,接下来才看路由或业务。

• 浏览器报跨域,而 curl 正常:请求可能到了服务器,但浏览器的同源/CORS 策略限制了前端读取响应。CORS 后面安全章节会专门讲。

• 响应已经拿到,页面却不变:要回到前端 State 和渲染逻辑检查。

九、用浏览器 DevTools 真正看一次

这篇最值得做的练习,不是自己手写 TCP 客户端,而是打开浏览器开发者工具的 Network 面板。

在聊天页面点击一次发送,然后点开 `/api/chat` 请求。你会看到 URL、Method、Status、Request/Response Headers、Payload、Timing 等信息。

现在先不用把每个字段看懂,只做一件事:

把"我代码里的一次 fetch"与"Network 面板里的一条真实请求"对应起来。

下一篇学习 HTTP 请求和响应时,我们就直接在这条真实请求上继续拆。

十、几个原稿里需要纠正的说法

• "一次请求固定经过 DNS → TCP → TLS"过于绝对。缓存和连接复用会跳过重复步骤;HTTP/3 的连接栈也不同。

• HTTP/2 并没有消除 TCP 层的队头阻塞;它主要解决 HTTP/1.1 层面多个请求在连接使用方式上的限制,而底层 TCP 丢包仍可能影响同连接的数据。

• "浏览器同域名最多 6 个连接"只能作为常见 HTTP/1.1 行为的近似印象,不应该当成所有浏览器和所有协议的固定标准。

• "HTTPS = 在 HTTP 和 TCP 之间插一层 TLS"适合解释 HTTP/1.1/2,但不能拿它概括 HTTP/3。

• 页面拿到 HTML 不等于页面已经可见可用;但 API 请求拿到 JSON 后,也不需要重新走完整页面解析流程。

十一、这一篇只记住 5 句话

• 域名先要被解析到可通信的目标地址。

• 浏览器需要一个可用的网络连接,HTTPS 还涉及安全连接。

• HTTP 负责表达请求和响应的应用层语义。

• 请求可能经过网关等中间层,最后才进入 FastAPI 路由。

• 响应回来以后,页面导航和 API 调用的处理方式不同;AI Chat 主要是前端拿数据并更新 UI。

十二、下一篇

下一篇 07《HTTP 请求和响应到底由什么组成?》会直接打开刚才 Network 面板里的那条 `/api/chat`:Method、URL、Header、Body、Status Code、Content-Type 分别是什么,它们为什么构成了前后端通信最基础的契约。

相关推荐
AI科技先锋报19 分钟前
如何为陪伴机器人搭建自然的对话式 AI?技术链路与声网方案怎么选?
人工智能·机器人·语音识别
新知图书22 分钟前
14.5 AI试驾预约系统的完整实现
人工智能·agent·ai agent·智能体
ZYJCSZKJ44 分钟前
基于大语言模型的地域实体语义增强:生成式引擎优化(GEO)中的多模态内容生成实践
android·人工智能·语言模型
北方的银狐-Zero1 小时前
OntoL本体产品—案例说明—穿透式投资监管案例UI设计说明
人工智能·本体论
爱分享的康康1 小时前
自动驾驶 HiL 测试选型|主流方案、供应商评估与仿真技术解析
人工智能·机器学习·自动驾驶
GIS数据转换器1 小时前
智慧林草“一张图“平台
java·大数据·服务器·前端·javascript·数据库·人工智能
HealthGeek1 小时前
临床预后研究:微创一站式瓣膜手术全周期诊疗在高危多瓣膜病变中的应用价值分析
人工智能
2401_885885041 小时前
国际语音php接口代码示例:PHP使用cURL快速调用语音发送API
android·开发语言·前端·人工智能·python·php·语音识别
leoZ2311 小时前
AI+前端提效-08 AI自动化文档:前端组件、接口、项目文档自动生成
前端·人工智能·深度学习·神经网络·目标检测·自然语言处理·自动化