簡體   English   中英

為什么 HttpClient BaseAddress 不起作用?

[英]Why is HttpClient BaseAddress not working?

考慮以下代碼,其中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");
}

我希望這對http://something.com/api/resource/7執行GET請求。 但事實並非如此。

經過一番搜索,我找到了這個問題和答案: 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上包含或排除尾隨或前導正斜杠的四種可能排列以及傳遞給GetAsync方法(或HttpClient任何其他方法)的相對 URI 中,只有一種排列有效。 必須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");
}

盡管我回答了我自己的問題,但我想我會在這里提供解決方案,因為這種不友好的行為是沒有記錄的。 我和我的同事花了一天的大部分時間試圖解決最終由HttpClient的這種奇怪之處引起的問題。

RFC 3986 Uniform Resource Identifier (URI): Generic Syntax描述了參考解析。 這正是它應該如何工作的。 要保留基本 URI 路徑,您需要在基本 URI 的末尾添加斜杠並在相對 URI 的開頭刪除斜杠。

如果基本 URI 包含非空路徑,合並過程將丟棄它的最后一部分(在最后/ )。 相關部分

5.2.3. 合並路徑

上面的偽代碼指的是用於將相對路徑引用與基本 URI 的路徑合並的“合並”例程。 這是按如下方式完成的:

  • 如果基本 URI 具有定義的權限組件和空路徑,則返回由“/”與引用路徑連接組成的字符串; 除此以外

  • 返回一個字符串,該字符串包含附加到除基本 URI 路徑的最后一部分之外的所有部分的引用路徑組件(即,排除基本 URI 路徑中最右邊的“/”之后的任何字符,或者排除整個基本 URI 路徑,如果它不包含任何“/”字符)。

如果相對 URI 以斜杠開頭,則稱為絕對路徑相對 URI。 在這種情況下,合並過程會忽略所有基本 URI 路徑。 有關更多信息,請查看5.2.2。 轉換參考部分。

我也遇到了同樣的問題BaseAddress 我決定根本不使用BaseAddress ,最簡單的解決方案是簡單的單行添加:

Uri GetUri(string path) => new Uri("http://something.com/api" + path);

那么你的代碼將變成:

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

我還沒有調查過使用BaseAddress利弊,但對我來說這完美無缺。 希望這可以幫助某人。

如果您使用的是 httpClient。 SendAsync () 沒有像 Get、Post 和其他動詞特定方法中的重載那樣的字符串重載。

但是您可以通過將UriKind.Relative作為第二個參數來創建相對 Uri

        var httpRequestMessage = new HttpRequestMessage
        {
            Method = httpMethod,
            RequestUri = new Uri(relativeRequestUri, UriKind.Relative),
            Content = content
        };

        using var httpClient = HttpClientFactory.CreateClient("XClient");
        var response = await httpClient.SendAsync(httpRequestMessage);
        var responseText = await response.Content.ReadAsStringAsync();

或者 - 根本不使用BaseAddress 將整個URL放在GetAsync ()中

遇到了 HTTPClient 的問題,即使有建議仍然無法對其進行身份驗證。 原來我的相對路徑中需要一個尾隨的“/”。

IE

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
            });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM