REST API가 여러 자원을 하나의 단일 복합 자원으로 리턴 할 수 있습니까?


10

REST API를 작성하는 중이며 현재 다음과 같은 문제가 발생합니다.

  • Foo첫 번째 리소스입니다. CRUD 작업은 /foo/URI 를 통해 적용 할 수 있습니다 .
  • Bar두 번째 자원입니다. CRUD 작업은 /bar/URI 를 통해 적용 할 수 있습니다 .
  • 모든 Foo것은 0 또는 1과 연관됩니다 Bar. 내가 Bar하위 리소스로 취급하지 않는 Foo이유는 동일한 Bar인스턴스가 여러 인스턴스간에 공유 될 수 있기 때문 Foo입니다. 그래서 대신에 독립 URI를 통해 액세스하는 것이 더 낫다고 생각했습니다 /foo/[id]/bar.

내 문제는 상당량의 경우 Foo인스턴스 를 요청하는 클라이언트 도 관련 Bar인스턴스에 관심이 있다는 것입니다 . 현재 이것은 하나 대신 두 개의 쿼리를 수행해야 함을 의미합니다. 하나의 쿼리로 두 객체를 모두 얻을 수있는 방법을 소개하고 싶지만 API를 모델링하는 방법을 모르겠습니다. 내가 지금까지 생각해 낸 것 :

  • 다음과 비슷한 쿼리 매개 변수를 도입 할 수 /foo/[id]?include_bar=true있습니다. 이 접근법의 문제점은 응답의 자원 표현 (예 : JSON 구조)이 다르게 보일 필요가 있고 (예를 들어 { foo: ..., bar: ... }직렬화 된 대신 컨테이너와 같은 Foo) Foo자원 엔드 포인트를 "이질적"으로 만드는 것 입니다. 나는 그것이 좋은 것이라고 생각하지 않습니다. 쿼리 할 때 /foo클라이언트는 쿼리 매개 변수에 관계없이 항상 동일한 리소스 표현 (구조)을 가져와야합니다.
  • 또 다른 아이디어는 새로운 읽기 전용 엔드 포인트를 도입하는 것입니다 (예 :) /fooandbar/[foo-id]. 이 경우, 리소스 { foo: ..., bar: ... }의 "공식적인"표현이기 때문에과 같은 표현을 반환하는 것은 문제가되지 않습니다 fooandbar. 그러나 그러한 도우미 끝 점이 실제로 RESTful인지는 모르겠습니다 (이것이 질문의 제목에 "can"이라고 쓴 이유입니다. 물론 기술적으로 가능하지만 좋은 아이디어인지는 알 수 없습니다).

어떻게 생각해? 다른 가능성이 있습니까?


Foo와 Bar의 관계에 대한 용어는 무엇입니까? Bar가 Foo의 부모라고 말할 수 있습니까?
Nathan Merrill

A는 BarA와 관련없이 존재할 수 없다 Foo. 그러나 위에서 쓴 것처럼 여러 Foo개가 동일한 공유 할 수 Bar있습니다. 관련 Foo없는없이 생성 할 수 있어야하므로 부모로 취급해서는 안된다고 Bar생각 Bar합니다.
ceran

1
도메인 모델 관계를 URI로 직접 변환하고 리소스도메인 엔터티 와 동일시함으로써 몇 가지 문제가 발생했다고 생각합니다 . 그것은 관심을 가질만한 REST API를 하이퍼 텍스트 기반이어야합니다 . 4 포인트에 특별한 관심
Laiv

답변:


6

레벨 3 REST API는 당신에게 반환 Foo관련 지시도 링크를 Bar.

GET /foo/123
<foo id="123">
  ..foo stuff..
  <link rel="bar" uri="/bar/456"/>
</foo>

그런 다음 API에 "드릴 다운"기능을 추가하여 링크를 탐색 할 수 있습니다.

GET /foo/123?drilldown=bar
<foo id="123">
  ..foo stuff..
  <link rel="bar" uri="/bar/456">
    <bar id="456">
      ..bar stuff...
    </bar>
  </link>
</foo>

드릴 다운 기능은 API 앞에 앉아 응답을 차단합니다. 응답을 호출자에게 다시 전달하기 전에 드릴 다운 호출을 작성하고 세부 사항을 입력합니다.

느린 http에 비해 클라이언트 / 서버 대화가 크게 줄어들 기 때문에 레벨 3 REST에서 매우 일반적입니다. 내가 일하는 회사는 정확히이 기능을 갖춘 레벨 3 REST API를 생성합니다.

업데이트 : 그 가치에 대해 JSON에서 어떻게 보일 수 있습니까? 이것이 우리 API가 그것을 구성하는 방법입니다. 드릴 다운을 중첩하여 링크 링크 등을 당길 수 있습니다.

GET /foo/123?drilldown=bar

{
  "self": {
    "type": "thing.foo",
    "uri": "/foo/123=?drilldown=bar",
    "href": "http://localhost/api/foo/123?drilldown=bar"
  },
  "links": [
    {
      "rel": "bar",
      "rev": "foo",
      "type": "thing.bar",
      "uri": "/bar/456",
      "href": "http://localhost/api/bar/456"
    }
  ],
  "_bar": [
    {
      "self": {
        "type": "thing.bar",
        "uri": "/bar/456",
        "href": "http://localhost/api/bar/456"
      },
      "links": [
        {
          ..other link..
        },
        {
          ..other link..
        }
      ]
    }
  ]
}

흥미롭게도, 이미 URI에 대한 긴밀한 연결을 제거하기 위해 하이퍼 미디어 링크 / 제어를 사용하고 있지만 매우 유망한 "드릴 다운"아이디어에 대해서는 생각하지 않았습니다. JSON 표현은 어떻게 생겼습니까? 현재 내 리소스의 각 JSON 표현에는 links배열이 포함되어 있으며 각 항목은 reluriXML 이있는 링크 객체입니다 (xml 예제와 유사). 각 링크 객체에 세 번째 필드를 추가해야합니까 (예 :) data? 표준이 있습니까?
ceran

드릴 다운은 실제로 휴식 기능이 아니므로 표준이 없습니다 (적어도 내가 아는 것).
Qwerky

stateless.co/hal_specification.html 과 같이 제안 된 표준이 있습니다 . 그것은 당신의 예에 매우 가깝습니다.
피트 커캄

4

모든 쿼리의 95 %가 원하는 경우 Foo뿐만 아니라 Bar, 단순히 그것을 돌려 내부Foo객체 당신이를 요청할 때 Foo. 단순히 속성 bar(또는 관계에 대한 다른 용어)을 추가하고 Bar객체를 거기에 넣으십시오 . 관계가 존재하지 않으면 null을 사용하십시오.

나는 당신이 이것을 생각하고 있다고 생각합니다 :)


나는 그 숫자 (95 %)를 제시해서는 안되며 실수였습니다. 죄송합니다. 내가 말하고 싶은 것은 요청의 많은 부분이 동시에 두 리소스에 관심이 있다는 것입니다. 그러나 아직도 단지에 관심이 요청 관련 수는 Foo, 각 이후 Bar메모리에 매우 거대하다 (의 3 배 - 4 배 크기의 주위에 Foo), 나는을 반환하지 않으려는 Bar클라이언트가 명시 적으로 요청하지 않는 경우.
ceran

우리는 얼마나 큰 대화를하고 있습니까? 나는 그것을 만들 것 의심 전송 시간에 큰 차이를, 나는 속도를 통해 깨끗한 API를 선호
나단 메릴
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.