.net 为什么HttpClient BaseAddress不工作?

kuhbmx9i  于 12个月前  发布在  .NET
关注(0)|答案(5)|浏览(120)

考虑下面的代码,其中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这是怎么回事?

ddrv8njm

ddrv8njm1#

事实证明,在BaseAddress和传递给GetAsync方法的相对URI(或HttpClient的任何其他方法)上包含或排除尾随或前导正斜杠的四种可能排列中,只有一种排列有效。您必须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的这种奇怪行为引起的问题。

5tmbdcev

5tmbdcev2#

引用解析由RFC 3986 Uniform Resource Identifier (URI): Generic Syntax描述。这正是它应该如何工作。为了保留基本URI路径,您需要在基本URI的末尾添加斜杠,并在相对URI的开头删除斜杠。
如果基URI包含非空路径,合并过程将丢弃它的最后一部分(在最后一个/之后)。

5.2.3.合并路径

上面的伪代码引用了一个“merge”例程,用于将相对路径引用与基本URI的路径合并。这是按如下方式完成的:

  • 如果基URI具有已定义的授权组件和空路径,则返回一个由“/”和引用路径连接组成的字符串;否则
  • 返回一个字符串,该字符串由引用的路径组成,附加到基本URI路径的最后一段以外的所有部分(即,排除基本URI路径中最右边的“/”之后的任何字符,或者排除整个基本URI路径,如果它不包含任何“/”字符)。

如果相对URI以斜杠开头,则称为绝对路径相对URI。在这种情况下,合并过程将忽略所有基本URI路径。有关详细信息,请参阅5.2.2.转换引用部分。

zbwhf8kr

zbwhf8kr3#

如果您使用的是httpClient.SendAsync(),则没有字符串重载来提供相对URI,就像Get或其他特定于动词的方法的重载一样。
但是您可以通过将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();

字符串

hmae6n7t

hmae6n7t4#

我在使用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的利弊,但对我来说,这是毫无疑问的。希望这对某人有所帮助。

3pvhb19x

3pvhb19x5#

HTTPClient遇到了一个问题,即使有了这些建议,仍然无法让它进行身份验证。原来我需要在相对路径中添加一个尾随的'/'。

var result = await _client.GetStringAsync(_awxUrl + "api/v2/inventories/?name=" + inventoryName);

个字符

相关问题