일반적인 실패한 요청 (오류 아님)에 대한 적절한 HTTP 상태 코드 응답은 무엇입니까?


109

저장된 신용 카드를 사용하여 주문하는 것을 포함하여 여러 사용자 상호 작용을 처리하는 RESTful API를 만들고 있습니다.

성공적인 주문의 경우 200 OK를 반환하고 주문 요청이 잘못되었거나 잘못된 경우 400 Bad Request를 반환합니다. 그러나 실제 주문 처리 중에 문제가 발생하면 무엇을 반품해야합니까?

  1. 클라이언트는 사용자 리소스에 대해 서버에 주문을 게시합니다. 사용자가 없으면 404 Not Found가 반환됩니다.
  2. 주문 형식 및 정보가 확인되었습니다. 유효하지 않은 경우 400 Bad Request가 반환됩니다.
  3. 주문이 처리됩니다. 주문이 성공하면 주문에 대해 201 Created가 반환됩니다. 예기치 않은 오류가 발생하면 500 서버 오류가 반환됩니다.

마지막 단계는 문제입니다. 다른 이유로 주문이 완료되지 않으면 무엇을 반품해야합니까? 가능한 시나리오는 다음과 같습니다.

  • 상품이 매진되었습니다
  • 사용자 최대 주문 한도에 도달했습니다.
  • 신용 카드 거래 실패 (잔액 부족 등)

이것은 400 또는 500에 적합하지 않은 것 같습니다. 더 나은 코드가 없으면 400으로 볼 수있는 것이 있으면 비즈니스 규칙에 따라 요청이 유효하지 않습니다. 정확하지 않은 것 같습니다.

편집 : 동일한 주제에 대한 기존 토론 도 발견 했습니다 . 모든 답변은 이러한 유형의 위반에 대해 상태 코드를 사용하는 것으로 보이는데, 400, 409 또는 422 확장 사용 사이에 약간의 논의가 있습니다.


8
유효성 검사 오류에 대해 '422 unprocessable entity'를 좋아합니다. 그리고 위의 예에 사용하고 실제 비즈니스 문제 "제품이 매진되었습니다"라는 메시지를 응답에 포함하고 클라이언트가 응답에 따라 프로그래밍 방식으로 다른 결정을 내려야하는 경우 자신의 '코드'를 추가 할 수 있습니다.
house9

당신이 422에 뛰어 전에 WebDAV를 기능을 지원하는 경우, 고려
Mbithy Mbithy에게

답변:


90

비즈니스 규칙에는 400을 사용해야합니다. 주문이 수락되지 않은 경우 2xx를 반환하지 마십시오. HTTP는 애플리케이션 프로토콜이므로 잊지 마십시오. 2xx를 반품하면 고객은 본문에 보낸 정보에 관계없이 주문이 수락 된 것으로 간주 할 수 있습니다.


에서 RESTful 웹 서비스 요리 책 :

일부 웹 서비스의 일반적인 실수 중 하나는 성공을 반영하는 상태 코드 (200에서 206 및 300에서 307의 상태 코드)를 반환하지만 오류 조건을 설명하는 메시지 본문을 포함하는 것입니다. 이렇게하면 HTTP 인식 소프트웨어가 오류를 감지하지 못합니다. 예를 들어 캐시는이를 성공적인 응답으로 저장하고 클라이언트가 성공적인 요청을 할 수있는 경우에도 후속 클라이언트에 제공합니다.

4xx와 5xx 사이에서 결정하도록 맡기겠습니다.하지만 오류 상태 코드를 사용해야합니다.


1
이 접근 방식과 다른 접근 방식에 대한 예 또는 참조가 있습니까? 당신과 Widor의 대답은 모두 의미가 있습니다. 하나는 애플리케이션 프로토콜로서의 HTTP 관점에서, 다른 하나는 전송 목적을위한 것입니다. 사양에서는이를 "애플리케이션 수준 프로토콜"로 정의하는데 약간 모호합니다. 나는 또한 이것을 조사 할 때 웹에서 관점과 예를 모두 보았다.
Raelshark

이건 정말 진실.
젊은 현 유

2
'비즈니스 규칙에 4xx를 사용해야합니다'라는 뜻입니까?
Yawar

28

클라이언트가 오류를 해결하기 위해 요청을 수정할 수있는 경우 클라이언트 오류에 4xx를 사용해야합니다. 클라이언트가 실제로 해결할 수없는 서버 오류에는 5xx를 사용하십시오.

품절 된 상품은 서버 오류입니다. 클라이언트는 오류를 해결하기 위해 어떤 방식 으로든 요청을 수정할 수 없습니다. 다른 제품으로 전환 할 수 있지만 새로운 요청이 아닐까요?

사용자 최대 주문 한도에 도달 한 것도 서버 오류입니다. 클라이언트가 해당 오류를 해결하기 위해 수행 할 수있는 작업은 없습니다.

신용 카드 거래 실패는 클라이언트 오류입니다. 클라이언트는 오류를 해결하기 위해 다른 결제 방법 또는 신용 카드 번호로 요청을 다시 제출할 수 있습니다.


6
주문 한도에 도달하면 클라이언트가 사용자에게이를 알리고 요청을 적절히 변경하도록해야하지 않습니까? 4xx 오류처럼 보입니다. 매진되는 제품도 마찬가지입니다. 5xx 오류는 비즈니스 규칙에서 허용하지 않는 작업이 아니라 어떤 방식 으로든 시스템이 중단되어 발생하는 오류를위한 것입니다.
carlin.scott

7
위의 의견에 동의합니다. 5xx 오류는 서버에 문제가있을 때 발생합니다. 비즈니스 규칙에 대한 4xx 오류.
Merc 2019

21

오류 유형 :

4×× Client Error

에러 코드:

422 Unprocessable Entity

서버는 요청 엔티티의 컨텐츠 유형을 이해하고 (따라서 415 지원되지 않는 미디어 유형 상태 코드가 부적절 함) 요청 엔티티의 구문이 올바르지 만 (따라서 400 잘못된 요청 상태 코드가 부적절 함) 포함 된 항목을 처리 할 수 ​​없습니다. 명령.

예를 들어, XML 요청 본문에 올바른 형식 (즉, 구문 적으로 올바른)이 포함되어 있지만 의미 상 잘못된 XML 명령이 포함 된 경우이 오류 조건이 발생할 수 있습니다.

https://httpstatuses.com/422


16

이 질문이 오래되었다는 것을 알고 있지만 오늘도 똑같은 질문을 내놓았습니다. 사용자의 크레딧이 부족한 경우 REST API에서 어떤 상태 코드를 반환해야합니까?

나는 다음쪽으로 기울이는 경향이 있습니다 402 Payment Required.

Wikipedia 에 따르면 :

향후 사용을 위해 예약되었습니다. 원래 의도는이 코드가 어떤 형태의 디지털 현금이나 소액 결제 방식의 일부로 사용될 수 있다는 것이었지만, 그런 일이 발생하지 않았으며이 코드는 일반적으로 사용되지 않습니다. Google Developers API는 특정 개발자가 일일 요청 한도를 초과 한 경우이 상태를 사용합니다.

그리고 실제로 그들은 :

PAYMENT_REQUIRED (402)

  • 개발자가 설정 한 일일 예산 한도에 도달했습니다.
  • 요청 된 작업에는 할당량이 허용하는 것보다 더 많은 리소스가 필요합니다. 작업을 완료하려면 결제가 필요합니다.
  • 요청 된 작업에는 인증 된 사용자로부터 일종의 지불이 필요합니다.

이것은 가장 잘 생각하고 논리적 인 대답입니다.
GTodorov

5

어때요 424 Failed Dependency? 사양은 다음과 같이 설명합니다.

요청 된 작업이 다른 작업에 종속되어 해당 작업이 실패했기 때문에 리소스에서 메서드를 수행 할 수 없습니다.

그러나 다음과 같은 정의도 있습니다 .

상태 코드 424는 WebDAV 표준에 정의되어 있으며 클라이언트가 수행중인 작업을 변경해야하는 경우를위한 것입니다. 서버에 문제가 발생하지 않습니다.

고객에게 주문을 생성하고 잔액을 공제해야하는 내부 조치가 있으며 완벽하게 타당한 이유에도 불구하고 해당 조치 중 하나가 실패했다고 말하거나 가장 할 수 있으며, 이것이 요청이 실패한 이유입니다.

내가 볼 수있는 한 "액션"은 상당히 광범위한 용어이며 재고 부족, 신용 부족 또는 창고 파티 밤 등 다양한 상황에서 사용될 수 있습니다.


다른 옵션은 다음과 422 Unprocessable Entity같습니다.

서버는 요청 엔티티의 컨텐츠 유형을 이해하고 (따라서 415 지원되지 않는 미디어 유형 상태 코드가 부적절 함) 요청 엔티티의 구문이 올바르지 만 (따라서 400 잘못된 요청 상태 코드가 부적절 함) 포함 된 항목을 처리 할 수 ​​없습니다. 명령.

예를 들어, XML 요청 본문에 올바른 형식 (즉, 구문 적으로 올바른)이 포함되어 있지만 의미 상 잘못된 XML 명령이 포함 된 경우이 오류 조건이 발생할 수 있습니다.

재고가없는 아이템을 요청하거나 크레딧이 부족한 경우 의미 론적 수준에서 실수로 간주 될 수 있습니다.

MozDev 이것이 클라이언트 측의 실수를 나타냅니다. 특히 : 클라이언트는 수정없이이 요청을 반복해서는 안됩니다.

루프백 4 입력 유효성 검사가 실패 할 때 422를 사용 합니다.


재고 부족 또는 창고 파티의 밤은 일시적인 상태로 간주 될 수 있으므로 나중에 요청을 다시 시도 할 수 있습니다. 그 상황은 다음과 같이 나타낼 수 있습니다.503 Service Unavailable

서버는 현재 일시적인 과부하 또는 예정된 유지 보수로 인해 요청을 처리 할 수 ​​없으며, 이는 약간의 지연 후에 완화 될 수 있습니다.

서버는 요청을 재 시도하기 전에 클라이언트가 대기 할 적절한 시간을 제안하기 위해 Retry-After 헤더 필드를 보낼 수 있습니다.


그것들 중 어느 것도 지불과 관련이 없습니다. 이전 답변에서 402로갑니다!
GTodorov

2

모든 비즈니스 시나리오에 400을 사용할 수 있다고 생각하지 않습니다. 기본 데이터 입력 유효성 검사에 사용할 수 있습니다. 그 외에는 다른 비즈니스 로직을이 오류 코드에 맞추기가 어려울 수 있습니다. 이에 의해 처리되는 오류는 대부분 개발자가 클라이언트 코딩 중에 발생할 수있는 디자인 타임 오류입니다.

모든 매개 변수가 정확하고 사용자 계정 번호를 요청에 전달한다고 가정 해 보겠습니다.

따라서 요청은 더 이상 잘못된 요청이 아니며 서버는 요청을 수락 할 수 있습니다. 그러나 지금은 사용 가능한 새로운 정보를 기반으로 요청을 완료하는 것을 거부하고 있습니다. 즉, 계정에 충분한 잔액이 없습니다.

이러한 시나리오에서 적절한 오류 메시지와 함께 403을 사용하는 것이 좋습니다.

다른 가능한 오류 코드는 409 충돌 일 수 있습니다. 그러나 이는 리소스가 일관된 상태에있는 시나리오에서 사용됩니다.


-1

나는 406으로 간다 Not Acceptable.

다음은 4xx 목록입니다.

const HTTP_BAD_REQUEST = 400;
const HTTP_UNAUTHORIZED = 401;
const HTTP_PAYMENT_REQUIRED = 402;
const HTTP_FORBIDDEN = 403;
const HTTP_NOT_FOUND = 404;
const HTTP_METHOD_NOT_ALLOWED = 405;
const HTTP_NOT_ACCEPTABLE = 406;
const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
const HTTP_REQUEST_TIMEOUT = 408;
const HTTP_CONFLICT = 409;
const HTTP_GONE = 410;
const HTTP_LENGTH_REQUIRED = 411;
const HTTP_PRECONDITION_FAILED = 412;
const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
const HTTP_REQUEST_URI_TOO_LONG = 414;
const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const HTTP_EXPECTATION_FAILED = 417;
const HTTP_I_AM_A_TEAPOT = 418;                                               // RFC2324
const HTTP_MISDIRECTED_REQUEST = 421;                                         // RFC7540
const HTTP_UNPROCESSABLE_ENTITY = 422;                                        // RFC4918
const HTTP_LOCKED = 423;                                                      // RFC4918
const HTTP_FAILED_DEPENDENCY = 424;                                           // RFC4918
const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;   // RFC2817
const HTTP_UPGRADE_REQUIRED = 426;                                            // RFC2817
const HTTP_PRECONDITION_REQUIRED = 428;                                       // RFC6585
const HTTP_TOO_MANY_REQUESTS = 429;                                           // RFC6585

8
상태 코드 406의 이름은 그 자체로 정확하게 들릴 수 있지만 각 상태 코드에는 신뢰할 수있는 텍스트 설명이 있음을 알아야합니다. 상태 코드 406에 대한 설명은 당면한 경우에 적합하지 않습니다 . 예를 들어 httpstatuses.com/406을 참조하십시오 .
Zero3

1
@ Zero3이 맞습니다.이 코드는 클라이언트에서 보낸 수락 헤더와 엔드 포인트에서 보낸 MediaType (예 : application / json 대 text / plain
Gregor
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.