对于不同的 http 方法,对于无效 URL 的请求返回哪个状态?

whi*_*mot 5 rest http spring-mvc http-status-codes http-headers

当 REST 应用程序收到对不存在资源的请求时,它是否应该始终返回404 Not Found?

如果它返回一个不同的状态对于任何的HTTP方法 GETHEADPOSTPUTDELETEOPTIONSTRACE

Spring 返回一个404for GETand HEAD、一个200 OKforOPTIONS和一个405 Method Not Supportedfor 其他人。错了吗?

例如,这个 Spring Boot 应用程序显示了对错误输入的 URL 的请求的不同响应(问候语而不是问候语)。

@RestController
@SpringBootApplication
public class Application {

    private static Logger log = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);

        RestTemplate restTemplate = new RestTemplate();
        String badUrl = "http://localhost:8080/greetings";
        for (HttpMethod httpMethod : HttpMethod.values()) {
            try {
                restTemplate.execute(badUrl, httpMethod, null, null);
            } catch (Exception e) {
                log.error("Failed to " + httpMethod + " -- " + e.getMessage());
            }
        }
    }

    @RequestMapping("/greeting")
    public String greeting() {
        return "hello";
    }
}
Run Code Online (Sandbox Code Playgroud)

记录的输出是:

无法获取 - 404 未找到

HEAD 失败 -- 404 Not Found

POST 失败 -- 405 方法不允许

PUT 失败 -- 405 方法不允许

无法 PATCH -- 对“ http://localhost:8080/greetings ”的PATCH 请求的 I/O 错误:无效的 HTTP 方法:PATCH;嵌套异常是 java.net.ProtocolException: Invalid HTTP method: PATCH

删除失败 -- 405 方法不允许

对“ http://localhost:8080/greetings ”的OPTIONS 请求导致 200 (OK)

无法跟踪 -- 405 方法不允许

Rob*_*gam 5

简短的回答:它不必总是返回404。更长的答案:该规范似乎提供了一些关于使用哪些状态代码的选项。规格位于https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5说:


10.4.5 404 未找到

服务器未找到任何与请求 URI 匹配的内容。没有说明这种情况是暂时的还是永久性的。如果服务器通过某种内部可配置机制知道旧资源永久不可用并且没有转发地址,则应使用 410(消失)状态代码。当服务器不希望准确揭示请求被拒绝的原因,或者没有其他响应适用时,通常使用此状态代码。

10.4.6 405 方法不允许

Request-URI 标识的资源不允许使用 Request-Line 中指定的方法。响应必须包含一个允许标头,其中包含所请求资源的有效方法列表。


何时使用这两个代码有一定的解释空间。我的解释是:如果某些资源不存在,但某些操作仍然可以应用于 URI,那么405会更合适。

例如:

GET /reservation/1

405 Method not allowed
Allow: PUT
Run Code Online (Sandbox Code Playgroud)

可能意味着,尽管GET该特定资源不允许(因为它实际上不存在),但您仍然可以PUT,从而在流程中创建所述资源。

可以说,一个404可以说,尽管规范允许,但

关于OPTIONS。规范在这里:https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.2。根据规范,这并不意味着与资源本身的交互。它更多的是对服务器的具体查询,以确定给定 URI“理论上”支持哪些方法。例如,它支持通配符(“*”)查询,该查询也可能根本不存在。