고객 관리 시스템을 위해 RESTful 서비스를 작성 중이며 레코드를 부분적으로 업데이트하는 모범 사례를 찾으려고 노력하고 있습니다. 예를 들어, 발신자가 GET 요청으로 전체 레코드를 읽을 수 있기를 원합니다. 그러나 업데이트하려면 상태를 ENABLED에서 DISABLED로 변경하는 것과 같이 레코드의 특정 작업 만 허용됩니다. (이보다 더 복잡한 시나리오가 있습니다)
보안상의 이유로 호출자가 업데이트 된 필드만으로 전체 레코드를 제출하지 않기를 원합니다 (과도한 느낌).
URI를 구성하는 권장 방법이 있습니까? REST 책을 읽을 때 RPC 스타일 호출은 눈살을 찌푸리는 것처럼 보입니다.
다음 통화에서 ID가 123 인 고객의 전체 고객 레코드를 반환하는 경우
GET /customer/123
<customer>
{lots of attributes}
<status>ENABLED</status>
{even more attributes}
</customer>
상태를 어떻게 업데이트해야합니까?
POST /customer/123/status
<status>DISABLED</status>
POST /customer/123/changeStatus
DISABLED
...
업데이트 : 질문을 보완합니다. ‘비즈니스 로직 호출’을 REST API에 어떻게 통합합니까? 합의 된 방법이 있습니까? 모든 방법이 본질적으로 CRUD 인 것은 아닙니다. ‘ sendEmailToCustomer (123) ‘, ‘ mergeCustomers (123, 456) ‘, ‘ countCustomers () ‘ 와 같은 일부는 더 복잡합니다.
POST /customer/123?cmd=sendEmail
POST /cmd/sendEmail?customerId=123
GET /customer/count
답변
기본적으로 두 가지 옵션이 있습니다.
-
사용
PATCH
(하지만 정확하게 발생하는 것을 지정하는 고유 한 미디어 유형을 정의해야 함) -
사용
POST
하위 자원 및 Location 헤더가 주요 자원을 가리키는과 303 페이지의 기타를 반환합니다. 303의 목적은 클라이언트에게 “POST를 수행했으며 그 결과 다른 리소스가 업데이트 된 것입니다. 어떤 리소스의 위치 헤더를 참조하십시오.” POST / 303은 일부 주요 자원의 상태를 구축하기 위해 자원에 반복적으로 추가하기위한 것이며 부분 업데이트에 완벽하게 적합합니다.
답변
부분 업데이트에는 POST를 사용해야합니다.
고객 123의 필드를 업데이트하려면 / customer / 123에 POST를 만드십시오.
상태 만 업데이트하려면 / customer / 123 / status로 PUT 할 수도 있습니다.
일반적으로 GET 요청에는 부작용이 없어야하며 PUT은 전체 리소스를 작성 / 바꾸기위한 것입니다.
이것은 http://en.wikipedia.org/wiki/HTTP_PUT#Request_methods에서 볼 수 있듯이 HTTP에서 직접 수행됩니다 .
답변
json-patch 문서를 사용하여 부분 업데이트에 PATCH를 사용해야합니다 ( http://tools.ietf.org/html/draft-ietf-appsawg-json-patch-08 또는 http://www.mnot.net/ 참조). blog / 2012 / 09 / 05 / patch ) 또는 XML 패치 프레임 워크 ( http://tools.ietf.org/html/rfc5261 참조 ) 내 의견으로는, json-patch는 귀하의 비즈니스 데이터 종류에 가장 적합합니다.
JSON / XML 패치 문서가 포함 된 PATCH는 부분 업데이트를위한 매우 중요한 의미를 갖습니다. 원본 문서의 수정 된 복사본으로 POST를 사용하기 시작하면 부분 업데이트의 경우 누락 된 값 (또는 null 값)이 “이 속성을 무시합니다”또는 “이 속성을 empty value “-결국 해킹 된 솔루션으로 인해 결국에는 자신 만의 패치 형식이 만들어 질 것입니다.
http://soabits.blogspot.dk/2013/01/http-put-patch-or-post-partial-updates.html 에서보다 자세한 답변을 찾을 수 있습니다 .
답변
비슷한 문제가 발생합니다. 하위 리소스의 PUT은 단일 필드 만 업데이트하려는 경우 작동하는 것 같습니다. 그러나 때로는 여러 가지 사항을 업데이트하려고합니다. 일부 항목을 변경하는 옵션이있는 리소스를 나타내는 웹 양식을 생각하십시오. 사용자가 양식을 제출하면 여러 PUT이 생성되지 않아야합니다.
내가 생각할 수있는 두 가지 솔루션이 있습니다.
-
전체 리소스로 PUT을 수행하십시오. 서버 측에서 전체 자원이있는 PUT이 변경되지 않은 모든 값을 무시한다는 의미를 정의하십시오.
-
부분 리소스로 PUT을 수행하십시오. 서버 측에서이 의미를 병합으로 정의하십시오.
2는 1의 대역폭 최적화입니다. 자원이 일부 필드가 필수 필드 인 경우 (프로토 버퍼 생각) 1이 유일한 옵션입니다.
이 두 가지 접근 방식의 문제점은 필드를 지우는 방법입니다. 필드를 지우는 특수 널 값을 정의해야합니다 (특히 널 값은 프로토 버퍼에 대해 정의되지 않으므로 프로토 버퍼에 대해).
코멘트?
답변
상태를 수정하기 위해 RESTful 접근법은 리소스의 상태를 설명하는 논리적 하위 리소스를 사용하는 것입니다. 이 IMO는 상태가 줄어든 경우 매우 유용하고 깨끗합니다. 고객 리소스에 대한 기존 작업을 강요하지 않고도 API를보다 표현력있게 만듭니다.
예:
POST /customer/active <-- Providing entity in the body a new customer
{
... // attributes here except status
}
POST 서비스는 새로 작성된 고객을 id로 반환해야합니다.
{
id:123,
... // the other fields here
}
생성 된 리소스에 대한 GET은 리소스 위치를 사용합니다.
GET /customer/123/active
GET / customer / 123 / inactive는 404를 반환해야합니다.
PUT 조작의 경우 Json 엔티티를 제공하지 않고 상태 만 업데이트합니다.
PUT /customer/123/inactive <-- Deactivating an existing customer
엔티티를 제공하면 고객의 컨텐츠를 업데이트하고 동시에 상태를 업데이트 할 수 있습니다.
PUT /customer/123/inactive
{
... // entity fields here except id and status
}
고객 자원에 대한 개념적 하위 자원을 작성 중입니다. 또한 Roy Fielding의 자원에 대한 정의와 일치합니다. “… 자원은 특정 시점에서 맵핑에 해당하는 엔티티가 아닌 엔티티 세트에 대한 개념적 맵핑입니다.” 개념적 매핑은 status = ACTIVE 인 고객에게 능동적 인 고객입니다.
읽기 조작 :
GET /customer/123/active
GET /customer/123/inactive
다른 호출 중 하나가 상태 404를 반환해야하는 즉시 해당 호출을 수행하면 성공적인 출력에는 암시 적 상태가 포함되지 않을 수 있습니다. 물론 GET / customer / 123? status = ACTIVE | INACTIVE를 사용하여 고객 리소스를 직접 쿼리 할 수 있습니다.
의미 체계가 혼동 될 수 있으므로 DELETE 작업이 흥미 롭습니다. 그러나이 개념 자원에 대해 해당 조작을 공개하지 않거나 비즈니스 논리에 따라이를 사용할 수 있습니다.
DELETE /customer/123/active
이를 통해 고객을 삭제 / 비활성화 상태 또는 반대 상태 (ACTIVE / INACTIVE)로 전환 할 수 있습니다.
답변
확장 된 질문에 추가 할 사항. 더 복잡한 비즈니스 활동을 완벽하게 설계 할 수 있다고 생각합니다. 그러나 당신은 사고 방식 / 절차 스타일을 제시하고 자원과 동사에 대해 더 많이 생각해야합니다.
메일 발송
POST /customers/123/mails
payload:
{from: x@x.com, subject: "foo", to: y@y.com}
이 자원 + POST의 구현은 메일을 발송합니다. 필요한 경우 / customer / 123 / outbox와 같은 것을 제공 한 다음 / customer / mails / {mailId}에 대한 리소스 링크를 제공 할 수 있습니다.
고객 수
검색 리소스처럼 처리 할 수 있습니다 (페이징이 포함 된 검색 메타 데이터 및 고객 수를 제공하는 num-found 정보 포함).
GET /customers
response payload:
{numFound: 1234, paging: {self:..., next:..., previous:...} customer: { ...} ....}
답변
불완전한 / 부분 리소스를 업데이트하려면 PUT을 사용하십시오.
jObject를 매개 변수로 승인하고 해당 값을 구문 분석하여 자원을 업데이트 할 수 있습니다.
다음은 참조로 사용할 수있는 기능입니다.
public IHttpActionResult Put(int id, JObject partialObject)
{
Dictionary<string, string> dictionaryObject = new Dictionary<string, string>();
foreach (JProperty property in json.Properties())
{
dictionaryObject.Add(property.Name.ToString(), property.Value.ToString());
}
int id = Convert.ToInt32(dictionaryObject["id"]);
DateTime startTime = Convert.ToDateTime(orderInsert["AppointmentDateTime"]);
Boolean isGroup = Convert.ToBoolean(dictionaryObject["IsGroup"]);
//Call function to update resource
update(id, startTime, isGroup);
return Ok(appointmentModelList);
}