不少人遇到过一个怪现象:直连时页面大小正常,走了代理之后拿到的东西总是对不上,下载进度条走到一半卡住,或者浏览器一直提示内容长度不对。翻到响应头那一层才发现,有几个字段在链路上被改过,而客户端还在按老值解析。
代理在回程时要处理的东西比去程多。它一边把上游的响应转给客户端,一边可能为了保持一致性动几个头字段。动的范围有讲究,动错了就会在客户端那一侧留下各种对不上的现象。
| 字段 | 常见处理 | 带来的影响 |
|---|---|---|
| 内容长度 | 按实际字节重算 | 与实际不符时客户端会截断或挂起 |
| 内容编码 | 解压后去掉该标记 | 客户端误判压缩状态,拿到乱码 |
| 实体校验值 | 一般保持原样 | 被改写后条件请求永远不命中 |
| 缓存时效 | 可能被追加年龄标记 | 命中判断与预期出现偏差 |
动的范围越大,出问题的面越广。
代理通常会动哪几个响应头
响应头里,内容长度是最常被重算的一项,因为代理可能压缩、可能合并分块,实际字节数已经跟上游给的不一样,不改就会前后矛盾。内容编码也常被动,上游发了压缩内容,代理解压后再转发,如果不把编码标记去掉,客户端会按压缩内容去解,得到一堆乱码。缓存相关的字段可能被追加年龄标记,用来标明这份内容在中间环节待了多久。
判断改写是否合理,看一条就够:客户端拿到的头与实际内容是否自洽。长度和编码这两项只要有一项对不上,表现会非常直接,很容易定位。
哪些响应头不该被随意改动
实体校验值与条件请求有关的字段最好保持原样。这类值的作用就是内容指纹,一旦被改写,客户端带着旧指纹来问有没有更新,服务端永远回一句变了,缓存也就永远命不中。缓存策略本身也不宜被中间环节改写,它表达的是内容提供方的意图,代理最多追加时间信息,不该替对方做主。
怎么确认改写确实发生了
- 直连与走代理各抓一次回程头,逐字段比对
- 重点看长度、编码、校验值、缓存这几类
- 发现不一致时,换一条链路复测确认是否链路造成
- 把差异记下来,作为以后选配置的依据
小结一句:回程头的处理应当尽量少动,必须动时要保证与实际内容自洽,校验值和缓存策略这两类留给内容提供方决定。
