[rest] HATEOAS : 절대 또는 상대 URL?

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

까다로운 것은 체계와 권한이 생략되면 “경로”부분 자체가 절대 경로 (로 시작 /) 또는 “루트없는”상대 경로가 될 수 있다는 것입니다. 예 :

  1. 절대 URI 또는 전체 URI :"http://example.com:8042/over/there?name=ferret"
  2. 그리고 이것은 절대 경로 가있는 상대 URI입니다 ./over/there
  3. 그리고 이것은이다 상대 경로와 상대 URI, : 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를 사용하는 것이 더 쉽다는 것입니다. 물론, 그 차이는 절대 버전을하도록 나를 흔들기에 충분할 것입니다.


답변

애플리케이션이 확장됨에 따라로드 밸런싱, 장애 복구 등을 수행 할 수 있습니다. 절대 URI를 반환하면 클라이언트 측 앱이 진화하는 서버 구성을 따릅니다.


답변

RayLou의 삼분법을 사용하여 우리 조직은 (2)를 선호했습니다. 주된 이유는 XSS (Cross-Site Scripting) 공격을 피하는 것입니다. 문제는 공격자가 서버에서 돌아 오는 응답에 자신의 URL 루트를 삽입 할 수있는 경우 후속 사용자 요청 (예 : 사용자 이름 및 암호를 사용한 인증 요청)이 공격자의 자체 서버로 전달 될 수 있다는 것입니다 *.

일부는로드 밸런싱을 위해 요청을 다른 서버로 리디렉션 할 수 있다는 문제를 제기했지만 (내 전문 분야는 아니지만) 클라이언트를 다른 서버로 명시 적으로 리디렉션하지 않고도로드 밸런싱을 활성화하는 더 좋은 방법이 있다고 확신합니다. 호스트.

*이 논리에 결함이 있으면 알려주십시오. 물론 목표는 모든 공격을 막는 것이 아니라 적어도 하나의 공격 방법입니다.


답변

항상 전체 URL을 사용해야합니다. URL은 모두 고유해야하므로 리소스의 고유 식별자 역할을합니다.

나는 또한 당신이 일관되어야한다고 주장합니다. Location HTTP 헤더는 HTTP 사양에 따라 전체 URL을 예상하므로 새 리소스가 생성 될 때 전체 URL이 Location 헤더에서 클라이언트로 다시 전송됩니다. Location 헤더에 전체 URL을 제공 한 다음 응답 본문 내의 링크에 상대 URI를 제공하는 것은 이상 할 것입니다.


답변

대규모 API 결과에서 중요한 고려 사항은 전체 URI를 반복적으로 포함하는 추가 네트워크 오버 헤드입니다. 믿거 나 말거나, gzip은이 문제를 완전히 해결하지 못합니다 (이유는 확실하지 않음). 결과에 수백 개의 링크가 포함되어있을 때 전체 URI가 차지하는 공간에 충격을 받았습니다.