먼저
따라 RFC 3986 §3.4 (통일 자원 식별자가 § (구문 구성 요소) | 조회
3.4 질의
쿼리 구성 요소에는 경로 구성 요소 (섹션 3.3)의 데이터와 함께 URI 체계 및 명명 권한 (있는 경우) 범위 내에서 리소스를 식별하는 비 계층 데이터가 포함됩니다.
쿼리 구성 요소는 비 계층 데이터를 검색하기위한 것입니다. 가계도보다 본질적으로 더 계층적인 것들이 거의 없습니다! Ergo- 인터넷에서 시스템을 개발하고 형식, 프로토콜 및 프레임 워크를 준수하기 위해 "REST-y"인지 여부에 관계없이이 정보를 식별하기 위해 쿼리 문자열을 사용해서는 안됩니다.
REST는이 정의와 관련이 없습니다.
특정 질문을 해결하기 전에 "search"의 쿼리 매개 변수 이름이 잘못되었습니다. 쿼리 세그먼트를 키-값 쌍의 사전으로 취급하는 것이 좋습니다.
쿼리 문자열을보다 적절하게 정의 할 수 있습니다.
?first_name={firstName}&last_name={lastName}&birth_date={birthDate}
기타
특정 질문에 대답하려면
1) 어떤 API 디자인이 더 RESTful하고 왜 그럴까요? 의미 적으로, 그들은 같은 방식으로 의미하고 행동합니다. URI의 마지막 리소스는 "children"이며 클라이언트가 children 리소스에서 작동하고 있음을 나타냅니다.
나는 이것이 당신이 믿는 것처럼 명확한 컷이라고 생각하지 않습니다.
이 자원 인터페이스 중 어느 것도 RESTful이 아닙니다. RESTful 아키텍처 스타일 의 주요 전제 조건은 애플리케이션 상태 전이가 서버에서 하이퍼 미디어로 통신되어야한다는 것입니다. 사람들은 URI 구조에 대해 어떤 식 으로든 "RESTful URIs"를 만들려고 노력했지만 REST에 관한 공식 문헌은 실제로 이에 대해 거의 말할 것이 없다. 내 개인적인 의견은 REST에 관한 많은 메타 정보가 오래되고 나쁜 습관을 깰 의도로 출판되었다는 것입니다. (정말로 "RESTful"시스템을 구축하는 것은 실제로 상당한 작업입니다. 업계는 "REST"로 빛을 발하며 비 관념적인 자격 및 제한 사항에 대한 일부 직교 문제를 보완했습니다.)
REST 문서에 따르면 애플리케이션 프로토콜로 HTTP를 사용하려는 경우 프로토콜 스펙의 공식 요구 사항을 준수해야하며 "가는대로 http를 작성하고 여전히 http를 사용하고 있다고 선언 할 수 없습니다" ; 자원을 식별하기 위해 URI를 사용하려는 경우 URI / URL에 대한 스펙의 공식 요구 사항을 준수해야합니다.
귀하의 질문은 위에 링크 된 RFC3986 §3.4에 의해 직접 해결됩니다. 이 문제에 대한 결론은 그 규격에 부합하는 URI는 시스템이 실제로하고 싶은 경우, "편안하고"API를 고려하는 것이 부족에도 불구하고 수 "편안하고"당신은 당신이를 통해 계층 적 데이터를 식별 할 수없는, HTTP와 URI를 사용하는 다음과 같은 이유로 쿼리 문자열 :
3.4 질의
쿼리 구성 요소에 비 계층 데이터가 포함되어 있습니다.
... 그만큼 간단합니다.
2) 고객의 관점에서 이해 성과 디자이너의 관점에서 유지 보수 측면에서 각각의 장단점은 무엇입니까?
처음 두 사람의 "프로"는 그들이 올바른 길 을 가고 있다는 것 입니다. 세 번째 것의 "단점"은 그것이 잘못 평평한 것처럼 보입니다.
이해 및 유지 관리 가능성에 관한 한, 이는 주관적이며 클라이언트 개발자의 이해 수준과 디자이너의 디자인에 달려 있습니다. URI 사양은 URI의 형식을 지정하는 방법에 대한 결정적인 답변입니다. 계층 적 데이터는 경로와 경로 매개 변수로 표시되어야합니다. 비 계층 적 데이터는 쿼리에 표시되어야합니다. 조각의 의미론은 요청 된 표현의 미디어 유형에 따라 달라지기 때문에 조각이 더 복잡합니다. 따라서 질문의 "이해성"구성 요소를 해결하기 위해 처음 두 URI가 실제로 말하는 것을 정확하게 변환하려고 시도합니다. 그런 다음 유효한 URI로 달성하려는 말을 표현하려고 시도합니다.
동사 URI를 의미 적 의미로 변환
/myservice/api/v1/grandparents/{grandparentID}/parents/children?search={text}
이것은 조부모의 부모를 위해 자녀를 찾으 search={text}
십시오. URI로 말한 내용은 조부모의 형제를 검색하는 경우에만 일관됩니다. 당신의 "조부모, 부모님, 자녀들"과 함께 당신은 "조부모"가 부모에게 한 세대 올라가서 부모의 자녀를 보며 "조부모"세대로 돌아온 것을 발견했습니다.
/myservice/api/v1/parents/{parentID}/children?search={text}
이것은 {parentID}에 의해 식별 된 부모의 경우 원하는 것을 가진 것에 ?search={text}
더 가깝고 전체 API를 모델링하는 데 사용될 수있는 부모-자식 관계를 나타냅니다. 이러한 방식으로 모델링하기 위해, "grandparentId"가있는 경우, 자신이 가지고있는 ID와보고자하는 가족 그래프의 일부 사이에 간접 계층이 있음을 인식해야하는 부담이 고객에게 부과됩니다. "grandparentId"로 "자식"을 찾으려면 /parents/{parentID}/children
서비스를 호출 한 다음 반환 된 자식을 찾아 자녀의 개인 식별자를 검색하십시오.
URI로 요구 사항 구현
트리를 걸을 수있는보다 확장 가능한 리소스 식별자를 모델링하려는 경우이를 달성 할 수있는 몇 가지 방법을 생각할 수 있습니다.
1) 첫 번째는 이미 언급 한 것입니다. "사람"의 그래프를 복합 구조로 나타냅니다. 각 사람은 부모 경로를 통해 위에있는 세대와 어린이 경로를 통해 아래에있는 세대에 대해 언급합니다.
/Persons/Joe/Parents/Mother/Parents
조의 어머니 조부모를 잡는 방법이 될 것입니다.
/Persons/Joe/Parents/Parents
조의 조부모를 모두 잡는 방법이 될 것입니다.
/Persons/Joe/Parents/Parents?id={Joe.GrandparentID}
Joe의 조부모가 당신이 가지고있는 식별자를 가지고있을 것입니다.
"모자 / 부모 / 부모"패턴에서 분기 식별이 없기 때문에 서버에서 df를 강제 실행하여 작업에 따라 성능에 불이익이있을 수 있습니다. 임의의 수의 세대를 지원하는 능력. 어떤 이유로 8 세대를 조회하려는 경우이를 다음과 같이 나타낼 수 있습니다.
/Persons/Joe/Parents/Parents/Parents/Parents/Parents/Parents/Parents/Parents?id={Joe.NotableAncestor}
그러나 이것은 경로 매개 변수를 통해이 데이터를 나타내는 두 번째 지배적 인 옵션으로 이어집니다.
2) 경로 매개 변수를 사용하여 "계층 구조 쿼리"소비자에 대한 부담을 덜어주고 이해하기 쉬운 API를 갖도록 다음 구조를 개발할 수 있습니다.
147 세대를 되돌아 보려면이 매개 변수를 경로 매개 변수로 표시하면
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor}
조부모에게서 조를 찾으려면 조의 Id에 대해 알려진 세대 수의 그래프를 볼 수 있습니다.
/Persons/JoesGreatGrandparent/Children;generations=3?id={Joe.Id}
이러한 접근 방식에서 가장 주목할 점은 식별자와 요청에 추가 정보가 없으면 첫 번째 URI가 Joe.NotableAncestor의 식별자를 사용하여 Joe에서 Person 147 세대를 검색한다는 것을 예상해야합니다. 두 번째는 Joe를 검색해야합니다. 실제로 원하는 것은 호출 클라이언트가 전체 노드 세트와 루트 Person과 URI의 최종 컨텍스트 사이의 관계를 검색 할 수 있다고 가정하십시오. 동일한 URI (일부 추가 데코레이션 사용) text/vnd.graphviz
를 사용하여 요청시 수락 .dot
표시 (그래프 표시를 위한 IANA 등록 미디어 유형 )를 설정할 수 있습니다 . 그런 다음 URI를 다음으로 변경하십시오.
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor.Id}#directed
HTTP 요청 헤더
Accept: text/vnd.graphviz
를 사용하면 클라이언트가 Joe와 147 세대 사이의 세대 계층 구조에 대한 지시 그래프를 원한다는 것을 명확하게 전달할 수 있습니다.
text / vnd.graphviz에 조각에 대해 사전 정의 된 의미가 있는지 확실하지 않습니다. 명령 검색에서 아무것도 찾을 수 없습니다. 해당 매체 유형에 실제로 사전 정의 된 조각 정보가있는 경우 해당 의미론을 따라 적합한 URI를 작성해야합니다. 그러나 이러한 의미가 사전 정의되어 있지 않은 경우 URI 사양에 따르면 조각 식별자의 의미가 제한되지 않고 서버에 의해 정의되어이 사용법이 유효합니다.
3) 리소스에 대한 "필터링"외에 실제로 쿼리 문자열이 무엇입니까? 첫 번째 방법을 사용하면 필터 매개 변수가 쿼리 문자열 매개 변수 대신 경로 매개 변수로 URI 자체에 포함됩니다.
필자는이 문제를 이미 철저히 극복했다고 생각하지만 쿼리 문자열은 "필터링"리소스가 아닙니다. 비 계층 적 데이터에서 리소스 를 식별 하기 위한 것입니다. 당신이 이동하여 경로 계층 구조를 드릴 다운 한 경우
/person/{id}/children/
와 사용자가 확인하고자하는 특정 아동 또는 특정 아이들의 세트를, 당신은 당신이 식별하는 집합에 적용 몇 가지 속성을 사용하고는 쿼리 내부에 포함됩니다.