2011-08-18 3 views
154

REST 기반 API의 개념을 해결하는 가장 좋은 방법을 고민하고 있습니다. 다른 리소스를 포함하지 않는 플랫 리소스는 문제가되지 않습니다. 내가 곤경에 처하게되는 곳은 복잡한 자원이다.REST 복합/합성/중첩 리소스

예를 들어 나는 ComicBook 용 리소스가 있습니다. 만화책에는 작가, 발행 번호, 날짜 등 모든 종류의 속성이 있습니다.

만화책에는 1..n 표지 목록이 있습니다. 이 덮개는 복잡한 객체입니다. 여기에는 표지, 아티스트, 날짜 및 표지의 기본 64 인코딩 이미지에 대한 많은 정보가 포함되어 있습니다.

만화책에서 GET을하면 나는 만화와 그 base64'ed 이미지를 포함한 모든 표지를 반환 할 수 있습니다. 그것은 아마 하나의 만화를 얻는 것에 큰 문제가되지 않을 것입니다. 그러나 테이블에있는 시스템에있는 모든 만화를 나열하고자하는 클라이언트 응용 프로그램을 작성한다고 가정합니다. 이 테이블에는 ComicBook 리소스의 몇 가지 속성이 포함되어 있지만 테이블의 모든 커버를 표시하고 싶지는 않습니다. 1000 장의 만화책을 여러 장씩 나눠 쓰면, 여러 장의 표지가있는 경우 엄청나게 많은 양의 데이터가 유출 될 수 있습니다.이 경우 데이터는 최종 사용자에게는 필요하지 않습니다.

본능은 Cover를 리소스로 만들고 ComicBook에는 커버가 포함되어 있습니다. 이제 Cover는 URI입니다. 이제 만화책에서 GET하면 거대한 Cover 자원 대신에 각 표지에 URI를 보내고 클라이언트는 Cover 자원을 필요할 때 검색 할 수 있습니다.

이제 새로운 만화를 만드는 데 문제가 있습니다. 분명히 만화를 만들 때 최소한 하나의 표지를 만들고 싶습니다. 실제로는 아마도 비즈니스 규칙 일 것입니다. 이제 막 갇혔어요. 나는 클라이언트가 먼저 Cover를 제출하고, 그 Cover의 URI를 얻은 다음, 목록에있는 URI를 가진 ComicBook을 게시하거나, ComicBook의 POST가 다른보기를 취함으로써 비즈니스 규칙을 시행하도록합니다. 자원이 뱉어내는 것보다. POST 및 GET의 들어오는 리소스는 딥 복사본이며, 보내는 GET에는 종속 리소스에 대한 참조가 들어 있습니다.

어떤 경우에는 커버 리소스 방향을 지정하고 싶기 때문에 Cover 리소스가 필요할 수 있습니다. 따라서 문제는 종속 리소스의 크기에 관계없이 일반적인 형식으로 존재합니다. 일반적으로 복잡한 리소스는 클라이언트가 리소스 구성 방법을 "알기"만하지 않고 어떻게 처리합니까?

+0

[RESTFUL SERVICE DISCOVERY] (http://barelyenough.org/blog/2008/01/restful-service-discovery-and-description/)를 사용합니까? – treecoder

+1

나는 HATEAOS를 고수하려고 노력하고 있는데, 나는 내 마음 속에서 그런 것을 사용하는 것에 반대한다.하지만 나는 그것을 살펴볼 것이다. – jgerman

+0

같은 정신으로 다른 질문입니다. 그러나 소유권은 제안 된 솔루션과 다릅니다 (문제의 하나). http://stackoverflow.com/questions/20951419/what-are-best-practices-for-rest-nested-resources – Wes

답변

37

표지로 자원을 처리하는 것은 확실히 REST의 정신, 특히 HATEOAS입니다. 그래서 예, GET 요청은 http://example.com/comic-books/1으로 커버에 대한 URI 세트를 포함하는 속성으로 책 1의 표현을 제공합니다. 여태까지는 그런대로 잘됐다.

귀하의 질문은 만화책 제작을 다루는 방법입니다. 말할 수 (새로운 만화책을 작성하고 서버 생성 된 ID를 반환합니다 coverless 만화 데이터

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

: 비즈니스 규칙이 책 0 개 이상의 커버를 것이라고했다 경우에, 당신은 아무 문제가 없다 그것은 다시 8)을 제공하고, 지금 당신과 같이 여기에 커버를 추가 할 수 있습니다

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

를 엔터티 본문의 커버.

이제 비즈니스 규칙에 항상 최소한 하나의 표지가 있어야한다고 말하면 무슨 일이 일어나는 지 알 수 있습니다.

  1. 이 먼저 커버의 생성을 강제 지금은 본질적으로 만드는 비에 의존하는 자원을 포함하거나 엔터티 본문에 초기 커버를 배치 : 다음은 질문에서 확인 된 최초의 어느 일부 선택이다 만화책을 만드는 POST의 이것은 당신이 말하는 것처럼 당신이 만드는 POST 표현은 당신이 얻은 표현과 다를 것입니다.

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

단순히 커버 리없는 만화를 허용하는 것에는이 두 가지를 고려해야합니다.

3 가지 중 어느 것을 선택해야합니까? 당신의 상황에 대해 너무 많이 알고 있지만, 일반적으로 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> 

당신이 게시 할 때 당신이 (다른 책에서 차용)뿐만 아니라 하나 개 이상의 초기 이미지에 넣어 그들을있는 경우가 URI를 기존의 수 있습니다. 책을 만들고 엔티티에 초기 표지 이미지가없는 경우 409 또는 유사한 응답을 반환합니다. GET에서 URI를 반환 할 수 있습니다.

기본적으로 POST와 GET 표현을 "동일하게"허용하지만 GET에서 표지 이미지를 사용하거나 POST에서 표지를 사용하지 않도록 선택합니다. 희망은 그 말이 맞습니다.

58

@ray, 우수한 토론

@jgerman, 그것은 REST를 그냥 때문에, 자원 POST에서 돌에 설정해야 의미하지 않는다는 것을 잊지 마세요.

리소스의 임의 표현에 포함하기로 선택한 것은 귀하에게 달려 있습니다.

별도로 언급 한 표지의 경우는 하위 리소스 (표지)가 상호 참조 될 수있는 상위 리소스 (만화책)를 만드는 것일뿐입니다. 예를 들어 작성자, 게시자, 캐릭터 또는 카테고리에 대한 참조를 별도로 제공 할 수도 있습니다. 이러한 리소스를 별도로 만들거나 자식 리소스로 참조하는 만화책 앞에 만들 수 있습니다. 또는 상위 리소스를 만들 때 새 하위 리소스를 만들 수도 있습니다.커버의

특정 경우는 그 반대로 약간 더 커버 정말 만화를 필요로하지 점에서 복잡하고있다. 당신은 이메일 리소스로 메시지 등을 고려하는 경우

그러나, 아이 리소스와 같은 주소에서, 당신은 분명히 여전히 개별적으로 주소에서 참조 할 수 있습니다. 예를 들어, 모두 주소에서 가져 오기. 또는 이전 보낸 사람 주소로 새 메시지를 만듭니다. 이메일이 REST 인 경우/수신 메일, 임시 보관 메일,/보낸 사람 주소,/보낸 사람 주소,/주소,/제목,/첨부 파일,/폴더 등 많은 상호 참조 리소스를 사용할 수 있음을 쉽게 알 수 있습니다. ,/태그,/카테고리,/레이블 등.

이 튜토리얼은 상호 참조 자원의 좋은 예를 제공합니다. http://www.peej.co.uk/articles/restfully-delicious.html

이것은 자동으로 생성 된 데이터를위한 가장 일반적인 패턴이다. 예를 들어 새 자원에 대한 URI, ID 또는 작성 날짜는 서버에서 생성하므로 게시하지 마십시오. 그리고 새 리소스를 다시 얻으면 URI, ID 또는 생성 날짜를 검색 할 수 있습니다.

이진 데이터의 귀하의 경우 예. 예를 들어 이진 데이터를 하위 리소스로 게시하려고합니다. 상위 리소스를 얻으면 해당 하위 리소스를 동일한 이진 데이터 또는 이진 데이터를 나타내는 URI로 나타낼 수 있습니다.

양식 & 매개 변수는 이미 자원의 HTML 표현 다릅니다. 바이너리/파일 매개 변수를 게시하면 URL이됩니다.

새 리소스 (/ comic-books/new)의 양식을 가져 오거나 리소스 편집 양식 (/ comic-books/0/edit)을 얻으면 양식 별 표현을 요구하는 것입니다 자원의 컨텐츠 유형이 "application/x-www-form-urlencoded"또는 "multipart/form-data"인 자원 콜렉션에 게시하는 경우, 서버에 해당 유형 표현을 저장하도록 요청할 것입니다. 서버는 저장된 HTML 표현으로 응답 할 수 있습니다.

API 용도로 HTML, XML 또는 JSON 표현을 자원 콜렉션에 게시 할 수도 있습니다.

만화책 다음에 게시되는 표지를 고려하면서 설명대로 자원 및 워크 플로를 나타내지 만 만화책에는 표지가 있어야합니다. 예제는 다음과 같습니다.

  • 이 지연 커버 제작을 할 수 있습니다
  • 수 있습니다
  • 는 커버가 교차 참조
  • 여러 커버
  • 초안 만화를 만들기 초안 만화를 생성 할 수 있습니다 될 수 있도록 필요한 커버 만화 제작 커버
  • 초안 만화 게시

GET/만화책
=> 200 좋아, 모든 만화책을 구하십시오.

GET/만화책/0
=> 200 OK, 커버 (/ 커버/1,/커버/2)가 포함 된 만화책 (id : 0)을 가져옵니다.

GET/만화책/0/표지
=> 200 OK, 만화책 표지 (id : 0)를 받으십시오.

GET/covers
=> 200 OK, 모든 표지를 받으십시오.

GET/covers/1
=> 200 OK, 만화책 (/ 만화책/0)으로 표지 (ID : 1)를 받으십시오.

GET/만화책/신품
=> 200 OK, 만화책 (양식 : POST/draft-comic-books)을 만들기위한 양식을 얻으십시오.

POST/초안 만화 책
제목 = foo는
저자 = 야유
발행인 = 끈적 거리는
출판 = 2011-01-01
=> 302 발견 위치 :/초안 만화 책/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/초안 만화 책/3/커버/새로운
=> 200 OK, 초안 만화 책 표지를 만드는 형태를 가져옵니다 (/ 초안 만화책/3) (양식 : POST/draft- 만화책/3/표지)./초안 코믹 책/3/커버 새로 리디렉션 :

POST/초안 코믹 책/3 /은
cover_type 전면
가 cover_data = (바이너리)
=> 302 발견 위치 = 커버 만화책 초안 표지 (/ draft-comic-book/3/covers/1).

GET은/초안 만화 책/3/초안을 만화 (ID : 3) 게시 할 양식을 얻기,
=> 200 OK를 게시 (양식 : POST/출판 - 만화 - 책).

POST/출판 - 만화 책
제목 = foo는
저자는 야유
이 발행인 = 끈적 거리는
출판 = 2011-01-01
cover_type = 전면
cover_data = (진)
= > 302 발견, 위치 :/만화책/3, 표지가있는 출판 된 만화책 (id : 3)으로 리디렉션.

+0

나는 이것에 총 초심자이고, 그것을 서둘러 배우려고 노력하고있다. 나는 이것이 매우 도움이되는 것을 알았다. 그러나, 내가 오늘 읽고있는 다른 블로그 등에서, 조작 (특히 멱등수가 아닌 조작)을 수행하기위한 GET의 사용은 눈살을 찌푸리게 될 것입니다. 그래서 그것은 POST/draft-comic-books/3/publish가되어서는 안됩니까? –

+3

@GaryMcGill 그의 예에서/draft-comic-books/3/publish는 HTML 양식 만 반환합니다 (데이터는 수정하지 않음). –

+0

@Olivier가 정확합니다. 게시라는 단어는 양식의 의미를 나타냅니다. 그러나 HTTP 메소드에 한정된 동사를 유지하려는 경우, 게시 된 만화에 대한 자원에 게시해야합니다. ... 이것이 웹 사이트 인 경우 양식을 게시하기 위해 URI가 필요할 수 있습니다. ... 게시 작업이 만화 페이지의 단 하나의 단추 일 경우 단일 단추 양식이 직접/게시 된 만화 책 URI에 게시 될 수 있습니다. – Alex