首页 / 资讯中心 / 文章详情

HTTP面试基础体系:请求响应模型、报文结构与状态码详解

HTTP面试基础体系:请求响应模型、报文结构与状态码详解 ★ FEATURED ARTICLE
很多人准备面试的时候一看到HTTP就条件反射地去背三次握手四次挥手再背几个状态码觉得这块稳了。真到面试现场面试官随口问一句无状态到底是什么意思为什么有了Cookie还要Session报文里的空行到底干嘛用的不少人当场就卡壳。HTTP这块看着是八股实际上它是一整套理解Web的基础盘把基础概念、报文结构、请求方法、状态码和常见字段这几块串起来后面聊缓存、聊连接复用、聊安全、聊性能优化全都有落脚点。这篇就按面试官的实际考察路径把HTTP一这部分内容拆开讲什么是HTTP的请求响应模型报文长什么样八种请求方法各自解决什么问题状态码背后反映了服务端什么状态常见首部字段又该怎么读。内容偏基础和框架新手能照着理清体系有经验的可以直接拿来对照检查自己有没有漏掉细节。1. 先搞清楚HTTP这块面试到底在考什么1.1 从一道开放题看考察意图我见过不少面试场景面试官不太爱直接问什么是HTTP因为这种题人人都能背一句超文本传输协议。他们更常抛的是开放式问题比如你在浏览器地址栏敲一个网址回车到页面显示出来中间发生了什么这道题表面在问流程实际在考你能不能把HTTP放在整条链路里定位DNS解析拿地址、建立传输层连接、构造HTTP请求报文、服务端处理返回响应报文、浏览器解析渲染。你只要能把HTTP请求报文怎么构造、响应报文怎么回的讲清楚这道题就过了一大半。所以面试官真正想听的不是你复述定义而是你能不能把协议规范和实际行为对应起来。比如知道请求方法除了GET/POST还有哪些知道301和302在缓存行为上的区别知道Content-Type和Accept一个是告诉对方我发了什么、一个是告诉对方我能收什么。这些细节才是区分背过和懂了的地方。我在带新人的时候也常说HTTP这部分不需要你背名词需要你能在脑子里画出一问一答的完整画面。1.2 知识体系怎么搭才不散我给自己的学习路径是这么排的先理解模型请求-响应、客户端-服务端再理解载体报文结构再理解动作请求方法再理解反馈状态码最后理解元信息首部字段。这五层是层层递进的报文是请求方法的物理承载状态码是响应报文的第一个关键信息首部字段是补充说明。你把这条线捋顺后面无论聊缓存、聊跨域、聊长连接都能挂到这条主线上而不是一堆零散知识点。这也是为什么我建议面试前不要只翻状态码大全而是拿一个真实的抓包结果从请求行到消息体一行一行读下来。你自己读一遍报文比背十遍定义都管用。下一节就从模型和几个容易说错的词开始拆。2. 基本概念把无状态连接这些高频词说透2.1 请求-响应模型到底意味着什么HTTP是典型的客户端发起、服务端响应的模式通信永远由客户端主动发起服务端被动应答。这一条看着简单实际决定了很多设计服务端不会主动给你推消息所以要实现消息推送就得靠轮询、长轮询或者别的机制来模拟每次交互都是独立的请求-响应对服务端不会天然记住你上一次是谁。理解了被动应答这四个字你就能解释为什么早期的实时聊天在纯HTTP下体验很差。另外要注意HTTP是应用层协议它自己不负责把字节可靠地送到对面这件事交给了下层的传输层。所以规范里HTTP只定义报文长什么样、语义是什么不定义怎么保证不丢包。很多人面试时把可靠传输的机制说成是HTTP的能力这是个典型的混淆点面试官一听就知道你没分清层次。2.2 无状态是优点还是缺点HTTP是无状态协议这句话几乎人人会背但追问无状态带来什么问题、怎么解决才是重点。无状态的意思是每个请求之间相互独立服务端处理完一个请求后不会保留这次交互的上下文。好处很明显服务端不用为每个客户端维护会话内存请求可以随便分发到任意一台机器上处理横向扩展非常方便。这也是为什么早期的服务端能轻松扛住大量并发连接。坏处同样明显登录状态、购物车、多步表单这些需要记住上一步的场景纯无状态根本做不了。于是就引入了额外的状态管理手段比如客户端存一段标识、每次请求带上服务端凭这个标识去查对应的会话数据。这里的关键认知是状态并没有消失只是从服务端内存转移到了客户端携带标识 服务端按标识查询这套机制里。面试时能把这句话说出来比单纯背用Cookie和Session解决要有分量得多。2.3 连接这件事要说到点子上早期HTTP每个请求都要单独建立一次传输层连接用完就关这种方式在页面元素多的时候开销很大。后来的版本支持在一次连接上连续处理多个请求减少了反复建连的成本。这里我不展开具体版本差异只强调一个理解角度连接管理的演进本质是在简单和高效之间做权衡。短连接实现简单、服务端资源回收快但建连成本高长连接复用性好但要处理连接保持、超时、并发占用等问题。面试里常被追问长连接会不会一直占着资源答案是要配合超时和最大请求数等策略来回收否则空闲连接会白白消耗服务端句柄。这种机制 回收策略的答法比只说支持长连接要完整。很多八股答案只讲了一半你补上回收这一半区分度立刻就有了。2.4 URL、URI这些名词别混用这几个缩写是面试高频混淆点。简单说URI是统一资源标识符是一个大类URL是统一资源定位符是URI的一种强调位置能定位到资源在哪URN强调名字用名字标识资源但不依赖位置。日常我们说的网址基本都是URL。一个完整的URL拆开包括协议、主机、端口、路径、查询参数、片段标识这几部分片段标识通常只对客户端有意义不会随请求发给服务端这一点经常被拿来出题。我个人的记法是URI是身份证体系URL是住址URN是姓名。住址和姓名都属于身份证体系里的一种标识方式但住址能定位、姓名只是称呼。用这个类比去回答面试官一般会觉得你理解得比较到位。3. 报文结构一行一行读才叫真懂3.1 请求报文的三段式构成请求报文由请求行、首部字段、空行、消息体四部分组成。请求行里依次是请求方法、请求目标通常是路径加查询串、协议版本三者用空格分隔。比如一个典型的请求行方法在最前、路径在中间、版本在最后顺序不能乱。首部字段每行一个名称: 值的形式大小写不敏感。空行是一个单独的空行用来标记首部结束、消息体开始这个空行绝对不能省省了服务端就无法判断首部到哪结束。消息体是可选的GET请求通常没有消息体POST、PUT这类提交数据的请求才有。这里有个容易踩的细节有没有消息体、消息体多长很多时候要靠首部里的长度字段或者传输编码方式来界定不能靠读到连接关闭来判断否则长连接场景下会出问题。面试被问到服务端怎么知道请求体有多长答出长度字段和分块传输两种界定方式基本就够用了。3.2 响应报文的对应结构响应报文结构对称也是三段式只不过第一行换成了状态行协议版本、状态码、状态描述短语。状态码是三位数字描述短语是给人看的文字说明机器判断主要看数字。首部字段和空行规则与请求报文一致消息体就是服务端返回的实际内容可能是HTML、JSON、图片二进制等等。我抓包时习惯先看状态行确认结果类别再看首部里的内容类型和长度最后看消息体。这个顺序能快速定位问题如果状态码是4开头问题多半在请求本身如果是5开头问题在服务端处理如果状态码正常但页面显示乱码那大概率是内容类型或者字符集设置不对。3.3 首部字段怎么分类记首部字段数量多硬背不现实按用途分组记效率最高。大致可以分成几类请求相关的告诉服务端请求的上下文比如目标主机、客户端标识、接受的内容类型、响应相关的告诉客户端服务端的信息比如服务端软件、内容类型、缓存策略、通用相关的请求响应都能用比如日期、连接管理、实体相关的描述消息体本身比如长度、编码、语言。分组之后你会发现同一个词在不同位置出现语义往往是配套的。举个常见组合客户端用接受类型字段声明自己能收什么格式服务端用内容类型字段声明自己实际发的是什么格式。这两个字段一个在请求里、一个在响应里配合起来完成内容协商。你要是能讲清这对配合关系说明你不是孤立地背字段名。4. 请求方法八种方法各自解决什么问题4.1 方法清单与语义定位规范里定义的常用方法有GET、POST、PUT、DELETE、HEAD、OPTIONS、PATCH、TRACE等。GET用于获取资源是最常用的POST用于提交数据通常会引起服务端状态变化PUT用于整体替换资源PATCH用于局部修改DELETE用于删除HEAD和GET类似但只返回首部不要消息体常用来探测资源是否存在或获取元信息OPTIONS用于询问服务端支持哪些方法跨域预检请求用的就是它TRACE用于回显请求主要做诊断实际生产环境一般会关掉。这里的关键不是背清单而是理解每个方法的语义承诺。比如PUT强调幂等替换你重复提交同一个PUT结果应该和提交一次一样POST不承诺幂等重复提交可能产生多条记录。这个差别直接影响到接口设计和重试策略面试里聊到接口幂等性时经常从这里切入。4.2 GET和POST的对比要答出层次这是被问烂的题但答好不容易。我一般从几个层面拆语义层面GET是获取、POST是提交参数位置层面GET参数在地址里、POST参数在消息体里幂等层面GET是幂等的、POST不是缓存层面GET结果通常可被缓存、POST默认不缓存长度限制层面GET受地址长度约束、POST受服务端配置和传输方式约束安全层面GET参数会出现在地址栏和历史记录里不适合放敏感信息但这不代表POST就安全传输安全要靠加密层来保证。表格对比更直观对比维度GETPOST语义获取资源提交数据、可能改变状态参数位置地址查询串消息体幂等性幂等非幂等可缓存性通常可缓存默认不缓存长度约束受地址长度限制受服务端与传输配置限制敏感信息不适合相对好些但仍需加密我把这个表格当成自查清单用面试时按维度一条条说比想到哪说到哪要清楚得多。特别注意最后一行很多人会说POST比GET安全这句话是有问题的明文传输下两者都不安全区别只在于暴露位置不同真正的安全要靠传输层加密。4.3 幂等和安全的判断标准幂等指同一个请求执行一次和执行多次对服务端资源的影响相同。GET、HEAD、PUT、DELETE按语义都是幂等的POST不是。安全指请求本身不改变服务端资源状态GET、HEAD、OPTIONS、TRACE属于这一类POST、PUT、PATCH、DELETE不属于。这两个概念经常一起考注意它们是两个独立维度一个方法可以幂等但不安全比如DELETE也可以既不幂等也不安全比如POST。实际工作中这个知识点的价值在于重试设计网络抖动导致请求超时客户端要不要自动重试幂等的方法可以放心重试非幂等的方法重试就可能造成重复下单、重复扣款。所以很多接口会加一个请求唯一标识让服务端做去重这就是把非幂等操作改造成可安全重试的常见做法。4.4 方法误用的真实场景我见过一些项目把删除操作做成GET理由是方便在浏览器里点一下链接就删了。这种设计的问题很明显GET可能被浏览器预取、被爬虫抓取、被缓存一个不小心就把数据删了。还有人把查询接口做成POST理由是参数太长地址放不下这个理由本身可以理解但更规范的做法是评估是否真的需要那么多参数或者接受用POST但明确它不产生副作用并做好缓存控制。方法误用往往不是技术问题而是设计习惯问题。我的建议是接口设计阶段就把方法语义写在文档里评审时重点看这个方法会不会在重复调用下产生额外影响早发现早改比上线后再补要省事得多。5. 状态码三位数字背后的服务端状态5.1 五大类怎么快速定位状态码按首位数字分五类1开头是信息性表示请求已收到、继续处理2开头是成功表示请求被正常处理3开头是重定向表示需要进一步动作才能完成4开头是客户端错误表示请求本身有问题5开头是服务端错误表示服务端处理失败。记住这个分类看到一个陌生状态码也能大致判断问题方向这是排查的第一步。我排查线上问题时有个习惯先看状态码首位。4开头先检查请求参数、路径、权限5开头先看服务端日志、下游依赖、资源是否耗尽3开头看跳转链路是否形成循环。这个习惯能省掉大量盲目排查的时间。5.2 常见状态码逐个说清200表示成功是最常见的。201表示资源创建成功通常配合提交创建类请求。204表示成功但没有返回内容常用于删除成功。301是永久重定向302是临时重定向这两个的区别在于是否应该被缓存301告诉客户端以后都走新地址302说这次先走新地址、下次还按原地址来。307和308是在方法语义上更严格的重定向307临时、308永久它们保证重定向后请求方法和消息体不变而301/302在历史上有些客户端会把POST改成GET。这个细节面试常考能说出来说明你看过规范演进。304表示资源未修改配合缓存校验使用客户端可以继续用本地缓存节省带宽。400表示请求语法或参数有问题。401表示未认证需要先证明身份。403表示已认证但无权限。404表示资源不存在。405表示方法不被允许。408表示请求超时。429表示请求过于频繁被限流。500表示服务端内部错误。502表示网关从上游收到无效响应。503表示服务暂时不可用常见于过载或维护。504表示网关等待上游响应超时。502和504在有多层代理的架构里特别常见排查时要沿着链路往上游找。5.3 几组容易混淆的状态码401和403最容易混401是你还没证明你是谁403是我知道你是谁但你不能做这件事。301和302的区别前面说了核心是缓存语义。502和504的区别在于502是上游返回了看不懂的东西504是上游压根没在时限内回话。还有一组是200和204很多接口删除成功返回200带一段提示文字也有返回204不带内容的两种都行关键看接口约定是否统一。团队里最怕的是同一个项目里风格乱飞有的删除返回200、有的返回204前端处理起来就得写一堆分支。6. 常见首部字段读懂请求和响应的备注6.1 内容协商相关字段Accept声明客户端能接受的内容类型Accept-Encoding声明能接受的压缩编码Accept-Language声明语言偏好。服务端对应使用Content-Type声明实际内容类型Content-Encoding声明实际压缩方式Content-Language声明语言。这套字段完成的是客户端说我能收什么、服务端说我发了什么的协商过程。这里有个实操细节Content-Type里除了类型还常带字符集参数比如文本类型后面跟字符集声明。字符集写错是乱码的常见原因排查乱码时先看响应首部里的字符集和页面里声明的字符集是否一致不一致就容易出问题。6.2 缓存控制相关字段Cache-Control是缓存策略的核心字段常见取值有禁止缓存、必须重新校验、最大存活时间等。Expires是旧式的过期时间字段用绝对时间表示受客户端时钟影响所以现在更多用相对时间的最大存活时间。ETag是资源版本标识Last-Modified是资源最后修改时间这两个配合条件请求使用客户端带上版本标识或时间服务端判断没变化就返回304。缓存这块是面试深水区我这里只点到位强缓存靠最大存活时间和过期时间协商缓存靠版本标识和修改时间。两者的区别在于要不要发请求去问服务端。能把这个层次讲清楚基本就过关了。6.3 连接与其他常用字段Host指明请求的目标主机在共用同一入口地址托管多个站点时非常关键。Connection用于连接管理比如声明保持连接或关闭连接。Referer记录请求来源页面常用于统计和防盗链注意拼写是Referer而不是Referrer这是历史遗留的拼写错误面试偶尔会拿来考细节。User-Agent标识客户端信息。Cookie携带客户端保存的状态标识。Referer这个字段还涉及隐私问题很多场景会做裁剪或限制发送比如跨站请求时不带完整路径。这个点如果被问到可以从功能需求和隐私保护两个角度回答体现你考虑得比较全面。7. 常见问题与排查技巧实录7.1 面试高频追问怎么接被问到报文里的空行能不能省答案是绝对不能它是首部和消息体的分界。被问到GET请求能不能带消息体规范上没禁止但语义上不推荐很多服务端和中间层会忽略它所以别依赖这个行为。被问到状态码能不能自定义可以但应该避开规范已占用的码段且要保证语义自洽。被问到为什么有了Cookie还要Session可以从存储位置和数据量回答Cookie存在客户端、容量有限、每次请求都携带不适合放大量或敏感数据Session数据存在服务端客户端只存一个标识。两者是配合关系而不是替代关系。这类问题我建议先给结论再补原因面试官时间有限先听到结论他会顺着追问你就有机会展开。7.2 排查速查表现象可能原因排查方向页面乱码字符集声明不一致对比响应首部与页面内声明一直转圈最后失败请求超时或被限流看状态码是408还是429跳转死循环重定向链路成环逐跳记录地址变化缓存不生效缓存策略被覆盖检查缓存控制字段优先级跨域请求失败预检未通过检查方法、首部是否被允许上传大文件失败长度或超时限制核对服务端与中间层配置这张表是我自己排障时整理的实际用下来能覆盖大部分基础问题。特别提醒一点有多层代理的架构里同一个请求在不同层可能被改写排查时要逐层看日志别只盯最外层。7.3 几个踩过的坑第一个坑是把参数放在地址里传递敏感信息结果日志、历史记录、来源字段里全带着事后清理很麻烦。第二个坑是缓存策略配置冲突不同层各配各的最后实际生效的和预期的完全不一样调试花了很久才定位。第三个坑是重定向后方法被改提交类请求经过一次跳转变成了获取类请求服务端收到的参数全丢了。这些坑的共同点是单看某一条规范都没错组合起来就出问题。所以我的经验是涉及报文、缓存、重定向的改动一定要在真实链路上抓包验证别只在本地测。本地环境往往没有中间层很多问题复现不出来。8. 我个人的复习和作答建议最后分享一点我自己的体会。HTTP这部分内容我从来不按背题的方式准备而是拿一个真实请求从发出到返回逐行读报文、逐字段问这个是干嘛的、不写会怎样、写错了会怎样。用这种假设删掉它的方式过一遍记忆深度完全不一样。比如你试着删掉Host字段想想会怎样删掉长度字段想想会怎样删掉空行想想会怎样这些问题想通了面试时无论怎么变形提问都能接住。另外我建议把状态码和首部字段整理成自己的速查卡不要抄网上的大全而是只收自己实际见过、排查过的那部分每条后面写一句我在什么场景下遇到过。这样整理出来的卡片是有温度的面试时你能讲出具体场景而不是干巴巴的定义。基础概念、报文结构、请求方法、状态码、首部字段这五块吃透后面再去看缓存机制、连接管理、安全传输这些进阶内容会顺很多因为所有进阶话题最终都要落回报文和字段上。
阅读完成 · 觉得有帮助?
咨询建站