繁体   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