HTTPQUERY
English

405 Method Not Allowed

用法

收到 405 Method Not Allowed 错误时,客户端明白资源存在,但所指定的方法不被允许。作为响应的一部分,服务器会发送一个 Allow 头,列出该资源当前支持的方法。

SEO 影响

像 Google 这样的搜索引擎不会索引返回 405 状态的 URL。此前已被索引、如今返回该状态码的 URL 会从搜索结果中移除。

示例

客户端尝试对一个只读资源执行 DELETE。服务器返回 405 Method Not Allowed,并包含 Allow 头,表明仅允许 GET、HEAD 和 OPTIONS。

请求

DELETE /policies.pdf HTTP/1.1
Host: example.com

响应

HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS
Content-Type: text/html
Content-Length: 157

<html>
  <head>
    <title>Operation Not Permitted</title>
  </head>
  <body>
    <p>This resource is read-only and cannot be
    deleted.</p>
  </body>
</html>

如何修复

405 Method Not Allowed 意味着资源存在,但不支持请求中所用的 HTTP 方法。

检查响应中的 Allow 头。服务器会包含该头,列出资源允许的每一个方法。切换到列出的某个方法。使用 curl -I 或在浏览器开发者工具的 Response Headers 部分检查该头。

切换到正确的方法。一个常见错误是向只读端点发送 POST,或向提交端点发送 GET。使方法与 API 文档中描述的操作相匹配。表单提交在未将 method 属性设为 post 时默认为 GET。

核实 API 端点文档。REST API 为每个资源路径定义了特定的方法。确认路径和方法的组合是有效的。在许多框架中,/api/users 与 /api/users/ 之间的末尾斜杠差异会路由到不同的处理程序,其中一个路径接受该方法而另一个不接受。

检查服务器配置中的方法限制。Web 服务器指令按 location 限制允许的方法。在 Apache 中, 块按方法控制访问:

<LimitExcept GET HEAD OPTIONS>
    Require all denied
</LimitExcept>

在 nginx 中,limit_except 指令可实现相同效果:

location /api {
    limit_except GET POST {
        deny all;
    }
}

调整这些指令以允许预期的方法。

处理 CORS 预检请求。跨域请求会在实际方法之前触发一次 OPTIONS 预检。服务器必须以正确的 Access-Control-Allow-Methods 头响应 OPTIONS,列出允许的方法。缺失或不完整的 CORS 配置会使预检返回 405。在 nginx 中:

add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";

审查应用框架的路由。Web 框架(Django、Rails、Express、Spring)只为显式声明的方法注册路由。缺少对应所请求方法的路由装饰器或控制器动作会产生 405。确认路由定义与预期的 HTTP 方法相匹配。

检查静态文件服务器的干扰。nginx 默认提供静态文件服务,并会拒绝对静态资源的 POST 请求。当 POST 本应发往应用后端时,核实 location 块会将请求路由到上游应用而非静态文件处理程序。

代码参考

.NET

HttpStatusCode.MethodNotAllowed

Rust

http::StatusCode::METHOD_NOT_ALLOWED

Rails

:method_not_allowed

Go

http.StatusMethodNotAllowed

Symfony

Response::HTTP_METHOD_NOT_ALLOWED

Python3.5+

http.HTTPStatus.METHOD_NOT_ALLOWED

Java

java.net.HttpURLConnection.HTTP_BAD_METHOD

Apache HttpComponents Core

org.apache.hc.core5.http.HttpStatus.SC_METHOD_NOT_ALLOWED

Angular

@angular/common/http/HttpStatusCode.MethodNotAllowed