When a REST application receives a request for a non-existent resource, should it always return a 404 Not Found
?
Should it return a different status for any of the HTTP methods GET
, HEAD
, POST
, PUT
, DELETE
, OPTIONS
or TRACE
?
Spring returns a 404
for GET
and HEAD
, a 200 OK
for OPTIONS
, and a 405 Method Not Supported
for the others. Is that wrong?
e.g. This Spring Boot application shows the different responses for requests to a mis-typed URL (greetings instead of greeting).
@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";
}
}
The logged output is:
Failed to GET -- 404 Not Found
Failed to HEAD -- 404 Not Found
Failed to POST -- 405 Method Not Allowed
Failed to PUT -- 405 Method Not Allowed
Failed to PATCH -- I/O error on PATCH request for "http://localhost:8080/greetings": Invalid HTTP method: PATCH; nested exception is java.net.ProtocolException: Invalid HTTP method: PATCH
Failed to DELETE -- 405 Method Not Allowed
OPTIONS request for "http://localhost:8080/greetings" resulted in 200 (OK)
Failed to TRACE -- 405 Method Not Allowed
Short answer: It does not have to always return 404
. Longer answer: The specification seems to provide some options regarding which status codes to use. The specification at https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5 says:
10.4.5 404 Not Found
The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.
10.4.6 405 Method Not Allowed
The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. The response MUST include an Allow header containing a list of valid methods for the requested resource.
There is some room for interpretation when to use those two codes. My interpretation would be: If some resource does not exist, yet some operation conceivably could still be applied to the URI, then a 405
would be more appropriate.
For example:
GET /reservation/1
405 Method not allowed
Allow: PUT
Could mean, that although GET
is not allowed on that particular resource (because it does not actually exist), you could still make PUT
work, thereby creating said resource in the process.
Arguably, a 404
, although allowed by the specification, would be less usable.
Regarding OPTIONS
. Specification is here: https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.2 . According to specification is does not imply an interaction with the resource itself. It is more of a query to the server specifically, to determine what methods would be "theoretically" supported on the given URI. It supports for example a wildcard ("*") query, which also probably does not exist at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With