[rest] REST-본문에 ID를 넣을까요?

클라이언트가 ID를 할당 할 수있는 사람들을위한 RESTful 리소스를 원한다고 가정 해 보겠습니다.

사람은 다음과 같습니다. {"id": <UUID>, "name": "Jimmy"}

이제 클라이언트는이를 어떻게 저장 (또는 “PUT”)해야합니까?

  1. PUT /person/UUID {"id": <UUID>, "name": "Jimmy"} -이제 우리는 항상 확인해야하는 불쾌한 중복이 있습니다. 본문의 ID가 경로의 ID와 일치합니까?
  2. 비대칭 표현 :
    • PUT /person/UUID {"name": "Jimmy"}
    • GET /person/UUID 보고 {"id": <UUID>, "name": "Jimmy"}
  3. 본문에 ID 없음-위치에만 ID :
    • PUT /person/UUID {"name": "Jimmy"}
    • GET /person/UUID 보고 {"name": "Jimmy"}
  4. 의 어떤 종류의 POSTID를이 클라이언트에 의해 생성되기 때문에 좋은 아이디어처럼 보인다.

일반적인 패턴과 해결 방법은 무엇입니까? 위치에만있는 ID는 가장 독단적으로 올바른 방법처럼 보이지만 실제 구현을 더 어렵게 만듭니다.



답변

다른 읽기 / 쓰기 모델을 사용하는 데 아무런 문제가 없습니다. 클라이언트는 서버가 추가 / 계산 된 요소가 포함 된 다른 표현을 반환 할 수있는 하나의 리소스 표현을 작성할 수 있습니다 (또는 완전히 다른 표현도 가능합니다. , 유일한 요구 사항은 PUT가 리소스를 생성하거나 교체해야한다는 것입니다).

그래서 나는 (2)의 비대칭 솔루션을 선택하고 작성할 때 서버 측에서 “불쾌한 중복 검사”를 피할 것입니다.

PUT /person/UUID {"name": "Jimmy"}

GET /person/UUID returns {"id": <UUID>, "name": "Jimmy"}


답변

공개 API 인 경우 답장 할 때는 보수적이어야하지만 자유롭게 수락해야합니다.

즉, 1과 2를 모두 지원해야합니다. 3이 말이 안된다는 데 동의합니다.

1과 2를 모두 지원하는 방법은 요청 본문에 아무것도 제공되지 않은 경우 URL에서 ID를 가져오고 요청 본문에있는 경우 URL의 ID와 일치하는지 확인하는 것입니다. 둘이 일치하지 않으면 400 Bad Request 응답을 반환합니다.

사람 리소스를 반환 할 때는 보수적이어야하며 put에서 선택 사항이더라도 json에 항상 id를 포함하십시오.


답변

이 문제에 대한 한 가지 해결책은 “애플리케이션 상태의 엔진으로서의 하이퍼 텍스트”또는 “HATEOAS”라는 다소 혼란스러운 개념을 포함합니다. 이는 REST 응답에 하이퍼 링크로 수행 할 사용 가능한 리소스 또는 작업이 포함되어 있음을 의미합니다. REST의 원래 개념의 일부였던이 방법을 사용하면 리소스의 고유 식별자 / ID 자체가 하이퍼 링크입니다. 예를 들어 다음과 같은 것을 가질 수 있습니다.

GET /person/<UUID> {"person": {"location": "/person/<UUID>", "data": { "name": "Jimmy"}}}

그런 다음 해당 리소스를 업데이트하려면 다음을 수행 할 수 있습니다 (의사 코드).

updatedPerson = person.data
updatedPerson.name = "Timmy"
PUT(URI: response.resource, data: updatedPerson)

이것의 한 가지 장점은 클라이언트가 사용자 ID의 서버 내부 표현에 대해 전혀 알 필요가 없다는 것입니다. 클라이언트가 ID를 발견 할 수있는 한 ID는 변경 될 수 있으며 URL 자체도 변경 될 수 있습니다. 예를 들어, 사람들의 컬렉션을 가져올 때 다음과 같은 응답을 반환 할 수 있습니다.

GET /people
{ "people": [
    "/person/1",
    "/person/2"
  ]
}

(물론 응용 프로그램의 필요에 따라 각 사람에 대한 전체 사람 개체를 반환 할 수도 있습니다.)

이 방법을 사용하면 리소스 및 위치 측면에서 개체를 더 많이 생각하고 ID 측면에서는 덜 생각합니다. 따라서 고유 식별자의 내부 표현은 클라이언트 논리에서 분리됩니다. 이것이 REST의 원동력이었습니다. HTTP의 기능을 사용하여 이전에 존재했던 RPC 시스템보다 느슨하게 결합 된 클라이언트-서버 아키텍처를 만드는 것입니다. HATEOAS에 대한 자세한 내용은 Wikipedia 기사 와이 짧은 기사를 참조하십시오 .


답변

삽입에서 URL에 ID를 추가 할 필요가 없습니다. 이런 식으로 PUT에서 ID를 보내면 기본 키를 변경하는 UPDATE로 해석 될 수 있습니다.

  1. 끼워 넣다:

    PUT /persons/
      {"id": 1, "name": "Jimmy"}
    HTTP/1.1 201 Created
      {"id": 1, "name": "Jimmy", "other_field"="filled_by_server"}
    
    GET /persons/1
    
    HTTP/1.1 200 OK
      {"id": 1, "name": "Jimmy", "other_field"="filled_by_server"}
    
  2. 최신 정보

    PUT /persons/1
         {"id": "2", "name": "Jimmy Jr"} -
    HTTP/1.1 200 OK
         {"id": "2", "name": "Jimmy Jr", "other_field"="filled_by_server"}
    
    GET /persons/2
    
    HTTP/1.1 200 OK
         {"id": "2", "name": "Jimmy Jr", "other_field"="updated_by_server"}
    

JSON API는 이 표준을 해결해 새 개체에 대한 링크 삽입 또는 업데이트 된 개체를 반환 몇 가지 문제를 사용합니다. 일부 업데이트 또는 삽입에는 추가 필드를 변경하는 비즈니스 논리가 포함될 수 있습니다.

또한 삽입 및 업데이트 후 get을 피할 수 있음을 알 수 있습니다.


답변

이것은 이전에 질문 된 적이 있습니다. 토론은 살펴볼 가치가 있습니다.

RESTful GET 응답이 리소스의 ID를 반환해야합니까?

이것은 “휴식”이 무엇인지 아닌지 에 대한 논쟁에 빠지기 쉬운 질문 중 하나입니다 .

그만한 가치는 일관된 리소스의 관점에서 생각하고 방법간에 디자인을 변경하지 않습니다. 그러나 IMHO는 사용성 관점에서 가장 중요한 것은 전체 API에서 일관성이 있다는 것입니다!


답변

다른 작업에 대해 다른 표현 을 사용하는 것은 괜찮지 만 PUT에 대한 일반적인 권장 사항 은 WHOLE 페이로드를 포함하는 것 입니다. 그것은 id또한 거기에 있어야 함을 의미합니다 . 그렇지 않으면 PATCH를 사용해야합니다.

그렇긴하지만 PUT는 대부분 업데이트에 활용 id되어야하며 항상 URL에도 전달되어야 한다고 생각 합니다. 그 결과 PUT를 사용하여 리소스 식별자를 업데이트하는 것은 좋지 않습니다. idURL id이 본문 과 다를 수있는 경우 바람직하지 않은 상황에 처하게됩니다 .

그렇다면 그러한 갈등을 어떻게 해결합니까? 기본적으로 두 가지 옵션이 있습니다.

  • 4XX 예외 발생
  • Warning( X-API-Warnetc) 헤더를 추가하십시오 .

일반적으로 주제는 의견의 문제이기 때문에이 질문에 답할 수있는 한 거의 비슷합니다.


답변

참고로 여기에 대한 답변이 잘못되었습니다.

보다:

https://restfulapi.net/rest-api-design-tutorial-with-example/

https://restfulapi.net/rest-put-vs-post/

https://restfulapi.net/http-methods/#patch

놓다

PUT API를 주로 사용하여 기존 리소스를 업데이트합니다 (리소스가없는 경우 API가 새 리소스를 만들지 여부를 결정할 수 있음). PUT API에 의해 새 리소스가 생성 된 경우 원본 서버는 HTTP 응답 코드 201 (Created) 응답을 통해 사용자 에이전트에 알려야하며 기존 리소스가 수정되면 200 (OK) 또는 204 (No Content) 중 하나를 알려야합니다. 요청이 성공적으로 완료되었음을 나타 내기 위해 응답 코드를 전송해야합니다 (SHOULD).

요청이 캐시를 통과하고 Request-URI가 현재 캐시 된 하나 이상의 엔티티를 식별하는 경우 해당 항목은 부실한 것으로 취급해야합니다 (SHOULD). 이 메서드에 대한 응답은 캐시 할 수 없습니다.

이미 리소스 컬렉션의 일부인 단일 리소스를 수정하려는 경우 PUT를 사용합니다. PUT는 리소스 전체를 대체합니다. 요청이 리소스의 일부를 업데이트하는 경우 PATCH를 사용합니다.

반점

HTTP PATCH 요청은 리소스를 부분적으로 업데이트하는 것입니다. PUT 요청도 리소스 엔터티를 수정하여보다 명확하게 표시하는 경우 – PATCH 메서드는 기존 리소스를 부분적으로 업데이트하는 올바른 선택이며 PUT는 리소스 전체를 교체하는 경우에만 사용해야합니다.

따라서 다음과 같이 사용해야합니다.

POST    /device-management/devices      : Create a new device
PUT     /device-management/devices/{id} : Update the device information identified by "id"
PATCH   /device-management/devices/{id} : Partial-update the device information identified by "id"

RESTful 관행은 / {id}에 무엇을 입력하든 상관 없습니다. 레코드의 내용은 페이로드가 제공하는 내용으로 업데이트해야하지만 GET / {id}는 여전히 동일한 리소스에 연결되어야합니다.

즉, PUT / 3은 페이로드 ID를 4로 업데이트 할 수 있지만 GET / 3은 여전히 ​​동일한 페이로드에 연결되어야합니다 (ID가 4로 설정된 페이로드를 반환).

API에 URI와 페이로드에 동일한 식별자가 필요하다고 결정하는 경우, 일치하는지 확인하는 것이 귀하의 작업이지만, 전체가 있어야하는 페이로드에서 ID를 제외하는 경우 PUT 대신 PATCH를 사용하십시오. . 이것은 받아 들여진 대답이 잘못된 곳입니다. PUT는 전체 리소스를 대체해야합니다. 패치는 부분적 일 수 있습니다.