【问题标题】:Using Uri strings that may or may not have trailing /'s使用可能有也可能没有尾随 / 的 Uri 字符串
【发布时间】:2015-12-10 17:11:06
【问题描述】:

我在代码中使用 HttpClient 已经有一段时间了,并且一直觉得它对 Uris 的使用导致我的实现有些脆弱。我们的大多数服务端点基地址都在 app./web.config 中。因此,它们可以很容易地改变。

我发现当使用这些端点字符串生成Uri 时,如果它们不以/ 结尾,我的行为会非常不稳定。当使用非/ 终止的BaseAddress 调用GetAsync() 时,发送GET 请求的结果级联URL 通常会丢弃BaseAddress 中最后一个/ 之后的字符串,或者会丢弃GetUri 中第一个 / 之前的字符串。

例如:

BaseAddress:http://test/serviceEndpoint

GetUri:api/customer

当使用GetUri 调用HttpClient.GetAsync() 时,它将尝试从http://test/api/customer 获取。如果我用/BaseAddress 加盖,一切都会按预期进行。

我的问题BaseAddress 是配置驱动的,并在 .config 文件中添加注释说“确保以 / 结束所有服务 URL!”是一个非常脆弱的解决方案。

所以我养成了在所有HttpClient 构造中使用以下代码的习惯:

        var service = settings.GetValue("ServiceBaseUrl");
        var serviceUri = !service.EndsWith("/")
            ? new Uri(service + "/")
            : new Uri(service);

        _client = new HttpClient
        {
            BaseAddress = serviceUri
        };`

虽然这并不脆弱,但在每个 HttpClient 构造函数中都有它感觉是重复的。 HttpClientUri 中是否有一些东西可以用来避免这个样板代码?

【问题讨论】:

  • 您可以尝试将逻辑包装在扩展方法中以减少重复量。您将在整个应用程序中使用 var serviceUri = service.GetBaseURL()。 msdn.microsoft.com/en-us/library/bb383977.aspx
  • 只是一种极端情况的想法:serviceUri = service.TrimEnd('/') + "/" 会捕获ServiceBaseUrl 以多个/ 结尾的情况以及它不以/ 结尾的情况。

标签: c# uri dotnet-httpclient


【解决方案1】:

在 HttpClient 或 Uri 中没有任何东西可以解决这个问题,这就是我在 Flurl 中以几种方式解决它的原因。 Flurl 的AppendPathSegmentAppendPathSegments 方法将确保段之间只有一个“/”分隔符。例如,这些会产生相同的结果:

"http://mysite/".AppendPathSegment("/endpoint")
"http://mysite".AppendPathSegment("endpoint")

静态的Url.Combine 方法也有这种行为,相当于URL 的Path.Combine

这些和其他有用的 URL 构建位在核心 Flurl 包中提供,但真正有趣的是 Flurl.Http,它将流畅的 URL 构建器与 HttpClient 和 Json.NET 之上的轻量级包装器相结合,让您从字符串到 URL 再到 HTTP 请求再到反序列化结果,而无需从纸上拿起笔,可以这么说:

var result = await settings.GetValue("ServiceBaseUrl")
    .AppendPathSegment("endpoint")
    .GetJsonAsync<T>();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多