HATEOAS : 절대 또는 상대 URL?


답변:


83

사람들이 "상대적 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로 대체 될 수 있으며 절대 경로를 사용하지 마십시오 .


2
이것은 최종 결론을 제외하고는 동의하는 좋은 답변 (+1)입니다. 그러나 내 대답에서 나는 HTTP 사양 이 예를 들어 "절대"를 정의 하여 완전한 URI가 아닌 절대 경로 를 참조 한다고 주장합니다 . 이 - 나는 (2) 귀하의 동의 그래서 입니다 그것은 완전한 URI하지 그래서 클라이언트가 네트워크 프로토콜 및 호스트를 추론해야하는 하나의 절대 URI하지만. 그리고, 그러므로, 또한 (1)의 당신의 정의에 동의 모두 전체 URI와 절대 URI.
Lawrence Dol 2014

댓글 주셔서 감사합니다. 파일 시스템에서 절대 경로와 상대 경로 개념을 빌려 왔습니다. 용어가 다르지만 귀하의 의견과 저의 의견 사이에는 큰 차이가 없습니다. 당신은 또한 양식 1과 2를 추천하고 당신은 양식 3에 반대합니다.
RayLuo 2014

2
실제로 나는 (2); 나는 (1) 백엔드가 많은 HTTP 관련 지식 (일반적인 HTTP가 아닌 특정 HTTP 환경의 세부 사항에 대한 의미)을 필요로하고 (3) 클라이언트를 너무 많이 요구하는 것 같다고 생각합니다. 그러나 내 추론은 원본 초안 사양을 기반으로했으며 추론을 무효화하는 방식으로 이후 버전에서 예제가 변경되었습니다.
Lawrence Dol 2014

개인적으로 나는 HATEOAS를 (아직) 전혀 확신하지 못하기 때문에 URI 반환에 대한 요구가 API에 대해 그다지 의미가 있습니다. 웹 사이트를 탐색하는 것과 유사한 방식으로 클라이언트에서 내 API가 구동되는 것을 볼 수 없습니다. 유스 케이스는 임시 기능에 의해 주도되는 것 같습니다.
Lawrence Dol 2014

@LawrenceDol 처음에는 HATEOAS에 대해 동일한 혼란이 있습니다. 이제 나는 그것을 선택의 문제로 생각합니다. 클라이언트는 adhoc 함수를 사용하여 확실히 API를 사용할 수 있지만, 원하는 경우 따라야 할 패턴을 개발할 수 있으므로 클라이언트가 정확한 각 URL을 하드 코딩 할 필요가 없습니다. HATEOAS입니다.
RayLuo

13

클라이언트 코드를 작성하는 사람에 따라 다릅니다. 클라이언트와 서버를 작성하는 경우 큰 차이가 없습니다. 클라이언트 또는 서버에서 URL을 작성하는 데 어려움을 겪을 것입니다.

그러나 서버를 구축하고 다른 사람들이 클라이언트 코드를 작성하기를 기대한다면 완전한 URI를 제공하면 훨씬 더 좋아할 것입니다. 상대 URI를 확인하는 것은 약간 까다로울 수 있습니다. 먼저이를 해결하는 방법은 반환 된 미디어 유형에 따라 다릅니다. Html에는 기본 태그가 있고, Xml에는 모든 중첩 요소에 xml : base 태그가있을 수 있으며, Atom 피드에는 피드에 기본이있을 수 있고 콘텐츠에 다른 기본이있을 수 있습니다. 클라이언트에 기본 URI에 대한 명시적인 정보를 제공하지 않으면 요청 URI 또는 ​​Content-Location 헤더에서 기본 URI를 가져와야합니다! 그리고 그 후행 슬래시를 조심하십시오. 기본 URI는 마지막 슬래시 오른쪽에있는 모든 문자를 무시하여 결정됩니다. 이는 이제 상대 URI를 확인할 때 후행 슬래시가 매우 중요하다는 것을 의미합니다.

작은 언급이 필요한 유일한 다른 문제는 문서 크기입니다. 각 항목에 여러 링크가있을 수있는 많은 항목 목록을 반환하는 경우 항목을 압축하지 않으면 절대 URL을 사용하면 항목에 상당한 양의 바이트가 추가 될 수 있습니다. 이것은 성능 문제이며 사례별로 중요한지 결정해야합니다.


11

유일한 실제 차이점은 클라이언트가 상대 버전에서 구성하는 대신 절대 URI를 사용하는 것이 더 쉽다는 것입니다. 물론, 그 차이는 절대 버전을하도록 나를 흔들기에 충분할 것입니다.


7

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


"절대"를 완전한 경로 (예 :)로 정의 /xxx/yyy...하고 정규화 된 URI (예 :)를 의미하지 않는 경우 http://api.example.com/xxx/yyy....
Lawrence Dol

6

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

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

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


이전 답변이 귀하의 조직에 도움이되어 다행입니다. 예, 개인적으로도 (2), 일명 무계획 절대 경로를 선호합니다. 그러나 나는 당신의 추론에 대해 궁금합니다. 클라이언트가 스키마없는 URL 만 허용하도록 어떻게 강요 했습니까? 브라우저와 같은 일반 클라이언트는 스키마없는 URL을 전혀 거부하지 않습니다. 그래서 실제로 URL을 따르기 전에 URL을 확인하기 위해 클라이언트 측 코드를 작성해야한다고 가정합니다. 기술적으로는 가능하지만 반드시 유용한 것은 아니지만 이러한 종류의 클라이언트 측 유효성 검사는 일반적으로 REST 또는 HATEOAS 논의의 일부가 아닙니다.
RayLuo

3
나는 이것이 오래된 게시물이라는 것을 알고 있지만, "공격자가 자신의 URL 루트를 다시 오는 응답에 주입 할 수있는 경우" 는 일종의 말도 안되는 이유 임을 지적하고 싶습니다 . 그들이 응답의 올바른 위치에 "자신의 URL을 삽입"할 수 있다면 호스트 이름을 자신의 호스트 이름으로 쉽게 바꿀 수있을 것입니다. 따라서 보안 관점에서 볼 때 유효한 주장으로 보지 않습니다.
Magnus Eriksson

5

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

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


1
음, Location 헤더에 대한 HTTP 사양은 절대 URI를 말합니다. 절대 URI에는 스키마 (예 : http)가 포함되어야합니다.
Mark Bober 2014

그러나 문제는 어떻게 문맥없는 불투명 식별자 를 구성하는 것이 아니라 링크 를 구성하는 방법을 묻습니다 . 후자는 "이 문서와 동일한 네트워크 위치에서"를 올바르게 추론 할 수 있으며, 이것이 바로 스펙의 Location헤더 예제가 제공하는 것입니다. URI 체계 나 서버의 네트워크 위치를 포함하지 않는 절대 URI입니다. 링크와 ID는 종종 병합되지만 동일한 것은 아닙니다. 전자에는 컨텍스트가 있지만 후자는 그렇지 않습니다.
Lawrence Dol 2014

당신이 말하는 사양의 일부에 대한 링크를 보낼 수 있습니까?
Mark Bober 2014

절대 URI는 체계를 지정합니다. 절대적이지 않은 URI는 상대적이라고합니다. URI는 불투명한지 계층 적인지에 따라 분류됩니다. 불투명 한 URI는 체계 특정 부분이 슬래시 문자 ( '/')로 시작하지 않는 절대 URI입니다. 불투명 한 URI는 더 이상 파싱되지 않습니다. 불투명 한 URI의 몇 가지 예는 다음과 같습니다. mailto : java-net@java.sun.com news : comp.lang.java urn : isbn : 096139210x
Mark Bober

1
이봐, 걱정마. 이 물건에 대한 또 다른 요점은 사람들이 hrefs를 ID로 사용하는 것을 본 것입니다. 클라이언트가 일부 구성 파일과 ID에서 URL을 재구성 할 필요가 없도록 URL 만 알고이를 기반으로 캐시 할 수 있습니다.
Mark Bober 2014

2

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


2

절대 URI 사용의 한 가지 단점은 api를 프록시 할 수 없다는 것입니다.

다시 가져 가세요 ... 사실이 아닙니다. 도메인을 포함한 전체 URL로 이동해야합니다.


3
절대 URI가 프록시의 호스트 이름을 사용할 수없는 이유는 무엇입니까?
Ed Summers

1
현재이 정확한 문제를 해결하고 있습니다. 우리는 모든 요청이 일종의 "부하 분산"계층을 먼저 거치기를 원합니다. 서버에 대한 절대 URI는이 모델을 직접 손상시킵니다.
mag382

1
절대 URL로 사이트를 프록시하기 위해 Nginx를 사용하고 있습니다. 백엔드 URL을 동등한 프록시 URL로 완벽하게 대체 할 수 있습니다. 특히 windyroad.artifactoryonline.com (정규화 된 URL 및 정규화 된 리디렉션이 있음)을 repo.windyroad.com.au
Tom Howard

2

전문가와 관련하여 (절대) 경로에 대해 클라이언트가 요구하는 추가 처리를 희생하면서 전송되는 바이트 수가 감소하는 것을 확인했습니다. gzip으로 콘텐츠 인코딩, 캐싱 헤더의 적절한 사용, etag 사용 및 클라이언트에서 조건부 요청을 시도한 후에도 모든 바이트를 저장하기 위해 필사적이라면 결국 이것이 필요할 수 있지만 훨씬 더 높은 수익을 기대합니다. 당신의 노력은 그렇지 않았습니다.

단점과 관련하여 향후 리소스간에 클라이언트 흐름을 지시 할 수있는 방법 (로드 밸런싱, A / B 테스트 등)에 대한 통제력이 상실된 것을보고 웹 관리와 관련하여 나쁜 습관이라고 생각합니다. API. 제공하는 URL은 더 이상 기본적으로 클라이언트에 대해 불투명하지 않습니다 ( URI 불투명도에 대한 웹 아키텍처의 Tim Berners-Lee Axioms 참조 ). 결국 귀하는 URL 공간의 구조에만 관련된 것이더라도 API의 창의적인 사용에 대해 클라이언트를 만족시킬 책임이 있습니다. 명시 적으로 정의 된 URL 수정을 허용해야하는 경우 Hypertext Application Language 에서 사용되는 URI 템플릿 사용을 고려하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.