REST API 404 : 잘못된 URI입니까, 아니면 리소스가 없습니까?


219

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 결과를 반환했습니다 . 반드시 받아 들여지는 것은 아니지만 간단하고 제 의견으로는 매우 깨끗합니다. 그러나 이것을하는 더 좋은 방법이 있습니까?



7
다른 질문은 URI 쿼리 문자열 형식과 관련이있는 것 같습니다. 404에 대한 토론은 내 질문에 대답하기에 충분하지 않습니다. 404가 실제로 의미하는 바를 결정하는 데 더 적절하거나 유용한 방법이 있는지 여부입니다. 게시하기 전에 그 내용을 검토했습니다.
Brian Lacy

브라우저 concole이 오류 404를 구성 할 때 정상입니까? 올바른 URI로 정규 작업을 수행하지만 리소스를 찾을 수없는 경우
Vasiliy Mazhekin

3
404는 잘못된 URI를 나타내지 않으며 리소스를 찾을 수 없음을 나타냅니다. 사용자 '13'이 없거나 / mywebsite / api 자원이 없기 때문일 수 있습니다.
ChrisV

답변:


101

404는 HTTP 응답 코드입니다. 또한 개발자에게 표시 될보다 의미있는 오류 메시지가있는 응답 본문 및 / 또는 기타 헤더를 ​​제공 할 수 있습니다.


7
이것은 말이됩니다. 그러나 null 응답으로 200을 반환하는 것과는 달리 404를 처음 반환하면 실제로 어떤 이점이 있는지 궁금합니다.
Brian Lacy

15
null로 200을 반환하면 HTTP 사양에 위배됩니다. 이 작업을 수행 할 수 있지만 API는 REST의 "Uniformed Interface"제한 조건을 준수하지 않습니다.
고소

5
... 응답 본문에는 유효한 URI에 대한 하이퍼 링크가 포함되어야합니다. 루트 URI 및 책갈피 또는 두 개를 제외하면 클라이언트는 항상 서버가 제공 한 링크를 따라야 합니다. 그런 다음 시스템 외부에서 작업하기로 결정한 방식과 관련하여 자세한 의미를 발명 할 필요가 없습니다.
fumanchu

@DarrylHebbes 무슨 뜻입니까, 요청을하고 Chrome 개발자 콘솔의 네트워크 탭에서 응답의 전체 내용을 볼 수 있습니다.
jaapz

빈 결과를 반환하는 모든 쿼리에 대해 오류 (404 등)를 반환하는 것은 엄청나게 좋지 않습니다. 데이터베이스는 그렇게하지 않으며 일반적으로 빈 결과를 예기치 않은 조건으로 사용자에게보고하지 않습니다. 예 : 다음 30 분 동안 예정된 약속이 있는지 확인하기 위해 API를 쿼리합니다. 아무것도 없으면 404를 반환해서는 안됩니다. 200 OK와 빈 배열을 반환하십시오.
esmiralha

59

404자원이없는 경우 사용하십시오 . 200빈 몸으로 돌아 오지 마십시오 .

이것은 프로그래밍에서 undefined빈 문자열 (예 :)과 유사합니다 "". 매우 유사하지만 분명히 차이가 있습니다.

404는 프로그래밍에 정의되지 않은 변수와 같이 해당 URI에 아무것도 존재하지 않음을 의미합니다. 200빈 본문 으로 돌아온다 는 것은 무언가가 존재하고 무언가가 지금 비어 있음을 의미합니다 (프로그래밍의 빈 문자열과 같이).

404"잘못된 URI"라는 의미는 아닙니다. URI 오류를위한 특수한 HTTP 코드가 있습니다 (예 :) 414 Request-URI Too Long.


1
이봐, 네가 뭔가있을 것 같아 "41"중 하나를 반환하는 것이 더 합리적이지 않습니까? 요청 된 리소스에 문제가있을 때 오류가 발생합니까? 예를 들어, 410 Gone"요청한 자원을 더 이상 서버에서 사용할 수 없으며 전달 주소를 알 수 없습니다"를 의미합니다. -( w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.11 참조 )
Brian Lacy

실제로 위에서 언급 한 리소스는 "서버가 조건이 영구적인지 여부를 알 수 없거나 결정할 기능이없는 경우 상태 코드 404 (찾을 수 없음)를 대신 사용해야합니다." 아마도 이것이 최고의 선택 일 필요는 없습니다 ..
Brian Lacy

2
41x 오류가 귀하의 사용 사례에 적합하다고 생각하지 않습니다. 나는 정의되지 않은 문자열과 빈 문자열을 비교하는 것을 좋아한다. 차이점이 있지만 빈 문자열이 오류라는 것을 의미하지는 않습니다. 유추를 늘리려면 : 다음과 String getName()같은 구현을 갖는 메소드 를 가질 수 있습니다 return this.name == null ? "" : this.name. 클라이언트가 알고 싶어하지 않는 한 잘못이 아니에요 this.name입니다 null.
jhericks

1
404가 여전히 가장 적합한 옵션입니다. 해당 404 응답의 본문을 사용하여 사용자 / 클라이언트에게 오류 수신에 대한 특정 세부 정보를 알릴 수 있습니다. stackoverflow.com/a/9999335/105484를 참조하십시오 . 귀하의 경우에는 당신은 그들이 / restapi / 사용자 / USER_ID처럼 보이도록 자신의 URI를 다시 포맷하는 사용자에게 추천 그 몸을 사용할 수 있습니다
nategood

좋아, 여기에 좋은 점이 있지만 4XX는 오류 코드입니다. 어떻게 오류 상황입니까? 클라이언트가 404가 발생하지 않도록하려면 어떻게해야합니까?
Krzysztof Kubicki

20

대부분의 경우와 마찬가지로 "의존합니다". 그러나 나에게 당신의 연습은 나쁘지 않으며 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을 돌려주는 기술을 많이 포기하지 않고도 사용할 수 있습니다.


1
이것이 제가 404 대신 204를 사용하여 선택한 솔루션입니다. 204는 "코드를 찾았지만 결과를 찾지 못했습니다"를 의미하고 404는 "실행할 코드를 찾을 수 없습니다"라는 의미입니다 잘못된 길? "
매트 샌더스

11

404 찾을 수 없음은 기술적으로 uri가 현재 리소스에 매핑 되지 않았 음을 의미 합니다. 귀하의 예에서 404http://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을 사용해야한다고 알려줍니다.


11

본질적으로 응답은 요청이 어떻게 형성되는지에 달려 있다고 들립니다.

요청 된 자원이 요청에 따라 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응답 을 보내는 것 입니다. 이 서버는 요청을 이행했지만 entity-body를 반환 할 필요가 없으며 업데이트 된 메타 정보를 반환 할 수 있습니다 * W3C의 설명을 준수합니다. * 1 혼동, 내 의견이 진술 위키 백과 항목에 의해 발생에 204 없음 콘텐츠 -서버가 요청을 성공적으로 처리했지만 내용을 반환하지 않습니다. 일반적으로 성공적인 삭제 요청에 대한 응답으로 사용됩니다 .마지막 문장은 논쟁의 여지가 있습니다. 해당 문장이없는 상황을 고려하면 해결 방법이 쉽습니다. 엔티티가 존재하지 않으면 204 만 보내십시오. 404 대신 204를 반환한다는 주장조차 있습니다. 요청이 처리되었으며 내용이 반환되지 않았습니다! 204는 응답 본문의 내용을 허용하지 않습니다.

출처

http://en.wikipedia.org/wiki/List_of_HTTP_status_codes 1. http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html


9

그것은 매우 오래된 게시물이지만 비슷한 문제에 직면하여 내 경험을 여러분과 공유하고 싶습니다.

나머지 API를 사용하여 마이크로 서비스 아키텍처를 구축 중입니다. 나머지 GET 서비스가 있으며 요청 매개 변수를 기반으로 백엔드 시스템에서 데이터를 수집합니다.

나머지 API 디자인 문서를 따르고 쿼리 조건에 맞는 데이터가 없을 때 완벽한 JSON 오류 메시지와 함께 HTTP 404를 클라이언트에 다시 보냈습니다 (예 : 0 레코드 선택).

클라이언트로 전송할 데이터가 없을 때 내부 오류 코드 등을 포함한 완벽한 JSON 메시지를 준비하여 "Not Found"의 이유를 클라이언트에게 알리고 HTTP 404를 사용하여 클라이언트로 다시 보냈습니다. 잘 작동합니다.

나중에 HTTP 통신 관련 코드를 숨기는 쉬운 도우미 인 나머지 API 클라이언트 클래스를 만들었으며 코드에서 나머지 API를 호출 할 때이 도우미를 항상 사용했습니다.

그러나 HTTP 404에는 두 가지 기능이 있기 때문에 혼란스러운 추가 코드를 작성해야했습니다.

  • 제공된 URL에서 나머지 API를 사용할 수없는 경우 실제 HTTP 404는 나머지 API 응용 프로그램이 실행되는 응용 프로그램 서버 또는 웹 서버에서 발생합니다.
  • 클라이언트는 쿼리의 위치 조건에 따라 데이터베이스에 데이터가없는 경우에도 HTTP 404를 가져옵니다.

중요 : 내 나머지 API 오류 처리기는 백엔드 서비스에 나타나는 모든 예외를 포착합니다. 즉, 오류가 발생하면 나머지 API는 항상 메시지 세부 정보가 포함 된 완벽한 JSON 메시지로 반환됩니다.

이것은 두 가지 다른 HTTP 404 응답을 처리하는 클라이언트 도우미 메소드의 첫 번째 버전입니다.

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");
}

그러나 Java 또는 JavaScript 클라이언트가 두 가지 종류의 HTTP 404를 수신 할 수 있기 때문에 HTTP 404의 경우 응답 본문을 확인해야합니다. 응답 본문을 구문 분석 할 수 있으면 응답이있는 곳에서 응답을 얻었습니다. 클라이언트에게 다시 보낼 데이터가 없습니다.

응답을 파싱 할 수 없다면 웹 서버 (나머지 API 응용 프로그램이 아닌)에서 실제 HTTP 404를 다시 가져 왔습니다.

너무 혼란스럽고 클라이언트 응용 프로그램은 항상 HTTP 404의 실제 이유를 확인하기 위해 추가 구문 분석을 수행해야합니다.

솔직히 나는이 솔루션을 좋아하지 않습니다. 혼란스럽고 항상 고객에게 여분의 헛소리 코드를 추가해야합니다.

따라서이 두 가지 시나리오에서 HTTP 404를 사용하는 대신 다음을 수행하기로 결정했습니다.

  • 더 이상 나머지 응용 프로그램에서 HTTP 404를 응답 HTTP 코드로 사용하지 않습니다.
  • HTTP 404 대신 HTTP 204 (No Content)를 사용하려고합니다.

이 경우 클라이언트 코드가 더 우아해질 수 있습니다.

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);
}

이것이 문제를 더 잘 처리한다고 생각합니다.

더 나은 솔루션이 있으면 공유하십시오.


Apache HttpClient 메소드는 204 응답에서 예외를 발생시키지 않습니다. 클라이언트가 비즈니스 오브젝트 (모델)에 응답하면 널을 리턴합니다. 작동하지만 최종 사용자가 204 상황을 감지하기는 어렵습니다.
chrisinmtown

그것은 모두 좋지만 문제는 404에 대한 if 문을 얼마나 자주 쓰십니까? 그리고 그것은 무엇입니까? 반면에 오류 json이있는 404를 정의하는 API를 호출하면이 경우에만 처리 ​​할 수 ​​있습니다.
Max

zappee 동의합니다. 데이터를 반환하는 서비스가 있습니다. 그러나 데이터가 깨지는 상황이 있습니다. 요청 URL은 정확하지만 (404가 아님) 실제로 논리 오류 (500)는 아니므로 204가 가장 적합 해 보입니다. 메시지 본문의 부족에 대해 정말 성가시다. 논란의 여지가 있지만 헤더에 이유를 삽입 할 수는 있습니다.
cs94njw


1

Uniform Resource Identifier는 리소스에 대한 고유 한 포인터입니다. 형식이 잘못된 URI는 리소스를 가리 키지 않으므로 GET을 수행하면 리소스가 반환되지 않습니다. 404 의미 서버가 Request-URI와 일치하는 것을 찾지 못했습니다. 잘못된 URI 또는 ​​잘못된 URI를 넣으면 문제이며 HTML 페이지이든 IMG이든 리소스에 액세스하지 못한 이유입니다.


0

이 시나리오의 경우 HTTP 404는 REST API의 응답에 대한 응답 코드입니다. 400, 401, 404, 422 처리 할 수없는 엔티티

예외 처리를 사용하여 전체 예외 메시지를 확인하십시오.

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);
     }

}

이 예외 블록은 REST API에 의해 발생 된 적절한 메시지를 제공합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.