Program Tip

리소스가 이미있는 경우 POST에 대한 HTTP 응답 코드

programtip 2020. 9. 29. 18:28
반응형

리소스가 이미있는 경우 POST에 대한 HTTP 응답 코드


클라이언트가 개체를 저장할 수있는 서버를 구축 중입니다. 이러한 개체는 클라이언트 측에서 완전히 구성되며 개체의 전체 수명 동안 영구적 인 개체 ID로 완성됩니다.

클라이언트가 PUT를 사용하여 개체를 만들거나 수정할 수 있도록 API를 정의했습니다.

PUT /objects/{id} HTTP/1.1
...

{json representation of the object}

{id}는 개체 ID이므로 Request-URI의 일부입니다.

이제 클라이언트가 POST를 사용하여 개체를 만들 수 있도록 허용하는 것도 고려 중입니다.

POST /objects/ HTTP/1.1
...

{json representation of the object, including ID}

POST는 "추가"작업을 의미하기 때문에 객체가 이미있는 경우 어떻게해야할지 모르겠습니다. 요청을 수정 요청으로 처리해야합니까, 아니면 오류 코드 (어떤)를 반환해야합니까?


내 느낌은 409 Conflict가장 적절하지만 물론 야생에서는 거의 볼 수 없습니다.

리소스의 현재 상태와 충돌하여 요청을 완료 할 수 없습니다. 이 코드는 사용자가 충돌을 해결하고 요청을 다시 제출할 수있을 것으로 예상되는 상황에서만 허용됩니다. 응답 본문은 사용자가 충돌의 원인을 인식 할 수있는 충분한 정보를 포함해야합니다 (SHOULD). 이상적으로 응답 엔터티는 사용자 또는 사용자 에이전트가 문제를 해결하기에 충분한 정보를 포함합니다. 그러나 이는 불가능할 수 있으며 필수 사항도 아닙니다.

충돌은 PUT 요청에 대한 응답으로 발생할 가능성이 가장 높습니다. 예를 들어, 버전 관리가 사용되고 있고 PUT중인 엔티티에 이전 (타사) 요청에 의해 생성 된 것과 충돌하는 리소스에 대한 변경이 포함 된 경우 서버는 409 응답을 사용하여 요청을 완료 할 수 없음을 나타낼 수 있습니다. . 이 경우 응답 엔터티는 응답 Content-Type에 정의 된 형식으로 두 버전 간의 차이점 목록을 포함 할 수 있습니다.


따르면 RFC 7231 하는 303 참조 기타 사용될 수있는 후 처리 결과는 기존 자원의 표현에 해당 될 경우 .


개인적으로 저는 WebDAV 확장을 사용 422 Unprocessable Entity합니다.

RFC 4918에 따름

422 Unprocessable Entity상태 코드는 서버가 요청 개체 (그러므로의 콘텐츠 유형을 이해하는 의미 415 Unsupported Media Type상태 코드 부적절), 상기 요청 엔티티의 구문 (따라서 올바른 400 Bad Request상태 코드 부적절) 그러나 포함 지시를 처리 할 수 없습니다.


게임이 늦었을지 모르지만 REST API를 만드는 동안이 의미론 문제를 발견했습니다.

Wrikken의 답변을 조금 확장하려면 상황에 따라 409 Conflict또는 둘 중 하나를 사용할 수 있다고 생각합니다 403 Forbidden. 즉, 사용자가 충돌을 해결하고 요청을 완료하기 위해 아무것도 할 수없는 경우 403 오류를 사용합니다 (예 : DELETE자원을 명시 적으로 제거하도록 요청) 또는 가능한 경우 409를 사용하십시오.

10.4.4 403 금지됨

서버가 요청을 이해했지만 이행을 거부하고 있습니다. 승인은 도움이되지 않으며 요청은 반복되지 않아야합니다. 요청 방법이 HEAD가 아니고 서버가 요청이 이행되지 않은 이유를 공개하려는 경우 엔티티에서 거부 이유를 설명해야합니다 (SHOULD). 서버가이 정보를 클라이언트에 제공하지 않으려면 대신 상태 코드 404 (찾을 수 없음)를 사용할 수 있습니다.

요즘 누군가가 "403"이라고 말하고 권한 또는 인증 문제가 떠오르지 만 사양에 따르면 기본적으로 서버가 클라이언트에게이를 수행하지 않을 것임을 알리고 다시 묻지 마십시오. 클라이언트가 그렇게하지 않아야하는 이유가 여기에 있습니다. '티.

사용자가 리소스에 대한 식별자를 생성 할 수단이 없거나 생성해서는 안되는 경우 리소스의 새 인스턴스를 생성하기 위해 for PUTvs. POST...를 POST사용해야합니다. PUT자원의 신원을 알 때 사용됩니다.

9.6 PUT

...

POST 및 PUT 요청의 근본적인 차이점은 Request-URI의 다른 의미에 반영됩니다. POST 요청의 URI는 포함 된 엔터티를 처리 할 리소스를 식별합니다. 해당 리소스는 데이터 수락 프로세스, 다른 프로토콜에 대한 게이트웨이 또는 주석을 수락하는 별도의 엔터티 일 수 있습니다. 대조적으로, PUT 요청의 URI는 요청에 포함 된 엔티티를 식별합니다. 사용자 에이전트는 의도 된 URI를 알고 있으며 서버는 다른 리소스에 요청을 적용하려고 시도하면 안됩니다. 서버가 요청이 다른 URI에 적용되기를 원하는 경우,

반드시 301 (영구 이동) 응답을 보내야합니다. 그러면 사용자 에이전트는 요청을 리디렉션할지 여부에 대해 자체적으로 결정할 수 있습니다.


"302 Found" sounds logical for me. And the RFC 2616 says that it CAN be answered for other requests than GET and HEAD (and this surely includes POST)

But it still keeps the visitor going to this URL to get this "Found" resource, by the RFC. To make it to go directly to the real "Found" URL one should be using "303 See Other", which makes sense, but forces another call to GET its following URL. On the good side, this GET is cacheable.

I think that I would use "303 See Other". I dont know if I can respond with the "thing" found in the body, but I would like to do so to save one roundtrip to the server.

UPDATE: After re-reading the RFC, I still think that an inexistent "4XX+303 Found" code should be the correct. However, the "409 Conflict" is the best existing answer code (as pointed by @ Wrikken), maybe including a Location header pointing to the existing resource.


It's all about context, and also who is responsible for having duplicates in requests (server or client or both)

If server just point the duplicate, look at 4xx:

  • 400 Bad Request - when server will not process request because it's obvious client fault
  • 409 Conflict - if server will not process request, but reason for that is not client's fault
  • ...

For implicit handling of duplicates, look at 2XX:

  • 200 OK
  • 201 Created
  • ...

if the server is expected to return something, look at 3XX:

  • 302 Found
  • 303 See Other
  • ...

when the server is able to point the existing resource, it implies a redirection.

If above is not enough, it's always a good practice to prepare some error message in the body of the response.


I don't think you should do this.

The POST is, as you know, to modify the collection and it's used to CREATE a new item. So, if you send the id (I think it's not a good idea), you should modify the collection, i.e., modify the item, but it's confusing.

Use it to add an item, without id. It's the best practice.

If you want to capture an UNIQUE constraint (not the id) you can response 409, as you can do in PUT requests. But not the ID.


I think for REST, you just have to make a decision on the behavior for that particular system in which case, I think the "right" answer would be one of a couple answers given here. If you want the request to stop and behave as if the client made a mistake that it needs to fix before continuing, then use 409. If the conflict really isn't that important and want to keep the request going, then respond by redirecting the client to the entity that was found. I think proper REST APIs should be redirecting (or at least providing the location header) to the GET endpoint for that resource following a POST anyway, so this behavior would give a consistent experience.

EDIT: It's also worth noting that you should consider a PUT since you're providing the ID. Then the behavior is simple: "I don't care what's there right now, put this thing there." Meaning, if nothing is there, it'll be created; if something is there it'll be replaced. I think a POST is more appropriate when the server manages that ID. Separating the two concepts basically tells you how to deal with it (i.e. PUT is idempotent so it should always work so long as the payload validates, POST always creates, so if there is a collision of IDs, then a 409 would describe that conflict).


Why not a 202 Accepted? It's an OK request (200s), there were no client errors (400s), per se.

From 10 Status Code Definitions:

"202 Accepted. The request has been accepted for processing, but the processing has not been completed."

... because it didn't need to be completed, because it already existed. The client doesn't know it already existed, they didn't do anything wrong.

I'm leaning on throwing a 202, and returning similar content to what a GET /{resource}/{id} would have returned.


I would go with 422 Unprocessable Entity, which is used when a request is invalid but the issue is not in syntax or authentication.

As an argument against other answers, to use any non-4xx error code would imply it's not a client error, and it obviously is. To use a non-4xx error code to represent a client error just makes no sense at all.

It seems that 409 Conflict is the most common answer here, but, according to the spec, that implies that the resource already exists and the new data you are applying to it is incompatible with its current state. If you are sending a POST request, with, for example, a username that is already taken, it's not actually conflicting with the target resource, as the target resource has not yet been posted to. It's an error specifically for version control, when there is a conflict between the version of the resource stored and the version of the resource requested. It's very useful for that purpose, for example when the client has cached an old version of the resource and sends a request based on that incorrect version which would no longer be conditionally valid. "In this case, the response representation would likely contain information useful for merging the differences based on the revision history." The request to create another user with that username is just unprocessable, having nothing to do with version control.

For the record, 422 is also the status code GitHub uses when you try to create a repository by a name already in use.


Another potential treatment is using PATCH after all. A PATCH is defined as something that changes the internal state and is not restricted to appending.

PATCH would solve the problem by allowing you to update already existing items. See: RFC 5789: PATCH


What about 208 - http://httpstatusdogs.com/208-already-reported ? Is that a option?

In my opinion, if the only thing is a repeat resource no error should be raised. After all, there is no error neither on the client or server sides.


Stumbled upon this question while checking for correct code for duplicate record.

Pardon my ignorance but I don't understand why everyone is ignoring the code "300" which clearly says "multiple choice" or "Ambiguous"

In my opinion this would be the perfect code for building a non standard or a particular system for your own use. I could be wrong as well!

https://tools.ietf.org/html/rfc7231#section-6.4.1


More likely it is 400 Bad Request

6.5.1. 400 Bad Request


The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

As the request contains duplicate value(value that already exists), it can be perceived as a client error. Need to change the request before the next try.
By considering these facts we can conclude as HTTP STATUS 400 Bad Request.

참고URL : https://stackoverflow.com/questions/3825990/http-response-code-for-post-when-resource-already-exists

반응형