Allow 列出这个资源支持哪些方法。
它最常出现在 405 和 OPTIONS 的响应里,作用是让客户端知道「换个方法再试」。
响应首部的九个讲完了,从这一节开始是实体首部。 第一个却是关于「方法」的——它描述的不是正文,而是这个地址能接受什么动作。
一、它回答的是「你能怎么动我」
一个资源支持 GET 和 HEAD,不一定支持 DELETE。Allow: GET, HEAD, OPTIONS 就是把这句话说清楚。
值是一串方法名,逗号分隔,全是大写。
OPTIONS 是专门用来问这件事的:客户端发 OPTIONS /doc,服务端回 204 加一行 Allow,
正文为空。这是标准的探测手段,跨域预检请求(CORS preflight)就是它的变种。
注意它和 Access-Control-Allow-Methods 不是一回事:后者是 CORS 专用的,前者是 HTTP 本身的。
两者经常一起出现在预检响应里。
二、405 里必须带
用了一个不支持的方法,服务端回 405 Method Not Allowed,并且必须在响应里带 Allow。
这条是规范里的硬要求。
Demo 里跑了对照:不带 Allow 的 405 是 133 字节,带的是 160 字节,差 27 字节。
这 27 字节买的不是「礼貌」,是可恢复性。没有它,客户端只知道「我错了」,不知道该改成哪个方法;
有了它,客户端能自己换一条路重试,不用人来猜。
三、三个常见误解
第一,Allow 不是「服务器支持的全部方法」,而是「这一个资源支持的方法」。
同一台服务器上,/a 可能只允许 GET,/b 允许 GET 和 PUT。
第二,Allow 不保证方法一定成功。
它说的是「这个动作在语义上被接受」,能不能做成还要看权限、看状态——那是 403 和 409 的事。
第三,HEAD 要不要列?如果支持 GET,按规范就该支持 HEAD。很多框架自动带上,自己实现的时候别忘了。
四、动手 Demo:OPTIONS 问一次,DELETE 撞一次
服务端只认 GET、HEAD、OPTIONS 三个方法。
先用 OPTIONS 问它都会什么,再用 DELETE 去撞,分别看带 Allow 和不带 Allow 的 405 差在哪。
SUPPORT = (u'GET', u'HEAD', u'OPTIONS')
def fn(raw, st):
meth = raw.split(b' ')[0].decode('latin-1')
if meth == u'OPTIONS':
return X.reply(u'HTTP/1.1 204 No Content',
[(u'Allow', u', '.join(SUPPORT))], b'')
if meth not in SUPPORT:
hd = [(u'Content-Type', u'text/plain; charset=utf-8')]
if with_allow:
hd.insert(0, (u'Allow', u', '.join(SUPPORT)))
return X.reply(u'HTTP/1.1 405 Method Not Allowed', hd, MSG)
return X.reply(u'HTTP/1.1 200 OK', [], TEXT)
实跑输出:
--------------------------------------------------------------------
Allow:这个资源认哪几个方法
--------------------------------------------------------------------
先用 OPTIONS 问一句「你都会什么」:
HTTP/1.1 204 No Content
Allow: GET, HEAD, OPTIONS
然后故意用 DELETE 去撞,看 405 里带不带 Allow:
带 Allow = False → HTTP/1.1 405 Method Not Allowed 响应 133 字节 Allow:(没有)
带 Allow = True → HTTP/1.1 405 Method Not Allowed 响应 160 字节 Allow:GET, HEAD, OPTIONS
两组的差别只有 27 字节(133 对 160),但后果不是「省几个字节」:
没有 Allow 的 405 只是在说「你错了」,客户端不知道该改成哪个方法;
带上 Allow,客户端才知道 GET 能用、HEAD 能用,于是能自己换一条路重试。
Allow 也能出现在 200 里(提前告知),但最常见的位置就是 405 和 OPTIONS。
OPTIONS 那一组回 204,正文 0 字节,首部里一行 Allow: GET, HEAD, OPTIONS。
这就是「问一句答一句」,比试探着发请求便宜得多。
DELETE 那两组都回 405,区别是 133 字节和 160 字节。
27 字节换的是客户端能不能自己纠错。这个比例在任何规模下都划算。
顺带说一句:405 和 501 不一样。405 是「这个方法我认识,但这个资源不支持」;
501 是「这个方法我压根没实现」。
30 秒实验
- 把
SUPPORT改成只留 GET,看 OPTIONS 的响应变成什么样。 - 发
PATCH而不是 DELETE,看 405 里的 Allow 是不是一样。 - 想一想:为什么 501 里不该带 Allow?
常见误区
- 「405 不带 Allow 也行」——规范要求必须带,不带客户端没法纠错。
- 「Allow 是全站支持的方法」——是这一个资源支持的方法。
- 「Allow 里的方法一定成功」——只表示语义上接受,权限和状态另算。
自测三问(点开对答案)
1. 哪个状态码必须带 `Allow`? —— 405 Method Not Allowed。 2. `Allow` 和 `Access-Control-Allow-Methods` 有什么区别? —— 前者是 HTTP 本身的,后者是 CORS 专用的,两者常一起出现在预检响应里。 3. 405 和 501 怎么区分? —— 405 是方法认识但资源不支持;501 是方法根本没实现。方法说完了,接下来是正文本身:先看它被怎么压过,再看它是哪国话。
- ☐ (本节完,下一节 6.6.2 Content-Encoding)