HATEOAS를 사용하여 RESTful 웹 서비스를 설계 할 때 링크를 완전한 URL ( " http : // server : port / application / customers / 1234 ")로 표시하는 것과 경로 ( "/ application /) 로 표시하는 것의 장단점은 무엇입니까? customers / 1234 ")?
HATEOAS를 사용하여 RESTful 웹 서비스를 설계 할 때 링크를 완전한 URL ( " http : // server : port / application / customers / 1234 ")로 표시하는 것과 경로 ( "/ application /) 로 표시하는 것의 장단점은 무엇입니까? customers / 1234 ")?
답변:
사람들이 "상대적 URI"라고 말할 때 미묘한 개념적 모호성이 있습니다.
으로 RFC3986의 정의 , 일반적인 URI가 포함되어 있습니다
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
hier-part = "//" authority path-abempty
/ path-absolute
/ path-rootless
/ path-empty
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
까다로운 것은 체계와 권한이 생략되면 "경로"부분 자체가 절대 경로 (로 시작 /
) 또는 "루트없는"상대 경로가 될 수 있다는 것입니다. 예 :
"http://example.com:8042/over/there?name=ferret"
/over/there
here
또는 ./here
또는 ../here
또는 등따라서 질문이 "서버가 안정된 응답에서 상대 경로 를 생성해야하는지 여부 "인 경우 대답은 "아니오"이며 자세한 이유는 여기에서 확인할 수 있습니다. . 나는 "상대 URI"에 대한 대부분의 사람들 (나를 포함)이 실제로 "상대 경로"에 반대한다고 생각합니다.
그리고 실제로 대부분의 서버 측 MVC 프레임 워크는 과 같은 절대 경로를 사용 하여 상대 URI를 쉽게 생성 할 수 /absolute/path/to/the/controller
있으며, 질문은 "서버 구현이 scheme://hostname:port
절대 경로 앞에 접두사를 붙여야하는지 여부 "가됩니다. OP의 질문처럼. 나는 이것에 대해 잘 모르겠습니다.
한편으로는 여전히 전체 URI를 반환하는 서버를 권장한다고 생각합니다. 그러나 서버는 이와 같은 소스 코드 내부를 하드 코딩 해서는 안됩니다.hostname:port
(그렇지 않으면 절대 경로가있는 상대 URI로 대체합니다). 해결책은 서버 측에서 항상 HTTP 요청의 "호스트"헤더에서 해당 접두사를 얻는 것입니다. 이것이 모든 상황에서 작동하는지 확실하지 않습니다.
반면에 클라이언트가 http://example.com:8042
절대 경로와 연결하는 것은 그리 번거롭지 않은 것 같습니다 . 결국 클라이언트는 서버에 요청을 보낼 때 이미 해당 체계와 도메인 이름을 알고 있습니까?
대체로 절대 URI를 사용하는 것이 좋습니다. 절대 경로가있는 상대 URI로 대체 될 수 있으며 절대 경로를 사용하지 마십시오 .
클라이언트 코드를 작성하는 사람에 따라 다릅니다. 클라이언트와 서버를 작성하는 경우 큰 차이가 없습니다. 클라이언트 또는 서버에서 URL을 작성하는 데 어려움을 겪을 것입니다.
그러나 서버를 구축하고 다른 사람들이 클라이언트 코드를 작성하기를 기대한다면 완전한 URI를 제공하면 훨씬 더 좋아할 것입니다. 상대 URI를 확인하는 것은 약간 까다로울 수 있습니다. 먼저이를 해결하는 방법은 반환 된 미디어 유형에 따라 다릅니다. Html에는 기본 태그가 있고, Xml에는 모든 중첩 요소에 xml : base 태그가있을 수 있으며, Atom 피드에는 피드에 기본이있을 수 있고 콘텐츠에 다른 기본이있을 수 있습니다. 클라이언트에 기본 URI에 대한 명시적인 정보를 제공하지 않으면 요청 URI 또는 Content-Location 헤더에서 기본 URI를 가져와야합니다! 그리고 그 후행 슬래시를 조심하십시오. 기본 URI는 마지막 슬래시 오른쪽에있는 모든 문자를 무시하여 결정됩니다. 이는 이제 상대 URI를 확인할 때 후행 슬래시가 매우 중요하다는 것을 의미합니다.
작은 언급이 필요한 유일한 다른 문제는 문서 크기입니다. 각 항목에 여러 링크가있을 수있는 많은 항목 목록을 반환하는 경우 항목을 압축하지 않으면 절대 URL을 사용하면 항목에 상당한 양의 바이트가 추가 될 수 있습니다. 이것은 성능 문제이며 사례별로 중요한지 결정해야합니다.
애플리케이션이 확장됨에 따라로드 밸런싱, 장애 복구 등을 수행 할 수 있습니다. 절대 URI를 반환하면 클라이언트 측 앱이 진화하는 서버 구성을 따릅니다.
/xxx/yyy...
하고 정규화 된 URI (예 :)를 의미하지 않는 경우 http://api.example.com/xxx/yyy...
.
RayLou의 삼분법을 사용하여 우리 조직은 (2)를 선호했습니다. 주된 이유는 XSS (Cross-Site Scripting) 공격을 피하는 것입니다. 문제는 공격자가 서버에서 돌아 오는 응답에 자신의 URL 루트를 삽입 할 수있는 경우 후속 사용자 요청 (예 : 사용자 이름 및 암호를 사용한 인증 요청)이 공격자의 자체 서버로 전달 될 수 있다는 것입니다 *.
일부는로드 밸런싱을 위해 요청을 다른 서버로 리디렉션 할 수 있다는 문제를 제기했지만 (내 전문 분야는 아니지만) 클라이언트를 다른 서버로 명시 적으로 리디렉션하지 않고도로드 밸런싱을 활성화하는 더 좋은 방법이 있다고 확신합니다. 호스트.
*이 논리에 결함이 있으면 알려주십시오. 물론 목표는 모든 공격을 막는 것이 아니라 적어도 하나의 공격 방법입니다.
항상 전체 URL을 사용해야합니다. URL은 모두 고유해야하므로 리소스의 고유 식별자 역할을합니다.
나는 또한 당신이 일관되어야한다고 주장합니다. Location HTTP 헤더는 HTTP 사양에 따라 전체 URL을 예상하므로 새 리소스가 생성 될 때 전체 URL이 Location 헤더에서 클라이언트로 다시 전송됩니다. Location 헤더에 전체 URL을 제공 한 다음 응답 본문 내의 링크에 상대 URI를 제공하는 것은 이상 할 것입니다.
Location
헤더 예제가 제공하는 것입니다. URI 체계 나 서버의 네트워크 위치를 포함하지 않는 절대 URI입니다. 링크와 ID는 종종 병합되지만 동일한 것은 아닙니다. 전자에는 컨텍스트가 있지만 후자는 그렇지 않습니다.
절대 URI 사용의 한 가지 단점은 api를 프록시 할 수 없다는 것입니다.
다시 가져 가세요 ... 사실이 아닙니다. 도메인을 포함한 전체 URL로 이동해야합니다.
전문가와 관련하여 (절대) 경로에 대해 클라이언트가 요구하는 추가 처리를 희생하면서 전송되는 바이트 수가 감소하는 것을 확인했습니다. gzip으로 콘텐츠 인코딩, 캐싱 헤더의 적절한 사용, etag 사용 및 클라이언트에서 조건부 요청을 시도한 후에도 모든 바이트를 저장하기 위해 필사적이라면 결국 이것이 필요할 수 있지만 훨씬 더 높은 수익을 기대합니다. 당신의 노력은 그렇지 않았습니다.
단점과 관련하여 향후 리소스간에 클라이언트 흐름을 지시 할 수있는 방법 (로드 밸런싱, A / B 테스트 등)에 대한 통제력이 상실된 것을보고 웹 관리와 관련하여 나쁜 습관이라고 생각합니다. API. 제공하는 URL은 더 이상 기본적으로 클라이언트에 대해 불투명하지 않습니다 ( URI 불투명도에 대한 웹 아키텍처의 Tim Berners-Lee Axioms 참조 ). 결국 귀하는 URL 공간의 구조에만 관련된 것이더라도 API의 창의적인 사용에 대해 클라이언트를 만족시킬 책임이 있습니다. 명시 적으로 정의 된 URL 수정을 허용해야하는 경우 Hypertext Application Language 에서 사용되는 URI 템플릿 사용을 고려하십시오 .