游客发表
打开浏览器开发者工具,网站切到Network面板,请求刷新页面。网站一排排请求冒出来,请求每个请求都带着一串键值对——那就是网站请求头。大多数人直接忽略它们,请求但如果你抓过包、网站调过API、请求或者被跨域问题折磨过,网站就知道这些东西不是请求摆设。
请求头是网站浏览器发给服务器的“自我介绍”。它告诉服务器:我是请求谁、我想要什么格式的网站数据、我从哪个页面跳过来的请求、我带了什么凭证。网站服务器拿到这些信息,决定给你返回什么、或者直接把你拒了。
HTTP/1.1开始,Host是唯一一个必须出现的请求头。一台服务器上可能跑着几十个网站,IP地址只有一个。你请求example.com,DNS把它解析到93.184.216.34,但服务器收到请求后得知道你要访问的是example.com还是api.example.com。Host就是干这个的。
我见过有人用IP直接访问虚拟主机,结果返回了默认站点的页面,就是因为Host头跟IP对不上。Nginx的server_name指令匹配的就是这个值。
User-Agent原本是浏览器用来表明身份的。Chrome发的是Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...,这一长串历史包袱来自九十年代的浏览器大战——网景叫Mozilla,IE也想蹭,于是大家都开始写Mozilla。后来就变成了一锅粥。
现在User-Agent主要用来做统计和兼容性判断。但很多爬虫会伪造UA,服务器也会检查UA来拦截异常流量。有个做电商的朋友跟我说,他们风控系统里UA匹配规则占了将近三成——某些抢购脚本用的UA一眼就能认出来。
Accept告诉服务器我能处理什么类型的内容,Accept-Encoding说我支持哪些压缩算法,Accept-Language表示语言偏好。这些头支持q值权重,比如:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 意思是HTML优先,XML次之,其他类型兜底。实际开发中,Accept-Encoding: gzip, deflate, br这个头最实用——服务器看到它才会压缩响应体。我调试过一个接口,响应JSON有2MB,开了gzip之后降到200KB出头,加载时间从三秒多降到不到一秒。
Cookie头是浏览器自动附带的,每次请求同域下的资源都会带上。服务器用Set-Cookie种下,浏览器存起来,下次请求再送回去。这一来一回就是HTTP无状态协议下维持会话的基础。
Authorization头则更直接,Basic认证、Bearer Token都走这里。跟Cookie不同,这个头需要前端手动设置。用fetch的时候忘了加credentials: 'include',跨域请求就不会带Cookie,这个坑我踩过不止一次。
Referer记录你从哪个页面跳过来的。图片防盗链就是靠它——服务器检查Referer是不是自己站点的域名,不是就返回403。不过Referer会泄露路径信息,有些浏览器支持Referrer-Policy来控制发送策略。
Origin头在跨域请求和POST请求中出现,只包含协议和域名,不带路径。CORS预检请求里,服务器就是根据Origin来决定是否返回Access-Control-Allow-Origin。
以前自定义头习惯加X-前缀,比如X-Requested-With: XMLHttpRequest。这个头是jQuery时代留下来的,用来标识Ajax请求。现在虽然不建议再用X-前缀(RFC 6648废除了这个约定),但很多老系统还在用。
实际工作中,自定义头常用于传递追踪ID、租户标识、灰度标记。我们后端就要求前端在每个请求里带X-Trace-Id,出了问题直接拿这个ID去日志系统里搜,比翻时间戳快得多。
请求头这东西,平时写业务代码感知不强,但一旦出问题——跨域被拦、缓存失效、认证失败——回头一看,十有八九是某个头没设对或者设多了。花半小时把常用请求头的含义过一遍,比出事后到处搜答案划算。
友情链接