[C#] HttpClient BaseAddress가 작동하지 않는 이유는 무엇입니까?

BaseAddress부분 URI 경로를 정의하는 다음 코드를 고려하십시오 .

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api");
    var response = await client.GetAsync("/resource/7");
}

GET요청을 수행 할 것으로 예상 합니다 http://something.com/api/resource/7. 그러나 그렇지 않습니다.

검색 한 후이 질문과 답변을 찾으십시오 : HttpClient with BaseAddress . 제안은 /의 끝에 배치 됩니다 BaseAddress.

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api/");
    var response = await client.GetAsync("/resource/7");
}

여전히 작동하지 않습니다. 문서는 다음과 같습니다. HttpClient.BaseAddress 여기서 무슨 일이 있습니까?



답변

메소드에 BaseAddress전달 된 상대 URI와 후행 슬래시를 포함하거나 제외하는 네 가지 가능한 순열 GetAsync중 하나 또는 하나의 순열 HttpClient만 작동합니다. 당신은 해야한다 의 끝에 슬래시를 배치 , 당신은 다음 예에서와 같이, 당신의 상대 URI의 시작 부분에 슬래시를 배치합니다.BaseAddress

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api/");
    var response = await client.GetAsync("resource/7");
}

나는 내 자신의 질문에 대답했지만,이 비우호적 인 행동이 문서화되어 있지 않기 때문에 여기에 해결책을 제공 할 것이라고 생각했습니다. 동료와 저는 하루 종일이 이상한 점으로 인해 발생한 문제를 해결하려고 노력했습니다 HttpClient.


답변

참조 해상도는 RFC 3986 URI (Uniform Resource Identifier) ​​: 일반 구문에 설명되어 있습니다. 그리고 그것이 정확히 작동하는 방식입니다. 기본 URI 경로를 유지하려면 기본 URI 끝에 슬래시를 추가하고 상대 URI의 시작에서 슬래시를 제거해야합니다.

기본 URI에 비어 있지 않은 경로가 포함 된 경우 병합 프로시 저는 마지막 부분 (마지막 이후 /)을 버립니다 . 관련 섹션 :

5.2.3. 패스 병합

위의 의사 코드는 상대 경로 참조를 기본 URI의 경로와 병합하기위한 “병합”루틴을 나타냅니다. 이는 다음과 같이 수행됩니다.

  • 기본 URI에 정의 된 권한 구성 요소와 빈 경로가있는 경우 참조의 경로와 연결된 “/”로 구성된 문자열을 리턴하십시오. 그렇지 않으면

  • 기본 URI 경로의 마지막 세그먼트를 제외한 모든 부분에 추가 된 참조의 경로 구성 요소로 구성된 문자열을 반환합니다 (예 : 기본 URI 경로에서 가장 오른쪽에있는 “/”뒤에있는 문자는 제외하거나 전체 기본 URI 경로는 제외) “/”문자를 포함하지 않습니다).

상대 URI가 슬래시로 시작하는 경우 절대 경로 상대 URI라고합니다. 이 경우 병합 절차는 모든 기본 URI 경로를 무시합니다. 자세한 내용은 5.2.2를 확인하십시오 . 변환 참조 섹션.


답변

제안이 여전히 인증을받을 수없는 경우에도 HTTPClient에 문제가 발생했습니다. 상대 경로에 후행 ‘/’가 필요하다는 것이 밝혀졌습니다.

var result = await _client.GetStringAsync(_awxUrl + "api/v2/inventories/?name=" + inventoryName);
var result = await _client.PostAsJsonAsync(_awxUrl + "api/v2/job_templates/" + templateId+"/launch/" , new {
                inventory = inventoryId
            });


답변

또는 전혀 사용하지 마십시오 BaseAddress. 전체 URL을 GetAsync() 에 넣습니다.


답변