☰
HTTP协议详解:从请求响应到状态码,前端开发者必懂的Web基础
2026/10/16 3:52:51 网站建设 项目流程

学 Web 开发到第 31 天,你大概率已经会写页面、会调接口、看得懂 JSON,但对 HTTP 协议恐怕还停留在“好像懂、又说不清”的状态。浏览器和服务器之间到底怎么对话?为什么接口明明返回了数据,页面上还报错?为什么 404 人人认识,301、304 很少有人说清楚?答案全藏在这个最基础也最容易被跳过的主题里。这篇 Day31 的记录,我不打算搬运教科书概念,而是顺着请求 / 响应、状态码、请求头这三条主线,把 HTTP 拆成你日常开发真正用得上、看得见的工具。无论你是前端新人,还是刚接触接口联调的后端实习生,读完再打开浏览器开发者工具,很多以前觉得“玄学”的报错,都能在协议层找到解释。

1. 学 Web 开发到第 31 天,为什么必须补 HTTP 协议

1.1 前面 30 天你其实一直在用 HTTP,只是没意识到

回想一下这一个月你做过的事:在地址栏输入网址打开页面,用 fetch 请求接口,提交表单,上传图片——这里面每一步都跑在 HTTP 之上。当你写下fetch('/api/users'),浏览器帮你构造的就是一个 HTTP 请求;你拿到的 data,本质上是服务器返回的 HTTP 响应被解析后的结果。只不过框架和浏览器把细节都藏起来了,所以你一直没“看见”它。

有个现象很典型:新人 debug 接口报错时,习惯把一行日志贴给后端同事,然后说“接口挂了”。后端同事反手一句“你怎么调的?返回什么状态码?请求头带了什么?”就直接问住。这不是后端态度差,而是双方在协议层面的词汇量不对等。状态码和请求头,就是前后端对话的“行话”,不懂行话,联调就是鸡同鸭讲。

1.2 HTTP 是什么:一套“双方都守规矩”的交流协议

HTTP 全称 HyperText Transfer Protocol,超文本传输协议。名字听着唬人,核心就两个词:约定、传输。它规定浏览器(客户端)和服务器之间交换消息要用什么格式、有哪些动作、成功失败怎么表达、附加信息放哪里。

用点餐类比:你进面馆,告诉服务员“一碗牛肉面,不要香菜”,这就是请求;服务员按单子把面端上来,这就是响应。要是你跟服务员说“给我来一段交响乐”,或者点一个菜单上根本不存在的菜,这顿饭就从源头谈崩了。HTTP 就是那本“双方都遵守的菜单”,谁不按规矩来,谁就沟通失败。

比较重要的是,HTTP 是一套基于文本的协议,尤其在 HTTP/1.1 里,你直接能看到请求报文和响应报文的完整文本。哪怕后来的 HTTP/2、HTTP/3 在传输层面做了很多优化,语义依然和 1.1 保持一致。所以对新手来说,把 HTTP/1.1 的消息格式看懂,就等于拿到了整个协议家族的钥匙。

2. 一次 HTTP 请求的完整生命周期:从回车到页面渲染

2.1 输入网址之后发生的第一件事不是发请求

我在带新人时经常问一个问题:“你在地址栏敲完网址按下回车,第一件事是什么?”有人回答“发请求”,这其实不对。发 HTTP 请求是整个流程里靠后的环节,前面还排着 DNS 解析和连接建立。

流程大致是这样:浏览器先解析 URL,判断这是一个网址还是一个搜索词;接着做 DNS 解析,把example.com这类域名翻译成服务器真正的 IP 地址,你可以理解成查电话簿;然后浏览器和服务器建立 TCP 连接,经过三次握手确认“你听得见我,我也听得见你”;如果走 HTTPS,还会多一步 TLS 握手,把后续通信加密;完成这些准备工作,真正的 HTTP 请求才被发送出去。

为什么要关心这些?因为很多“接口慢”的排查,第一步就是要分清慢在哪一段。如果解析 DNS 就花了 2 秒,HTTP 层怎么优化都没用;如果 HTTP 请求本身很快,但 TCP 连接建立很慢,那问题可能在网络环境而不是服务端。这份时间拆解,后面第 6 节用开发者工具能直接看到。

2.2 一个页面背后往往站着几十次请求

新手最容易忽略的事实:打开一个页面,不等于只发一次 HTTP 请求。浏览器拿到 HTML 之后,会继续解析文档,发现里面有link引用的 CSS、script引用的 JS、img引用的图片,然后为每一个资源单独发起一次 HTTP 请求。所以一个电商首页背后常常站着几十个请求,它们并行排队,然后陆续到达。

这个认知直接影响你 debug 白屏问题的思路。页面打不开,先别急着看后端接口,打开 Network 面板看看:HTML 文档本身有没有回来?CSS、JS 有没有因为路径写错返回 404?某个字体文件是不是跨域被拦了?很多时候页面白屏不是后端接口挂了,而是某个静态资源请求失败,浏览器渲染流程被中断了。

另外,请求数量也是性能指标里很重要的一项。HTTP/1.1 时代浏览器对同一个域名的并发连接数有限制,资源一多就得排队;于是才有了合并文件、雪碧图、把资源分散到多个域名这类老派优化手段。这些做法的核心动机,说到底都是为了“减少请求次数”。

2.3 无状态:“服务器记不住你”是什么意思

HTTP 有一个对新手非常反直觉的特点:它天生无状态。意思是,协议本身不要求服务器记住“上一次这个客户端做过什么”。每次请求都是独立事件,服务器收到一个请求,处理完,返回结果,这段对话就结束了。下次再来一个请求,服务器不会主动想起“哦,是你啊”。

那登录状态是怎么保持的?答案是把“你是谁”这个信息每次请求都带上。早期用 Cookie,服务器在响应头里用Set-Cookie给浏览器发一个小纸条,之后浏览器每次请求都自动把纸条放在Cookie请求头里带回去;后来流行 Token,客户端把凭证塞进Authorization请求头,每次请求重新提交。

理解了无状态,很多现象就有了答案:为什么每个需要鉴权的接口都要带 token?为什么有人说“别把登录状态只放在浏览器内存里,刷新就没了”?为什么服务器重启后用户的购物车还在——因为它存在数据库或缓存里,而不是某个 HTTP 连接里。HTTP 只是“运输员”,不负责“记忆”。

3. 请求部分逐一拆解:方法、URL、请求头、请求体的分工

3.1 请求行:方法、路径、协议版本

一个 HTTP 请求报文的第一行叫请求行,看起来像这样:

GET /api/users?page=2 HTTP/1.1

这一行只是三个部分的拼接:请求方法,空格,请求目标(路径加查询参数),再一个空格,最后是 HTTP 版本。含义分别是:你想做什么动作,你想对哪个资源做,你用的是哪个版本的话法。

URL 本身也值得拆一下。拿https://example.com:8080/api/users?page=2#top举例:https是协议,告诉浏览器接下来怎么通信;example.com是主机名,要解析成 IP;8080是端口,相当于大楼里的具体房间号(浏览器默认帮你填 80 或 443);/api/users是路径,表示资源在应用路由里的位置;?page=2是查询字符串,给请求带附加参数;最后的#top是片段标识符,它不会发给服务器,只给浏览器自己定位用。我在实际调试中常看到有人把#后面的内容发到后端去问 bug,其实服务器根本收不到那部分。

3.2 常用 HTTP 方法:GET、POST、PUT、DELETE、PATCH

方法表达了请求的“意图”,服务器根据意图决定怎么处理。我会用下面这张表过一遍核心方法:

方法语义是否带请求体幂等性典型场景
GET获取资源通常不带幂等拉取列表、详情
POST提交数据、创建资源带非幂等登录、下单、新增
PUT整体替换资源带幂等完整更新某条数据
PATCH局部更新资源带非幂等只改某个字段
DELETE删除资源通常不带幂等删一条记录
HEAD只要响应头,不要响应体不带幂等探测资源是否存在
OPTIONS查询服务器支持的能力不带幂等CORS 预检

这里有两个概念值得展开。第一个是 GET 和 POST 的核心区别不在于“安全”,而在于语义:GET 是去拿东西,不应该对数据产生副作用;POST 是去提交东西,允许产生新的数据。第二个是幂等——同一个请求执行一次和重复执行一百次,结果和状态应该一致。GET、PUT、DELETE 是幂等的,POST 不是。这决定了你写“重试逻辑”时敢不敢直接重发:POST 发重了可能重复下单,GET 则不用担心。

新手还有一个常见误区:觉得“GET 参数在 URL 里,POST 参数在 body 里,所以 POST 更安全”。这话对了一半——POST 的参数确实不会显示在 URL 和浏览器历史里,但如果不走 HTTPS,body 在传输过程中依然是明文。安全跟“放在哪”关系不大,跟“是否加密、服务端是否校验”关系才大。

3.3 请求头和请求体:什么时候需要、装什么

请求和响应除了第一行之外,剩下的结构是:一堆头部字段,然后一个空行,然后是可选的消息体。空行很关键,服务器就是靠它把头部和正文分开的。一个带体的 POST 请求完整报文大概长这样:

POST /api/login HTTP/1.1 Host: example.com Content-Type: application/json Content-Length: 43 Authorization: Bearer xxxxx {"username":"tom","password":"123456"}

请求体里装什么、用什么格式,由Content-Type请求头声明。最常见的三兄弟:application/json(JSON 文本)、application/x-www-form-urlencoded(表单,形如name=tom&age=18)、multipart/form-data(上传文件时用,因为要切分二进制和文本)。服务器收到请求,第一件事往往是看Content-Type,然后按对应的方式去解析 body。如果前端发的是 JSON,后台却按表单格式解析,接口就会报参数缺失或 400——这种联调事故,十次里有八次是Content-Type对不上。

我在前面加了一句Content-Length: 43,这是请求体按字节计算的长度,不是字符个数。中文一个字符在 UTF-8 下可能占三个字节,所以不能用“字符串长度”去填。平时浏览器和框架会自动帮你算好,但你手写报文、或者用一些底层网络工具调接口时,这个值算错会导致服务器读不满数据、请求一直挂起。这是协议层坑里的经典款,也是很多“接口偶尔成功偶尔超时”的隐藏元凶。

4. 状态码的五大家族与高频状态码实战解读

4.1 状态码为什么分五类:先看百位数字

响应的第一行叫状态行,长这样:

HTTP/1.1 200 OK

三个数字不用逐个拆,看百位就够了。第一位数字决定了状态码归属的家族:

百位家族一句话含义
1xx信息类服务器表示“我还在处理,你先等着”
2xx成功类请求收到并处理成功
3xx重定向类你要的东西不在这个地址,去别处找
4xx客户端错误问题出在发起方,参数、路径、权限
5xx服务器错误请求本身没毛病,服务器自己出状况了

我一直跟新人强调:看到状态码第一反应不是背数字,而是判断“锅在谁头上”。4xx 优先检查自己发出去的请求,5xx 优先检查服务端。这一条判断就把排查范围缩小了一半,比记住上百个状态码都管用。

4.2 高频状态码逐个看:从 2xx 到 5xx

排错时至少要把下面这些码的“长相和脾气”记熟:

状态码含义常见触发场景排查切入点
200OK请求成功不代表业务成功,看响应体里的 code
201CreatedPOST 创建资源成功常伴随 Location 头指向新资源
204No Content删除/更新成功但没有返回体前端别期待 body,容易解析报错
301Moved Permanently域名换新、HTTP 迁 HTTPS看 Location 头,浏览器会自动跟着走
302Found临时跳转,比如未登录跳登录页看 Location,确认跳转逻辑
304Not Modified协商缓存生效,资源没变配合 ETag / Last-Modified 理解
400Bad Request参数格式不对、body 解析失败检查请求体、Content-Type、参数字段
401Unauthorized没有凭证或凭证失效检查 Authorization 头、登录态
403Forbidden有凭证但没权限检查账号角色、权限配置
404Not Found路径不存在、资源缺失检查 URL 拼写、路由前缀、静态资源路径
405Method Not Allowed路径存在但方法不对检查接口到底定义的 GET 还是 POST
429Too Many Requests触发限流检查请求频率,别急着还责怪服务端
500Internal Server Error服务器代码异常看服务端日志,复现现场
502Bad Gateway上游服务没返回有效响应检查上游进程、网关配置
503Service Unavailable服务不可用、维护中大概率不是你能修的,联系运维

这里我要特别提醒 304。很多新手看到 304 觉得“怎么又失败了”,其实它不算错误,它的意思是“嘿,你缓存里的版本还能用,我就没重新给你传”。浏览器收到 304 会直接从本地缓存读资源,肉眼看到的效果是页面加载很快,Network 面板里那一行显示灰色的小字 304。你要是把它当错误,就误解了自己的缓存策略。

4.3 从状态码反推问题:一个排查案例

说一个我实际见过的案例,帮你看看这套思路怎么用。某同事的列表接口突然从 200 变成 500,前端第一反应是“后端代码写挂了”。我让他先用 curl 原样复现:

curl -i "https://api.example.com/api/users?page=2"

结果 curl 返回 200 而且数据完整。那问题就很有意思了——同样的参数,curl 好使,浏览器不好使,说明差别不在接口本身,而在“请求长什么样”。再对比浏览器开发者工具里的请求头和 curl 的请求头,发现浏览器多带了一些Accept字段和一堆 Cookie。问题很快定位:接口代码里有个分支,遇到某类Accept或者特定 Cookie 时走了异常路径,直接抛 500。后端修掉那个分支之后,浏览器立刻恢复正常。

这个案例想表达的是:状态码只是起点,它告诉你“问题大概在哪一层”,接下来要用 curl 做对照实验,把变量一个个隔离。先排除客户端因素(请求头、Cookie、缓存),再怀疑服务端逻辑。很多看起来“一会好一会坏”的接口问题,都是这样对比出来的——源头上是请求细节不一致,而不是服务器随机抽风。

5. 请求头和响应头:前端高频接触的头部字段清单

5.1 请求头:你发出去的信封上写了什么

如果报文正文是信的内容,头部就是信封上的地址和说明。每一个头部都是一行字段名: 值,比如Host: example.com。字段名大小写不敏感,host和Host一样,但习惯上写成首字母大写。头部字段几十上百个,前端日常真正高频接触的,我列一张单子:

请求头作用备注
Host告诉服务器目标域名和端口HTTP/1.1 起必带,浏览器自动填
User-Agent客户端身份标识服务端常用来统计和反爬,不建议伪造
Accept客户端希望收到的媒体类型比如application/json
Accept-Encoding客户端支持的压缩算法gzip,br,服务端据此决定压不压
Content-Type请求体格式JSON / 表单 / multipart,联调事故高发区
Authorization认证凭证常见Bearer <token>,别放 URL 里
Cookie浏览器自动携带的站点 Cookie前端 JS 一般不手动设置
Referer请求来源页面有的站点会校验
Origin请求来源的协议+域名+端口CORS 判断关键字段

举个例子,一次跨域请求在浏览器里看到的请求头大概长这样:

GET /api/profile HTTP/1.1 Host: api.example.com Origin: https://www.example.com Authorization: Bearer eyJhbGciOi... Accept: application/json

Origin和Referer很多人分不清。Origin只包含协议、域名、端口,而且跨域请求时基本都会带上;Referer包含完整来源路径,但可能因为隐私设置被省略。调试 CORS 问题时,优先看Origin。

5.2 响应头:服务器回信时附带的信息

响应头是服务器写给浏览器的“回执信息”,前端新手也要看得懂,因为很多运行时问题都藏在里面:

响应头作用前端关注点
Content-Type响应体的媒体类型和字符集类型不对会导致 JSON.parse 失败
Content-Length响应体字节数下载进度条实现会用到
Set-Cookie要求浏览器种下 Cookie是否 HttpOnly、SameSite、Secure
Location跳转目标地址配合 301/302 使用
Cache-Control强缓存策略max-age、no-cache、no-store
ETag/Last-Modified资源版本标识协商缓存,304 的判断依据
Access-Control-Allow-OriginCORS 允许的来源跨域调试重点盯它

一个典型的 JSON 响应头是这个样子:

HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Cache-Control: no-cache Access-Control-Allow-Origin: https://www.example.com

我见过很多新人拿着接口返回的字符串直接JSON.parse,结果报错,一查响应头发现Content-Type是text/html——大概率是服务器把错误页当成功响应返回了,或者中间的网关程序把响应体换成了 HTML。所以遇到解析失败,第一反应应该是看响应头的Content-Type,而不是盯着代码反复改 parse 方式。

5.3 Content-Type、Cookie、CORS:三个高频出事点

这三个头是前端联调路上的三座大山,每个都值得单独说两句。

Content-Type的坑在于“两边认知不一致”。前端用 fetch 默认不带Content-Type,某些接口调试工具会自动猜,后端按约定解析,哪边猜错了就是 400 或参数为 null。我建议写接口时养成习惯:发 JSON 就显式声明'Content-Type': 'application/json';传文件就交给FormData对象自动生成 multipart 边界,不要手动拼字符串。

Cookie的坑在于可见性。HttpOnly的 Cookie 前端 JS 读不到,登录相关排查时别光看document.cookie,要去开发者工具的 Application 面板看。SameSite会影响跨站请求是否携带 Cookie;Secure标记的 Cookie 在 http 环境下不会被设置,本地用 http + localhost 调试时很常见。我调过一晚上登录态,最后发现是 localhost 的 http 页面种不下SecureCookie。

CORS的坑在于“浏览器拦截的是响应,不是请求”。跨域时请求其实已经发到服务器了,服务器也处理了,只是浏览器发现响应头里没有允许跨域的字段,于是拒绝把结果交给前端 JS。所以 CORS 报错的第一反应不是“请求没到”,而是在 Network 里找到那条请求,看响应头有没有Access-Control-Allow-Origin。如果还伴随一条 OPTIONS 预检请求,说明你用了自定义请求头或非简单 Content-Type,服务器得先把预检放行。本地开发最常见的解决方案是让前端和接口走同一个域名,比如开发服务器把/api请求转发给后端服务,避开跨域问题。别一上来就想着关掉浏览器的安全策略——那只是治标。

6. 实弹演练:curl 和浏览器开发者工具里的 HTTP 真相

6.1 curl:命令行里亲手发一次请求

说了这么多,不如亲手发一次。curl 是命令行里最常用的 HTTP 客户端,几乎所有系统自带。它的好处是没有任何浏览器“滤镜”,请求头、响应头、状态码全部赤裸裸地给你看。

最简单的一条:

curl -i https://api.example.com/users

-i的意思是“把响应头也打印出来”。不加它,你只能看到响应体。加了你就能看到完整的HTTP/1.1 200 OK和一堆响应头。想看请求的全过程,用-v:

curl -v https://api.example.com/users

-v会打印连接建立过程、发出去的请求头、服务器返回的响应头。我第一次看-v的输出时有种“原来我之前一直隔着毛玻璃看 HTTP”的感觉。

想模拟一个 POST 请求也很简单:

curl -X POST https://api.example.com/api/login \ -H "Content-Type: application/json" \ -d '{"username":"tom","password":"123456"}'

-X指定方法,-H加请求头,-d塞请求体。这里有个细节:-d默认会自动把Content-Type改成application/x-www-form-urlencoded,所以如果你发 JSON,最好显式用-H声明,免得服务器按表单去解析。带查询参数的 GET 记得给整个 URL 加引号,因为&字符会被 shell 解释成后台执行符号,这是个让人哭笑不得的经典事故。

6.2 浏览器开发者工具 Network 面板怎么看

日常前端 debug,Network 面板是主战场。按 F12 打开开发者工具,切到 Network,刷新页面,每一行就是一个 HTTP 请求。点开任意一条,重点看四个部分:

第一是 Headers 里的 General 区,里面有最关键的三个信息:Request URL、Request Method、Status Code。有时候你调接口,接口地址看着没问题,但看一眼这里的 Request URL 才发现被拼接错了,比如少了环境前缀、多了个空格。

第二是同页面的 Request Headers 和 Response Headers,浏览器把发出去的请求头和收到的响应头原样列出来,比你猜一百遍都准。之前说的Content-Type、Authorization、Access-Control-Allow-Origin,都在这里一眼可见。

第三是 Payload(部分浏览器里叫 Request)和 Response 区。请求体长什么样、响应体长什么样,都简洁地展示出来。前端“明明传了参数,后端却说没收到”的纠纷,在这里看 Payload 最清楚。

第四是 Timing 区,也就是下一小节要说的耗时拆解。另外说一句,接口调试时记得在 Network 面板顶部勾上 “Disable cache” 选项。它能在页面刷新时强制禁用浏览器缓存,避免出现“我改了代码,页面却还是旧效果”这种干扰项。调完记得取消勾选,因为真实用户不会开着这个选项访问你的网站,你要验证的线上表现应当是默认缓存策略下的表现。

6.3 读懂一条请求瀑布流

点开一个请求的 Timing 标签,会看到一条时间瀑布,按顺序分成几段:

  • Queueing:请求在浏览器里排队等待发出。如果很多请求都在这个阶段,多半是到达了域名连接数上限。
  • Stalled:发送前的停顿,可能是因为等待可用连接。
  • DNS Lookup:域名解析耗时。
  • Initial connection:建立 TCP 连接(以及 TLS 握手)耗时。
  • Request sent:发送请求字节本身的时间,通常极短。
  • Waiting (TTFB):从请求发出到接收到第一个响应字节的时间。这一段最能反映服务器处理和网络往返的速度,接口慢主要慢在这里。
  • Content Download:接收响应体的耗时,和响应体大小、网络带宽直接相关。

看懂了这条瀑布,你就能判断“接口慢”到底是谁的锅。TTFB 居高不下,大概率是服务器处理慢或网络链路长;Content Download 很长,那就要看是不是响应体太大、压缩没开。我自己调过一张图片接口,后端总觉得“自己只需 10ms 就处理完了”,前端却显示 TTFB 要 2 秒,最后发现是跨地域的公网链路延迟,不是谁写错了代码。用数据说话,联调起来都更有底气。

7. 新手最容易误解的五个 HTTP 知识点

7.1 “POST 比 GET 更安全”其实是个误会

这个误区我在第 3 节已经埋了线,这里展开说。HTTP 方法本身不提供任何安全保证。GET 的参数在 URL 里,会出现在浏览器历史、服务器日志、链路中各种日志工具里,确实更容易泄露;POST 把参数放在 body,表面上看“藏”起来了,但如果不走 HTTPS,抓包拿到照样是明文。

真正决定安全的是三层东西:传输层的 HTTPS 加密;服务端对参数的校验和过滤;以及正确的鉴权授权。你前端为了“安全”把密码塞进自定义请求头里(比如X-Password: 123456),其实一点都不安全,反而会因为自定义头触发 CORS 预检,给联调添乱。密码、Token 这类敏感信息该走 body 就走 body,该用 HTTPS 就用 HTTPS,别自作聪明搞特殊位置。

7.2 状态码 200 不代表业务成功

这是业务系统里最容易被忽视的“协议与现实错位”。很多后端接口的约定是:HTTP 永远返回 200,真正的成功与否放在响应体 JSON 的code字段里。你收到 200 很开心,一解析发现{"code": 10001, "message": "商品库存不足"}——业务上这是失败,但 HTTP 层面确实成功了。

所以前端的校验逻辑不能只写if (response.ok),还要检查业务码。更规范的接口设计是 4xx/5xx 表示请求或系统错误,2xx 表示请求处理成功,业务失败用语义化的状态码或code字段表达。但现实是很多老系统就是“全 200”。遇到这种后端,别争论规范,老老实实把业务码的判断先写进拦截器,否则你迟早被“200 但业务失败”的接口坑一次。

7.3 刷新页面不等于重新下载所有资源

浏览器有自己的缓存体系。强缓存生效时,资源直接从本地读,Network 面板里那一行标注from disk cache或from memory cache,根本没有网络请求;协商缓存生效时,浏览器会发请求,但服务器发现资源没变,返回 304,浏览器从缓存里取内容。

这就导致一个经典现象:你改了 CSS,刷新页面,样式纹丝不动。因为浏览器还在使用旧缓存。解决办法很简单:发版时给静态资源加版本号或 hash(打包工具默认会做);调试时按 Ctrl+F5 强制刷新,或者在开发者工具勾选 “Disable cache”。这也是为什么很多人喜欢问“为什么线上改了文件,用户还是看不到最新版本”——答案十有八九是缓存,而不是部署没成功。排查“页面没更新”的 bug 时,先排除缓存再怀疑代码,能省下大把瞎猜的时间。

7.4 请求头不是前端能随便改的

浏览器出于安全和行为一致性,对一部分请求头做了限制,专业上叫 forbidden header names。比如Host、Content-Length、Cookie,你设了也发不出去;User-Agent也被浏览器控制。有些人以为在 fetch 里写'Cookie': 'xxx'就能改 Cookie,实际上浏览器直接无视这个设置,Cookie 的发送由浏览器自己管理。

另一个连带后果:跨域场景下,只要你在请求里加了自定义头(比如X-Token),或者Content-Type使用了非简单值,浏览器就会先发一条 OPTIONS 预检请求,询问服务器能不能带这些头。很多新人被这条自动多出来的 OPTIONS 请求吓到,以为后端写错了——其实这是浏览器在“提前问路”。遇到这种场景,该做的是让后端在响应头里声明允许的Access-Control-Allow-Headers,而不是在前端想办法绕过去。

7.5 HTTP 是应用层协议,不是传输层

最后一个概念层面的误区。TCP 负责把字节流可靠地从 A 传到 B,IP 负责寻址和路由,HTTP 站在它们之上,只关心“消息内容长什么样、语义是什么”。所以严格说,HTTP 不负责“传输”,它负责约定传输的内容和规则。

这个概念能帮你理清很多术语:比如“HTTP 连接”其实通常指 TCP 连接;HTTP/1.1 的 Keep-Alive 意思是“一条 TCP 连接可以复用多次请求”;HTTP/2 的“多路复用”是“一条 TCP 连接上可以同时跑多个请求”。如果不能区分 HTTP 和 TCP,你看到性能优化文章里的“连接数”“多路复用”就会一头雾水。WebSocket 也不是 HTTP,它是在 TCP 之上另一套协议,只是在握手阶段借用了 HTTP 的机制。把这个边界划清楚,再去看网络相关的资料,会顺畅很多。

我自己带过几批新人,观察到一个规律:那些 debug 接口时能精准说出“返回 401 说明凭证有问题”“带上了 Content-Type 为什么还报 400”“CORS 是浏览器拦了响应而不是请求”的,都是早期认真补过 HTTP 的人。这个协议不难,它反而像一层透明的玻璃,你之前没留意是正常的;一旦你把请求 / 响应、状态码、请求头这三条线走通,再回头看每天的接口联调,会有一种“世界突然清晰了”的感觉。第 31 天补 HTTP,是我觉得这个系列里性价比相当高的一天。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询