[api] REST Complex / Composite / Nested Resources [폐쇄]

REST 기반 API에서 개념을 해결하는 가장 좋은 방법으로 머리를 감싸려고합니다. 다른 자원을 포함하지 않는 플랫 자원은 문제가되지 않습니다. 내가 곤경에 처한 곳은 복잡한 자원입니다.

예를 들어, 만화책에 대한 자료가 있습니다. ComicBook그것을 좋아에 속성의 모든 종류를 가지고 author, issue number,date , 등

만화책에는 1..n표지 목록도 있습니다. 이 표지는 복잡한 개체입니다. 그들은 표지에 대한 많은 정보를 포함하고 있습니다 : 예술가, 날짜, 심지어 표지의 기본 64 인코딩 이미지.

경우 a GETComicBook 난 그냥 만화를 반환하고, 자신의 base64’ed 이미지를 포함하여 커버의 모든 수 있습니다. 단일 만화를 얻는 데 큰 도움이되지는 않을 것입니다. 그러나 시스템의 모든 만화를 테이블에 나열하려는 클라이언트 앱을 작성한다고 가정하십시오.
표에는 몇 가지 속성이 포함됩니다.ComicBook 리소스 되지만 테이블의 모든 표지를 표시하지는 않을 것입니다. 각각 표지가 여러 개인 만화책 1000 개를 반환하면 엄청나게 많은 양의 데이터가 전송되며 최종 사용자에게는 필요하지 않은 데이터가 발생합니다.

나의 본능은 Cover자원 을 만들고 ComicBook덮개를 포함하는 것입니다. 이제 CoverURI입니다.GET만화책에서 지금 작동합니다. 거대한 Cover리소스 대신 각 표지에 대한 URI를 다시 보내면 클라이언트가 필요에 따라 표지 리소스를 검색 할 수 있습니다.

이제 새로운 만화를 만드는 데 문제가 있습니다. 확실히 나는을 만들 때 적어도 하나의 커버를 만들고 싶습니다 Comic. 사실 그것은 아마도 비즈니스 규칙 일 것입니다.
그래서 지금은 나도 처음을 제출하여 비즈니스 규칙을 적용 할 클라이언트를 붙어 강제하고있어 Cover다음, 그 커버의 URI를 받고, POSTA는 보내고 ComicBook목록에서 URI, 또는 내 것을 함께 POST에가 ComicBook다른 찾고 자원의 소요가 옷을 사는 것보다 밖. 대한 들어오는 자원 POSTGET발신 전체 복사본입니다 GET의 의존 자원에 대한 참조를 포함합니다.

Cover내가 어떤 경우에는 주소 커버 방향 싶어 클라이언트로 확신하기 때문에 자원은 아마 어떤 경우에 필요하다. 따라서 문제는 종속 리소스의 크기에 관계없이 일반적인 형태로 존재합니다. 일반적으로 클라이언트가 이러한 리소스가 어떻게 구성되어 있는지 “알지”않고 복잡한 리소스를 어떻게 처리합니까?



답변

@ 레이, 훌륭한 토론

@jgerman은 REST이기 때문에 POST에서 리소스를 스톤으로 설정해야한다는 것을 잊지 마십시오.

주어진 리소스 표현에 포함 시키기로 선택한 것은 귀하에게 달려 있습니다.

개별적으로 언급 된 표지의 경우는 하위 자원 (표지)이 상호 참조 될 수있는 상위 자원 (만화)을 작성하는 것입니다. 예를 들어 저자, 출판사, 캐릭터 또는 카테고리에 대한 참조를 별도로 제공 할 수도 있습니다. 이러한 리소스를 별도로 또는 만화로 만들기 전에 하위 리소스로 참조 할 수 있습니다. 또는 부모 리소스를 만들 때 새 자식 리소스를 만들 수도 있습니다.

표지의 특정 사례는 표지에 실제로 만화책이 필요하고 그 반대의 경우도 있기 때문에 약간 더 복잡합니다.

그러나 전자 메일 메시지를 리소스로, 보낸 사람 주소를 자식 리소스로 생각하는 경우에는 여전히 보낸 사람 주소를 개별적으로 참조 할 수 있습니다. 예를 들어 주소에서 모두 가져옵니다. 또는 이전 발신 주소로 새 메시지를 작성하십시오. 이메일이 REST 인 경우 / received-messages, / draft-messages, / from-addresses, / to-addresses, / addresses, / subjects, / attachments, / folders와 같이 여러 상호 참조 된 리소스를 사용할 수 있음을 쉽게 알 수 있습니다. , / tags, / categories, / labels 등

이 학습서는 상호 참조 된 자원의 좋은 예를 제공합니다.
http://www.peej.co.uk/articles/restfully-delicious.html

자동 생성 된 데이터에 가장 일반적인 패턴입니다. 예를 들어 새 리소스에 대한 URI, ID 또는 생성 날짜는 서버에서 생성하므로 게시하지 않습니다. 그러나 새 리소스를 다시 가져올 때 URI, ID 또는 생성 날짜를 검색 할 수 있습니다.

이진 데이터의 예입니다. 예를 들어 이진 데이터를 자식 리소스로 게시하려고합니다. 상위 자원을 확보하면 해당 하위 자원을 동일한 2 진 데이터 또는 2 진 데이터를 나타내는 URI로 나타낼 수 있습니다.

양식 및 매개 변수는 이미 리소스의 HTML 표현과 다릅니다. URL을 생성하는 이진 / 파일 매개 변수를 게시하는 것은 쉽지 않습니다.

새 자원 (/ comic-books / new)에 대한 양식을 얻거나 자원을 편집하기위한 양식 (/ comic-books / 0 / edit)을 받으면 양식의 자원에 대한 표현을 요구합니다. 컨텐츠 유형이 “application / x-www-form-urlencoded”또는 “multipart / form-data”인 자원 콜렉션에 게시하는 경우 서버에 해당 유형 표시를 저장하도록 요청합니다. 서버는 저장된 HTML 표현 등으로 응답 할 수 있습니다.

API 등의 목적으로 HTML, XML 또는 JSON 표현이 자원 콜렉션에 게시되도록 할 수도 있습니다.

또한 만화책 뒤에 게시 된 표지를 고려하면서 설명하면서 자원과 워크 플로우를 표현할 수 있지만, 만화책에는 표지가 있어야합니다. 예를 들면 다음과 같습니다.

  • 지연된 표지 생성 허용
  • 필요한 표지로 만화책 제작 가능
  • 표지를 상호 참조 할 수 있습니다
  • 여러 커버를 허용
  • 초안 만화 만들기
  • 임시 만화책 표지 작성
  • 초안 만화 출판

GET / comic-books
=> 200 OK, 모든 만화책을 얻으십시오.

GET / comic-books / 0
=> 200 OK, 표지 (/ covers / 1, / covers / 2)와 함께 만화책 (id : 0)을 얻습니다.

GET / comic-books / 0 / covers
=> 200 OK, 만화책 표지를 얻습니다 (ID : 0).

GET / covers
=> 200 OK, 모든 표지를 얻습니다.

GET / covers / 1
=> 200 OK, 만화책 (/ comic-books / 0)으로 표지 (id : 1)를 얻습니다.

GET / comic-books / new
=> 200 OK, 만화책을 만들 양식을 얻습니다 (형식 : POST / draft-comic-books).

POST / draft-comic-books
title = foo
author = boo
publisher = goo
게시 = 2011-01-01
=> 302 찾은 위치 : / draft-comic-books / 3, 다음으로 초안 만화 (ID : 3)로 리디렉션 커버 (이진).

GET / draft-comic-books / 3
=> 200 OK, 표지가있는 만화책 초안 (ID : 3)을 가져옵니다.

GET / draft-comic-books / 3 / covers
=> 200 OK, 초안 만화 (/ draft-comic-book / 3)에 대한 표지를 얻습니다.

GET / draft-comic-books / 3 / covers / new
=> 200 OK, 만화 초안 (/ draft-comic-book / 3)에 대한 표지를 작성하는 양식 가져 오기 (형식 : POST / draft-comic-books / 3 / 커버).

POST / draft-comic-books / 3 / covers
cover_type = front
cover_data = (binary)
=> 302 찾은 위치 : / draft-comic-books / 3 / covers, 초안 만화 용 새 표지로 리디렉션 (/ draft-comic -도서 / 3 / 표지 / 1).

GET / draft-comic-books / 3 / publish
=> 200 OK, 초안 만화책을 발행 할 양식을 얻습니다 (ID : 3) (형식 : POST / published-comic-books).

POST / published-comic-books
title = foo
author = boo
publisher = goo
publish = 2011-01-01
cover_type = front
cover_data = (binary)
=> 302 찾은 위치 : / comic-books / 3, 게시 된 만화책으로 리디렉션 덮개가있는 (id : 3).


답변

커버를 리소스로 취급하는 것은 확실히 REST, 특히 HATEOAS의 정신에 있습니다. 예,GEThttp://example.com/comic-books/1 표지에 대한 URI 세트를 포함하는 특성과 함께 책 1의 표현을 제공 하라는 요청이 있습니다. 여태까지는 그런대로 잘됐다.

귀하의 질문은 만화책 제작을 다루는 방법입니다. 비즈니스 규칙에 따라 책의 표지 가 0 개 이상이면 문제가 없습니다.

POST http://example.com/comic-books

표지가없는 만화 데이터를 사용하면 새 만화책이 생성되고 서버에서 생성 한 ID (8로 돌아옴)가 반환되고 이제 다음과 같이 표지를 추가 할 수 있습니다.

POST http://example.com/comic-books/8/covers

엔터티 본문에 덮개가있는

이제 비즈니스 규칙에 항상 커버가 하나 이상 있어야한다고 말하는 경우에 좋은 질문이 있습니다. 다음은 몇 가지 선택 사항이며, 첫 번째는 질문에서 식별 된 것입니다.

  1. 표지를 먼저 작성하여 강제로 표지를 비 종속 자원으로 만들거나 만화책을 작성하는 POST의 엔티티 본문에 초기 표지를 배치하십시오. 이것은 당신이 말한 POST 생성 표현이 GET 표현과 다르다는 것을 의미합니다.

  2. 기본, 초기 또는 선호 또는 다르게 지정된 표지의 개념을 정의하십시오. 이것은 모델링 해킹 일 가능성이 높으며, 그렇게하면 기술에 맞게 개체 모델 (개념적 또는 비즈니스 모델)을 조정하는 것과 같습니다. 좋은 생각이 아닙니다.

단순히 커버리스 만화를 허용하는 것과 비교하여이 두 가지 선택을 평가해야합니다.

세 가지 중 어떤 것을 선택해야합니까? 귀하의 상황에 대해 너무 많이 알지 못하지만 일반적인 1..N 종속 자원 질문에 대답하십시오.

  • RESTful 서비스 계층에 0..N을 사용할 수 있다면 좋습니다. RESTful SOA 사이의 계층은 최소한 하나 이상이 필요한 경우 추가 비즈니스 제약 조건을 처리 할 수 ​​있습니다. (어떻게 보일지 모르겠지만 살펴볼 가치가있을 것이다 … 최종 사용자는 보통 SOA를 보지 못한다.)

  • 1..N 제약 조건을 모델링해야하는 경우 표지가 공유 가능한 리소스인지, 즉 만화 이외의 다른 곳에있을 수 있는지 스스로에게 묻습니다. 이제는 종속 리소스가 아니므로 먼저 리소스를 만들고 POST에 만화를 만드는 URI를 제공 할 수 있습니다.

  • 1.N이 필요하고 표지가 의존적 인 경우 POST의 표현을 동일하게 유지하거나 동일하게 유지하려면 본능을 완화하십시오.

마지막 항목은 다음과 같이 설명됩니다.

<comic-book>
  <name>...</name>
  <edition>...</edition>
  <cover-image>...BASE64...</cover-image>
  <cover-image>...BASE64...</cover-image>
  <cover>...URI...</cover>
  <cover>...URI...</cover>
</comic-book>

POST 할 때 기존 uri가 있으면 (다른 책에서 빌려온) 하나 이상의 초기 이미지를 넣을 수 있습니다. 책을 작성 중이고 엔티티에 초기 표지 이미지가없는 경우 409 또는 이와 유사한 응답을 리턴하십시오. GET에서는 URI를 반환 할 수 있습니다.

따라서 기본적으로 POST와 GET 표현은 “동일하게”허용하지만 GET의 표지 이미지 나 POST의 표지 이미지를 “사용”하지 않기로 선택합니다. 이해가 되길 바랍니다.


답변