Development Tip

REST : 하나의 요청으로 여러 리소스 업데이트-표준입니까 아니면 피해야합니까?

yourdevel 2020. 12. 5. 10:45
반응형

REST : 하나의 요청으로 여러 리소스 업데이트-표준입니까 아니면 피해야합니까?


간단한 REST API :

  • GET : items / {id}-주어진 ID를 가진 항목에 대한 설명을 반환합니다.
  • PUT : items / {id}-지정된 ID로 항목을 업데이트하거나 생성합니다.
  • DELETE : items / {id}-주어진 ID를 가진 항목을 삭제합니다.

이제 문제의 API 확장 :

  • GET : items? filter-필터와 일치하는 모든 항목 ID를 반환합니다.
  • PUT : 항목-JSON 페이로드에 설명 된대로 항목 집합을 업데이트하거나 만듭니다.
  • [[ DELETE : items-JSON 페이로드에 설명 된 항목 목록을 삭제합니다. ]] <- 올바르지 않음

이제 PUT / DELETE 항목 / {id}에서 쉽게 액세스 할 수있는 DELETE 및 PUT 작업 재활용 기능에 관심이 있습니다.

질문 : 이와 같은 API를 제공하는 것이 일반적입니까?

대안 : 단일 연결 시대에서 다중 요청을 발행하는 것은 저렴하고 변경이 성공하거나 실패하기 때문에 더 원자 적으로 작동하지만 NOSQL 데이터베이스 시대에는 요청 처리가 다음과 같이 종료 되더라도 목록의 변경이 이미 발생했을 수 있습니다. 내부 서버 또는 어떤 이유로 든.

[최신 정보]

백악관 웹 표준위키 백과 : REST 예제를 고려한 후 이제 다음 예제 API가 사용됩니다.

간단한 REST API :

  • GET : items / {id}-주어진 ID를 가진 항목에 대한 설명을 반환합니다.
  • PUT : items / {id}-지정된 ID로 항목을 업데이트하거나 생성합니다.
  • DELETE : items / {id}-주어진 ID를 가진 항목을 삭제합니다.

최고의 리소스 API :

  • GET : items? filter-필터와 일치하는 모든 항목 ID를 반환합니다.
  • POST : items-JSON 페이로드에 설명 된대로 항목 세트를 업데이트하거나 생성합니다.

/ items에 대한 PUT 및 DELETE는 지원되지 않으며 금지됩니다.

POST를 사용하면 둘러싸는 리소스에 새 항목을 만들면서 교체하지 않고 추가하는 것처럼 트릭을 수행하는 것 같습니다.

HTTP 의미 체계 POST 읽기 :

추가 작업을 통해 데이터베이스 확장

HTTP Semantics PUT에서 인용 한 것과 동일한 표현을 반환하기 위해 PUT 메서드가 전체 컬렉션을 대체해야하는 경우 :

주어진 표현의 성공적인 PUT는 동일한 대상 리소스에 대한 후속 GET이 200 (OK) 응답으로 반환되는 동등한 표현을 초래할 것임을 제안합니다.

[업데이트 2]

여러 개체의 업데이트 측면에서 훨씬 더 일관된 것으로 보이는 대안은 PATCH 방법 인 것 같습니다. PUT와 PATCH의 차이점은 RFC 5789 초안 에 다음과 같이 설명되어 있습니다 .

PUT 요청과 PATCH 요청의 차이는 요청 URI에 의해 식별 된 리소스를 수정하기 위해 서버가 동봉 된 엔티티를 처리하는 방식에 반영됩니다. PUT 요청에서 포함 된 엔티티는 원본 서버에 저장된 리소스의 수정 된 버전으로 간주되고 클라이언트는 저장된 버전의 교체를 요청합니다. 그러나 PATCH를 사용하면 포함 된 엔터티에는 현재 원본 서버에있는 리소스가 새 버전을 생성하기 위해 수정되어야하는 방법을 설명하는 일련의 지침이 포함됩니다. PATCH 방법은 Request-URI에 의해 식별 된 리소스에 영향을 미치며 다른 리소스에도 부작용이있을 수 있습니다. 즉, PATCH의 적용에 의해 새로운 자원이 생성되거나 기존 자원이 수정 될 수 있습니다.

따라서 POST와 비교할 때 PATCH는 UPDATE를 허용하기 때문에 PATCH는 수정의 기회없이 추가 할 의미를 추가하는 것만 허용하는 UPDATE를 허용하기 때문에 더 나은 아이디어 일 수 있습니다.

따라서 POST는 여기서 잘못된 것으로 보이며 제안 된 API를 다음과 같이 변경해야합니다.

간단한 REST API :

  • GET : items / {id}-주어진 ID를 가진 항목에 대한 설명을 반환합니다.
  • PUT : items / {id}-지정된 ID로 항목을 업데이트하거나 생성합니다.
  • DELETE : items / {id}-주어진 ID를 가진 항목을 삭제합니다.

최고의 리소스 API :

  • GET : items? filter-필터와 일치하는 모든 항목 ID를 반환합니다.
  • POST : items-JSON 페이로드에 설명 된대로 하나 이상의 항목을 생성합니다.
  • PATCH : items-JSON 페이로드에 설명 된대로 하나 이상의 항목을 생성하거나 업데이트합니다.

컬렉션을 패치 할 수 있습니다. 예 :

PATCH /items
[ { id: 1, name: 'foo' }, { id: 2, name: 'bar' } ]

기술적으로 PATCH는 URL (즉 /items/1, 요청 본문이 아닌 PATCH)에서 레코드를 식별 하지만 이는 좋은 실용적인 솔루션처럼 보입니다.

단일 호출에서 삭제, 생성 및 업데이트를 지원하기 위해 표준 REST 규칙에서는 실제로 지원되지 않습니다. 한 가지 가능성은 호출을 함께 조합 할 수있는 특별한 "일괄"서비스입니다.

POST /batch
[
  { method: 'POST', path: '/items', body: { title: 'foo' } },
  { method: 'DELETE', path: '/items/bar' }
]

포함 된 각 요청에 대한 상태 코드가있는 응답을 반환합니다.

[ 200, 403 ]

실제로 표준은 아니지만 나는 그것을 해왔고 작동합니다.


하나의 요청으로 여러 리소스 업데이트-표준입니까 아니면 피해야합니까?

글쎄, 때로는 단순한 REST API의 일반적인 체계에 맞지 않는 원자 배치 작업 또는 기타 리소스 관련 작업을 수행해야 할 때가 있지만 필요한 경우 피할 수 없습니다.

표준입니까?

There is no universally accepted REST API standard so this question is hard to answer. But by looking at some commonly quoted api design guidelines, such as jsonapi.org, restfulapi.net, microsoft api design guide or IBM's REST API Conventions, which all do not mention batch operations, you can infer that such operations are not commonly understood as being a standard feature of REST APIs.

That said, an exception is the google api design guide which mentions the creation of "custom" methods that can be associated via a resource by using a colon, e.g. https://service.name/v1/some/resource/name:customVerb, it also explicitly mentions batch operations as use case:

A custom method can be associated with a resource, a collection, or a service. It may take an arbitrary request and return an arbitrary response, and also supports streaming request and response. [...] Custom methods should use HTTP POST verb since it has the most flexible semantics [...] For performance critical methods, it may be useful to provide custom batch methods to reduce per-request overhead.

So in the example case you provided you do the following according to google's api guide:

POST /api/items:batchUpdate

Also, some public APIs decided to offer a central /batch endpoint, e.g. google's gmail API.

Moreover, as mentioned at restfulapi.net, there is also the concept of a resource "store", in which you store and retrieve whole lists of items at once via PUT – however, this concept does not count for server-managed resource collections:

A store is a client-managed resource repository. A store resource lets an API client put resources in, get them back out, and decide when to delete them. A store never generates new URIs. Instead, each stored resource has a URI that was chosen by a client when it was initially put into the store.


Having answered your original questions, here is another approach to your problem that has not been mentioned yet. Please note that this approach is a bit unconventional and does not look as pretty as the typical REST API endpoint naming scheme. I am personally not following this approach but I still felt it should be given a thought :)

The idea is that you could make a distinction between CRUD operations on a resource and other resource-related operations (e.g. batch operations) via your endpoint path naming scheme.

For example consider a RESTful API that allows you to perform CRUD operations on a "company"-resource and you also want to perform some "company"-related operations that do not fit in the resource-oriented CRUD-scheme typically associated with restful api's – such as the batch operations you mentioned.

Now instead of exposing your resources directly below /api/companies (e.g. /api/companies/22) you could distinguish between:

  • /api/companies/items – i.e. a collection of company resources
  • /api/companies/ops – i.e. operations related to company resources

For items the usual RESTful api http-methods and resource-url naming-schemes apply (e.g. as discussed here or here)

POST    /api/companies/items
GET     /api/companies/items
GET     /api/companies/items/{id}
DELETE  /api/companies/items/{id}
PUT     /api/companies/items/{id}

Now for company-related operations you could use the /api/companies/ops/ route-prefix and call operations via POST.

POST    /api/companies/ops/batch-update
POST    /api/companies/ops/batch-delete
POST    /api/companies/ops/garbage-collect-old-companies
POST    /api/companies/ops/increase-some-timestamps-just-for-fun
POST    /api/companies/ops/perform-some-other-action-on-companies-collection

Since POST requests do not have to result in the creation of a resource, POST is the right method to use here:

The action performed by the POST method might not result in a resource that can be identified by a URI. https://tools.ietf.org/html/rfc2616#section-9.5


As far as I understand the REST concept it covers an update of multiple resources with one request. Actually the trick here is to assume a container around those multiple resources and take it as one single resource. E.g. you could just assume that list of IDs identifies a resource that contains several other resources.

In those examples in Wikipedia they also talk about resources in Plural.

참고URL : https://stackoverflow.com/questions/32098423/rest-updating-multiple-resources-with-one-request-is-it-standard-or-to-be-avo

반응형