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


299

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 여기서 무슨 일이 있습니까?



@ ГеоргийЛанец 리버스 복제가 이미 제안되었습니다. 나는 다른 질문이 같은 문제를 가진 사람들에 의해 매우 쉽게 발견 될 수있는 방식으로 쓰여지지 않았기 때문에이 질문을 구체적으로 썼다.
Timothy Shields

그러나이 질문은 나중에 묻습니다
George Lanetz

2
@ ГеоргийЛанец 그것은 작동하지 않습니다. 일반적으로 가장 "정식적인"질문은 그것을 가리키는 복제본을 얻는 것입니다. 다른 질문은 FAQ처럼 읽는 대신 사용자가 겪고 있었던 단일 문제에 관한 것입니다.
Timothy Shields

2
@ ГеоргийЛанец 또한이 질문의 다른 질문을 언급하고 다른 질문과 답변이 문제를 해결하기에 부족한 이유를 설명합니다.
Timothy Shields

답변:


719

메소드에 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.


4
감사합니다. 이로 인해 Azure로, IIS로, IIS Express로 다시 전환 할 때까지 현재 이틀 동안 어려움을 겪고있는 문제가 해결되었습니다. 내 기본 클래스에 설정되면 RestClient거의 보이지 않았으며 전혀주의를 기울이지 않았으며 중단 점 등에서 전체 URL을 보지 못했습니다.
ProfK

43
이 기이함 (및이 수정)이 여전히 .NET Core와 관련이 있음을 확인할 수 있습니다. 머리카락을 찌르는 티모시를 줄여 주셔서 감사합니다.
Nate Barbettini

8
요청을 작성할 때 슬래시없이 마지막 부분을 삭제하기 때문입니다. 따라서 something.com/resource/7에 도달 합니다 . 기본 주소를 무언가 / com 으로 설정하면 (후행 슬래시 유무에 관계없이) api / resource / 7의 시작 부분에 슬래시를 넣는 것도 중요하지 않습니다. 후행 슬래시가 없으면 기본 주소의 마지막 부분이 파일처럼 취급되고 빌딩 요청시 삭제됩니다.
Piotr Perak

12
이것은 원래의 질문을 직접 다루지는 않지만 관련이 있습니다. Mircosoft 당 HttpClient를 인스턴스 ()은 정적 변수에 할당되어야하고 (다시 docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/... - Creating a new HttpClient instance per request can exhaust the available sockets). 따라서 Using () 제거를 고려해야합니다.
sanmcp

6
끔찍한 구현입니다. 왜이 문제를 해결하지 않습니까?
timmkrause

55

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

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

5.2.3. 패스 병합

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

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

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

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


3
HttpClient와 같은 클라이언트 라이브러리는 이와 같은 난해한 구현 세부 사항으로부터 우리를 보호해야합니다.
Jamie Ide

-1

제안이 여전히 인증을받을 수없는 경우에도 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
            });

-6

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


33
질문에 대답하지 않습니다.
Archibald

7
BaseAddress는 노이즈를 줄입니다. 어쨌든 내 눈에. :)
MetalMikester

2
부정적인 의견에 동의하지 않아야합니다. 내 HttpClient 호출이 내 Dev PC에서 작동하지만 서버에서 작동하는 이유를 알아 내려고 2 일을 보냈습니다. 이상한 Powershell은 작동하지만 .net은 작동하지 않습니다. .SendAsyc를 사용하고있었습니다. 그런 다음 .GetAsyc가 효과가 있음을 발견했습니다. 이것은 나를 다른 길로 이끌었고 결국 여기에 있습니다. 기본 주소와 상대 URL 사이에 /를 추가하거나 제거해도 아무런 효과가 없습니다. 여전히 404 오류가 발생했습니다 ....하지만 기본 주소를 설정하지 않고 전체 경로를 Relative에 넣었을 때 .. 작동했습니다! 다시, 이것은 .SendAsync와 함께 있지만 다시는 2 일이 지나지 않을 것입니다!
da_jokker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.