REST API 404 : 잘못된 URI입니까, 아니면 리소스가 없습니까?
REST API를 작성 중이지만 문제가 발생했습니다.
REST API를 설계 할 때 허용되는 관행은 요청 된 자원이 존재하지 않으면 404가 리턴되는 것입니다.
그러나 나에게 이것은 불필요한 모호성을 추가합니다. HTTP 404는 전통적으로 잘못된 URI와 관련이 있습니다. 그래서 사실상 우리가 말하고있는 "어느 쪽이든 당신은 바로 이곳에 도착하지만, 특정 기록이 존재하지 않는, 또는 그러한 위치가 Internets에 없다! 정말 아니에요 확인하는 일 ..."
다음 URI를 고려하십시오.
http://mywebsite/api/user/13
404를 다시 받으면 사용자 13이 존재하지 않기 때문입니까? 또는 내 URL 은 다음과 같아야합니다 .
http://mywebsite/restapi/user/13
과거 HTTP 200 OK
에는 레코드가 존재하지 않으면 응답 코드 와 함께 NULL 결과를 반환했습니다 . 반드시 받아 들여지는 것은 아니지만 간단하고 제 의견으로는 매우 깨끗합니다. 그러나 이것을하는 더 좋은 방법이 있습니까?
404는 HTTP 응답 코드입니다. 또한 개발자에게 표시 될보다 의미있는 오류 메시지가있는 응답 본문 및 / 또는 기타 헤더를 제공 할 수 있습니다.
404
자원이없는 경우 사용하십시오 . 200
빈 몸으로 돌아 오지 마십시오 .
이것은 프로그래밍에서 undefined
빈 문자열 (예 :)과 유사합니다 ""
. 매우 유사하지만 분명히 차이가 있습니다.
404
는 프로그래밍에 정의되지 않은 변수와 같이 해당 URI에 아무것도 존재하지 않음을 의미합니다. 200
빈 본문 으로 돌아온다 는 것은 무언가가 존재하고 무언가가 지금 비어 있음을 의미합니다 (프로그래밍의 빈 문자열처럼).
404
"잘못된 URI"라는 의미는 아닙니다. URI 오류를위한 특수한 HTTP 코드가 있습니다 (예 :) 414 Request-URI Too Long
.
대부분의 경우와 마찬가지로 "의존합니다". 그러나 나에게 당신의 연습은 나쁘지 않으며 HTTP 사양 자체 에 위배되지 않습니다 . 그러나 몇 가지 사항을 정리하겠습니다.
먼저 URI는 불투명해야합니다. 사람들에게 불투명하지 않더라도 기계에는 불투명합니다. 즉, 차이는 http://mywebsite/api/user/13
, http://mywebsite/restapi/user/13
차이와 동일 http://mywebsite/api/user/13
하고 http://mywebsite/api/user/14
동일한 같은 기간 아니다하지 즉. 따라서 404는 http://mywebsite/api/user/14
(이러한 사용자가없는 경우) 완전히 적합 하지만 반드시 유일한 적절한 응답은 아닙니다.
빈 200 응답 또는 204 (No Content) 응답을 명시 적으로 반환 할 수도 있습니다. 이것은 클라이언트에게 다른 것을 전달할 것입니다. 이는 식별 된 자원 http://mywebsite/api/user/14
이 내용이 없거나 본질적으로 아무것도 아니라는 것을 의미합니다 . 그것은 거기 있음을 의미 하는가 이다 이러한 자원. 그러나 반드시 ID 14의 데이터 저장소에 일부 사용자가 있다고 주장하는 것은 아닙니다. 이는 고객이 요청하는 것이 아니라 개인적인 문제입니다. 리소스를 모델링하는 것이 합리적이라면 계속 진행하십시오.
고객에게 합법적 인 URI를 쉽게 추측 할 수 있도록 정보를 제공하는 데 보안에 영향을 미칩니다. 404 대신 미스에 200을 반환하면 클라이언트가 적어도 http://mywebsite/api/user
부분이 정확 하다는 힌트를 얻을 수 있습니다 . 악의적 인 클라이언트는 계속해서 다른 정수를 시도 할 수 있습니다. 그러나 나에게는 악의적 인 클라이언트가 그 http://mywebsite/api/user
부분 을 추측 할 수있을 것 입니다. 더 나은 해결책은 UUID를 사용하는 것입니다. 즉, http://mywebsite/api/user/3dd5b770-79ea-11e1-b0c4-0800200c9a66
보다 낫다 http://mywebsite/api/user/14
. 그렇게하면 200을 반환하는 기술을 많이 포기하지 않고도 사용할 수 있습니다.
404 찾을 수 없음은 기술적으로 uri가 현재 리소스에 매핑 되지 않았 음을 의미 합니다. 귀하의 예에서 404 를 http://mywebsite/api/user/13
반환 하는 요청을 해석 하여이 URL이 리소스에 매핑 되지 않았 음 을 나타냅니다. 클라이언트에게는 이것이 대화의 끝이어야합니다.
모호한 문제를 해결하기 위해 다른 응답 코드를 제공하여 API를 향상시킬 수 있습니다. 예를 들어, 클라이언트가 url을 GET 요청을 발행하도록 허용 http://mywebsite/api/user/13
하고 클라이언트가 표준 url을 사용해야한다는 것을 알리고 싶다고 가정하십시오 http://mywebsite/restapi/user/13
. 이 경우 영구적으로 301 Moved Permanently 를 반환하여 영구 경로 재 지정을 고려 하고 응답 의 Location 헤더에 정식 URL을 제공 할 수 있습니다. 이것은 클라이언트에게 향후 요청에 대해 표준 URL을 사용해야한다고 알려줍니다.
본질적으로 응답은 요청이 어떻게 형성되는지에 달려 있다고 들립니다.
요청 된 자원이 요청에 따라 URI의 일부를 형성 http://mywebsite/restapi/user/13
하고 사용자 (13)가 존재하지 않는 경우, URI는 존재하지 않는 사용자 / 엔티티 / 문서 / 등을 나타 내기 때문에 404가 적절하고 직관적 일 수있다. GUID http://mywebsite/api/user/3dd5b770-79ea-11e1-b0c4-0800200c9a66
와 위의 api / restapi 인수를 사용하는보다 안전한 기술도 마찬가지입니다 .
그러나 요청 된 자원 ID가 요청 헤더 (자신의 예제 포함)에 포함되거나 실제로 URI에 매개 변수 http://mywebsite/restapi/user/?UID=13
로 포함 된 경우 URI는 여전히 정확합니다 (USER의 개념이에서 종료되기 때문에 http://mywebsite/restapi/user/
). 따라서 13으로 알려진 특정 사용자는 존재하지 않지만 URI는 존재하기 때문에 응답은 200 (적절한 자세한 메시지가있는) 일 것으로 예상 될 수 있습니다. 이런 식으로 URI는 양호하지만 데이터 요청에는 내용이 없습니다.
개인적으로 200은 여전히 옳지 않다고 생각합니다 (이전에 주장 했음에도 불구하고). 200 응답 코드 (자세한 응답이없는)는 예를 들어 잘못된 ID가 전송 될 때 문제를 조사하지 못하게 할 수 있습니다.
더 좋은 방법은 204 - No Content
응답 을 보내는 것 입니다. 이것은 w3c의 설명을 준수합니다. * 서버가 요청을 이행했지만 엔티티 본문을 리턴 할 필요가 없으며 업데이트 된 메타 정보를 리턴하려고 할 수 있습니다. * 1 혼란에 대한 의견은 Wikipedia 항목 204 No Content -서버가 요청을 성공적으로 처리했지만 내용을 반환하지 않습니다. 일반적으로 성공적인 삭제 요청에 대한 응답으로 사용됩니다 .마지막 문장은 논쟁의 여지가 있습니다. 그 문장이없는 상황을 고려하면 해결책이 쉽습니다. 엔티티가 존재하지 않으면 204를 보내십시오. 404 대신 204를 반환한다는 주장조차 있습니다. 요청이 처리되었으며 내용이 반환되지 않았습니다! 204는 응답 본문의 내용을 허용하지 않습니다.
출처
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes 1. http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
이 오래되었지만 훌륭한 기사 ... http://www.infoq.com/articles/webber-rest-workflow 는 이것에 대해 말합니다 ...
404 찾을 수 없음-서비스가 너무 게 으르거나 안전하여 요청이 실패한 이유를 알 수 있지만 이유가 무엇이든 처리해야합니다.
That is an very old post but I faced to a similar problem and I would like to share my experience with you guys.
I am building microservice architecture with rest APIs. I have some rest GET services, they collect data from back-end system based on the request parameters.
I followed the rest API design documents and I sent back HTTP 404 with a perfect JSON error message to client when there was no data which align to the query conditions (for example zero record was selected).
When there was no data to sent back to the client I prepared an perfect JSON message with internal error code, etc. to inform the client about the reason of the "Not Found" and it was sent back to the client with HTTP 404. That works fine.
Later I have created a rest API client class which is an easy helper to hide the HTTP communication related code and I used this helper all the time when I called my rest APIs from my code.
BUT I needed to write confusing extra code just because HTTP 404 had two different functions:
- the real HTTP 404 when the rest API is not available in the given url, it is thrown by the application server or web-server where the rest API application runs
- client get back HTTP 404 as well when there is no data in database based on the where condition of the query.
Important: My rest API error handler catches all the exceptions appears in the back-end service which means in case of any error my rest API always returns with a perfect JSON message with the message details.
This is the 1st version of my client helper method which handles the two different HTTP 404 response:
public static String getSomething(final String uuid) {
String serviceUrl = getServiceUrl();
String path = "user/" + , uuid);
String requestUrl = serviceUrl + path;
String httpMethod = "GET";
Response response = client
.target(serviceUrl)
.path(path)
.request(ExtendedMediaType.APPLICATION_UTF8)
.get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
// HTTP 200
return response.readEntity(String.class);
} else {
// confusing code comes here just because
// I need to decide the type of HTTP 404...
// trying to parse response body
try {
String responseBody = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
ErrorInfo errorInfo = mapper.readValue(responseBody, ErrorInfo.class);
// re-throw the original exception
throw new MyException(errorInfo);
} catch (IOException e) {
// this is a real HTTP 404
throw new ServiceUnavailableError(response, requestUrl, httpMethod);
}
// this exception will never be thrown
throw new Exception("UNEXPECTED ERRORS, BETTER IF YOU DO NOT SEE IT IN THE LOG");
}
BUT, because my Java or JavaScript client can receive two kind of HTTP 404 somehow I need to check the body of the response in case of HTTP 404. If I can parse the response body then I am sure I got back a response where there was no data to send back to the client.
If I am not able to parse the response that means I got back a real HTTP 404 from the web server (not from the rest API application).
It is so confusing and the client application always needs to do extra parsing to check the real reason of HTTP 404.
Honestly I do not like this solution. It is confusing, needs to add extra bullshit code to clients all the time.
So instead of using HTTP 404 in this two different scenarios I decided that I will do the following:
- I am not using HTTP 404 as a response HTTP code in my rest application anymore.
- I am going to use HTTP 204 (No Content) instead of HTTP 404.
In that case client code can be more elegant:
public static String getString(final String processId, final String key) {
String serviceUrl = getServiceUrl();
String path = String.format("key/%s", key);
String requestUrl = serviceUrl + path;
String httpMethod = "GET";
log(requestUrl);
Response response = client
.target(serviceUrl)
.path(path)
.request(ExtendedMediaType.APPLICATION_JSON_UTF8)
.header(CustomHttpHeader.PROCESS_ID, processId)
.get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
return response.readEntity(String.class);
} else {
String body = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
ErrorInfo errorInfo = mapper.readValue(body, ErrorInfo.class);
throw new MyException(errorInfo);
}
throw new AnyServerError(response, requestUrl, httpMethod);
}
I think this handles that issue better.
If you have any better solution please share it with us.
The Uniform Resource Identifier is a unique pointer to the resource. A poorly form URI doesn't point to the resource and therefore performing a GET on it will not return a resource. 404 means The server has not found anything matching the Request-URI. If you put in the wrong URI or bad URI that is your problem and the reason you didn't get to a resource whether a HTML page or IMG.
For this scenario HTTP 404 is response code for the response from the REST API Like 400, 401, 404 , 422 unprocessable entity
use the Exception handling to check the full exception message.
try{
// call the rest api
} catch(RestClientException e) {
//process exception
if(e instanceof HttpStatusCodeException){
String responseText=((HttpStatusCodeException)e).getResponseBodyAsString();
//now you have the response, construct json from it, and extract the errors
System.out.println("Exception :" +responseText);
}
}
This exception block give you the proper message thrown by the REST API
참고URL : https://stackoverflow.com/questions/9930695/rest-api-404-bad-uri-or-missing-resource