Max-Forwards 限制一条请求最多还能走几跳。每过一跳减一,减到 0 就由那一跳直接回复。
它只在 TRACE 和 OPTIONS 上有定义。
条件请求讲完了,这一节换个主题:排查。想搞清楚请求经过了哪几台代理,就用这个字段。
一、为什么要限制跳数
代理配置出错时会形成环路:A 转发给 B,B 又转发给 A。
没有限制的话,一个请求会在里面转圈直到超时,期间白白消耗掉两端的资源。
Max-Forwards 就是给这种环路上了一道闸:每过一跳减一,减到 0 就停下。请求最多活这么多跳。
它比 Via 更主动:Via 只记录「经过了谁」,Max-Forwards 能主动叫停。
二、它还是个排查工具
想知道请求到底走了哪条链路,就用不同的值试:
Max-Forwards: 0 看第一跳是谁,1 看第二跳,2 看第三跳……每次加一,
看在哪一跳返回的 Via 项数会增加。
Demo 里链路是 A → B → C:发 3 一路走到 C,发 1 停在 B,发 0 停在 A。
输出里那串「收到 mf」「转发出去 mf」的轨迹,就是逐跳衰减的过程。
这个手法在排查「请求被谁吃了」时很有用——尤其是中间有几层你不认识的设备时。
三、为什么只在 TRACE 和 OPTIONS 上
因为这两个方法是「问情况」的,不改状态,所以让它们半路停住没有副作用。
如果允许用在 POST 上,那停在中间就等于「请求处理了一半」,语义上没法收场。
这也是这个字段现实中很少见的原因:TRACE 出于安全考虑在大多数服务器上被禁用了(它会原样回显请求,
可能泄露 Cookie),OPTIONS 也不常用。所以很多人做了多年 Web 都没见过它。
四、动手 Demo:三级代理,三种起始值
搭一条 A → B → C 的代理链,每一跳把 Max-Forwards 减一,减到 0 或到了链尾就自己回复。
客户端分别发 3、1、0。
mf = hd.get(u'max-forwards', u'')
if mf == u'0' or nxt is None:
# 减到 0,或者已经是最后一跳,就地回复
return reply(u'HTTP/1.1 200 OK', [(u'X-Hop', name)],
(u'%s 在这里停住' % name).encode(u'utf-8'))
nv = str(int(mf) - 1) if mf else u''
keep = [(u'Max-Forwards', nv)] if nv else []
return ask(nxt(), req(u'OPTIONS', u'*', u't.example', keep))
实跑输出:
--------------------------------------------------------------------
Max-Forwards:一条链最多还能走几跳
--------------------------------------------------------------------
链路:客户端 → A → B → C
【客户端发 Max-Forwards: 3】
A 收到 mf=3
A 转发出去,mf=2
B 收到 mf=2
B 转发出去,mf=1
C 收到 mf=1
C 就地回复(已经是最后一跳)
最终结果 HTTP/1.1 200 OK | C 在这里停住
【客户端发 Max-Forwards: 1】
A 收到 mf=1
A 转发出去,mf=0
B 收到 mf=0
B 就地回复(mf 减到 0)
最终结果 HTTP/1.1 200 OK | B 在这里停住
【客户端发 Max-Forwards: 0】
A 收到 mf=0
A 就地回复(mf 减到 0)
最终结果 HTTP/1.1 200 OK | A 在这里停住
它只在 `TRACE` 和 `OPTIONS` 上有定义,作用是「别无限转发」。
每过一跳减一,减到 0 就由那一跳直接回复,不再往下走。
实际用途是排查:想知道请求到底经过了哪几台代理,
就用不同的 Max-Forwards 值试,看在哪一跳停住。
所以输出里 3 一路走到了 C,1 停在 B,0 停在 A。
发 3:A 收到 3 转 2,B 收到 2 转 1,C 收到 1,但 C 是最后一跳,就地回复。 最终结果「C 在这里停住」。 发 1:A 收到 1 转 0,B 收到 0,直接停住。轨迹里写的是「B 就地回复(mf 减到 0)」。 发 0:A 收到 0,立刻停住。请求一步都没往外走。 三组轨迹能清楚看到衰减:每过一跳少一,减到 0 就有人接住。这就是「最多还能走几跳」的字面意思。
30 秒实验
- 把链加长到五跳,用
Max-Forwards: 3试,看停在哪。 - 故意造一个 A → B → A 的环,看没有这个字段时会怎样。
- 想一想:为什么
TRACE在多数生产服务器上是关掉的?
常见误区
- 「
Max-Forwards是所有方法都能用」——只在TRACE和OPTIONS上有定义。 - 「它是让服务端最多处理几次」——是限制转发跳数,不是处理次数。
- 「减到 0 会报错」——就地正常回复,不报错。
自测三问(点开对答案)
1. `Max-Forwards: 0` 的含义是什么? —— 不许再转发,由收到它的那一跳直接回复。 2. 它最实际的用途是什么? —— 排查请求经过了哪几台代理:用不同的值试,看在哪一跳停住。 3. 为什么它只定义在 `TRACE` 和 `OPTIONS` 上? —— 因为这两个方法不改状态,半路停住没有副作用。排查工具说完了。下面又是一个认证字段,但这次是给代理的。
- ☐ (本节完,下一节 6.4.15 Proxy-Authorization)