使用可能有或没有尾随 / 的 Uri 字符串
Using Uri strings that may or may not have trailing /'s
我在代码中使用 HttpClient 有一段时间了,一直觉得它对 Uris
的使用导致我的实现有些脆弱。我们的大部分服务端点基地址都在 app./web.config 中。因此,它们可以很容易地更改。
我发现当使用这些端点字符串生成 Uri
时,如果它们不以 /
结尾,我的行为就会变得非常古怪。使用非 /
终止的 BaseAddress
调用 GetAsync()
时,发送 GET 请求的结果串联 URL 通常会在最终 [=13= 之后丢弃字符串] 在 BaseAddress
中,否则它将删除 GetUri 中第一个 /
之前的字符串。
例如:
BaseAddress
: http://test/serviceEndpoint
GetUri
: api/customer
当使用 GetUri
调用 HttpClient.GetAsync()
时,它将尝试从 http://test/api/customer
获取 GET。如果我用 /
来限制 BaseAddress
,一切都会按预期进行。
我的问题 是 BaseAddress
是配置驱动的,在 .config 文件中添加注释说 "Make sure you end all Service URLs with a /
!" 是一个非常脆弱的解决方案.
所以我养成了在所有 HttpClient
构造中使用以下代码的习惯:
var service = settings.GetValue("ServiceBaseUrl");
var serviceUri = !service.EndsWith("/")
? new Uri(service + "/")
: new Uri(service);
_client = new HttpClient
{
BaseAddress = serviceUri
};`
虽然这并不脆弱,但在每个 HttpClient
构造函数中使用它感觉很重复。 HttpClient
或 Uri
中是否有我可以用来避免此样板代码的内容?
HttpClient 或 Uri 中没有任何内容可以解决这个问题,这就是为什么我在 Flurl 中以几种方式解决它的原因。 Flurl 的 AppendPathSegment
和 AppendPathSegments
方法将确保段之间只有一个“/”分隔符。例如,这些产生相同的结果:
"http://mysite/".AppendPathSegment("/endpoint")
"http://mysite".AppendPathSegment("endpoint")
静态 Url.Combine
方法也有这种行为,作为 URLs 的 Path.Combine
。
这些和其他有用的 URL 构建位在核心 Flurl package, but the real fun is in Flurl.Http 中可用,它将流畅的 URL 构建器与 HttpClient 和 Json.NET 让你可以从字符串到 URL 再到 HTTP 请求再到反序列化的结果,而无需将笔从纸上移开,可以这么说:
var result = await settings.GetValue("ServiceBaseUrl")
.AppendPathSegment("endpoint")
.GetJsonAsync<T>();
我在代码中使用 HttpClient 有一段时间了,一直觉得它对 Uris
的使用导致我的实现有些脆弱。我们的大部分服务端点基地址都在 app./web.config 中。因此,它们可以很容易地更改。
我发现当使用这些端点字符串生成 Uri
时,如果它们不以 /
结尾,我的行为就会变得非常古怪。使用非 /
终止的 BaseAddress
调用 GetAsync()
时,发送 GET 请求的结果串联 URL 通常会在最终 [=13= 之后丢弃字符串] 在 BaseAddress
中,否则它将删除 GetUri 中第一个 /
之前的字符串。
例如:
BaseAddress
: http://test/serviceEndpoint
GetUri
: api/customer
当使用 GetUri
调用 HttpClient.GetAsync()
时,它将尝试从 http://test/api/customer
获取 GET。如果我用 /
来限制 BaseAddress
,一切都会按预期进行。
我的问题 是 BaseAddress
是配置驱动的,在 .config 文件中添加注释说 "Make sure you end all Service URLs with a /
!" 是一个非常脆弱的解决方案.
所以我养成了在所有 HttpClient
构造中使用以下代码的习惯:
var service = settings.GetValue("ServiceBaseUrl");
var serviceUri = !service.EndsWith("/")
? new Uri(service + "/")
: new Uri(service);
_client = new HttpClient
{
BaseAddress = serviceUri
};`
虽然这并不脆弱,但在每个 HttpClient
构造函数中使用它感觉很重复。 HttpClient
或 Uri
中是否有我可以用来避免此样板代码的内容?
HttpClient 或 Uri 中没有任何内容可以解决这个问题,这就是为什么我在 Flurl 中以几种方式解决它的原因。 Flurl 的 AppendPathSegment
和 AppendPathSegments
方法将确保段之间只有一个“/”分隔符。例如,这些产生相同的结果:
"http://mysite/".AppendPathSegment("/endpoint")
"http://mysite".AppendPathSegment("endpoint")
静态 Url.Combine
方法也有这种行为,作为 URLs 的 Path.Combine
。
这些和其他有用的 URL 构建位在核心 Flurl package, but the real fun is in Flurl.Http 中可用,它将流畅的 URL 构建器与 HttpClient 和 Json.NET 让你可以从字符串到 URL 再到 HTTP 请求再到反序列化的结果,而无需将笔从纸上移开,可以这么说:
var result = await settings.GetValue("ServiceBaseUrl")
.AppendPathSegment("endpoint")
.GetJsonAsync<T>();