Norns.Urd.HttpClient
Norns.Urd.HttpClient 基于 AOP 框架 Norns.Urd 实现,
是对 System.Net.Http
下的 HttpClient 封装,让大家只需简略在接口定义就能够实现 http 的调用,能够缩小一些反复代码的书写。
能够和已有的 Norns.Urd.Extensions.Polly
以及 Norns.Urd.Caching.Memory
配合应用。
源码放在:https://github.com/fs7744/Nor…
如何启用 HttpClient 性能
- 引入 Norns.Urd.HttpClient
dotnet add package Norns.Urd.HttpClient
- 代码中开启 HttpClient 性能,只需
new ServiceCollection()
.ConfigureAop(i => i.EnableHttpClient())
- 定义 要应用的 HttpClient 接口
举例如:
[BaseAddress("http://localhost.:5000")]
public interface ITestClient
{[Get("WeatherForecast/file")]
[AcceptOctetStream]
Task<Stream> DownloadAsync();
[Post("WeatherForecast/file")]
[OctetStreamContentType]
Task UpoladAsync([Body]Stream f);
}
- 注册到 ioc 中
new ServiceCollection()
.AddSingleton<ITestClient>() // 依照本人须要设置生命周期就好,并且不须要写具体实现,Norns.Urd.HttpClient 会为您生成对应 IL 代码
.ConfigureAop(i => i.EnableHttpClient())
- 通过 DI 应用就好,比方
[ApiController]
[Route("[controller]")]
public class ClientController : ControllerBase
{
private readonly ITestClient client;
public ClientController(ITestClient client)
{this.client = client;}
[HttpGet("download")]
public async Task<object> DownloadAsync()
{using var r = new StreamReader(await client.DownloadAsync());
return await r.ReadToEndAsync();}
}
HttpClient 反对的性能
Url 配置
BaseAddress
如果有些网站域名或者根底 api 地址都是很多接口都会应用的,就能够在接口上应用 BaseAddressAttribute
如:
[BaseAddress("http://localhost.:5000")]
public interface ITestClient
各种 Http Method 反对设置 Url
Http Method 反对如下:
- GetAttribute
- PostAttribute
- PutAttribute
- DeleteAttribute
- PatchAttribute
- OptionsAttribute
- HeadAttribute
(上述 method 不够应用时,能够继承HttpMethodAttribute
自定义实现)
所有的这些 Http Method 都反对配置 Url,有以下两种形式反对:
- 动态配置
[Post("http://localhost.:5000/money/getData/")]
public Data GetData()
- 动静配置
默认反对从 IConfiguration
通过 key 获取 url 配置
[Post("configKey", IsDynamicPath = true)]
public Data GetData()
如果这样简略的配置模式不反对您的需要,能够实现 IHttpRequestDynamicPathFactory
接口替换配置实现形式,实现好的类只需注册到 IOC 容器就能够了。
实现示例能够参考 ConfigurationDynamicPathFactory
路由参数设置
如果某些 url 路由参数须要动静设置,您能够通过 RouteAttribute
设置, 如
[Post("getData/{id}")]
public Data GetData([Route]string id)
如果参数名字不匹配 url 外面的设置,能够通过Alias =
设置,如
[Post("getData/{id}")]
public Data GetData([Route(Alias = "id")]string number)
Query string 设置
Query string 参数能够在办法参数列表中设置
[Post("getData")]
public Data GetData([Query]string id);
//or
[Post("getData")]
public Data GetData([Query(Alias = "id")]string number);
其 Url 后果都为 getData?id=xxx
,
参数类型反对根本类型和 class,
当为 class 时,会取 class 的属性作为参数,
所以当属性名不匹配定义时,能够在属性上用 [Query(Alias = "xxx")]
指定
Request body 设置
Request body 能够通过能够在办法参数列表中设置 BodyAttribute
指定参数,
需注意,只有第一个有 BodyAttribute
的参数会失效,举例如
public void SetData([Body]Data data);
将依据设置的 Request Content-Type 抉择序列化器序列化 body
Response body 设置
Response body 的类型指定,只需在办法的 return type 写上须要的类型就好,反对以下
- void (疏忽反序列化)
- Task (疏忽反序列化)
- ValueTask (疏忽反序列化)
- T
- Task<T>
- ValueTask<T>
- HttpResponseMessage
- Stream (只能 Content-Type 为 application/octet-stream 时起效)
举例如:
public Data GetData();
Content-Type 设置
无论 Request 还是 Response 的 Content-Type 都会影响 序列化和反序列化器的抉择,
默认反对 json/xml 的序列化和反序列化,能够通过如下设置
- JsonContentTypeAttribute
- XmlContentTypeAttribute
- OctetStreamContentTypeAttribute
举例如:
[OctetStreamContentType]
public Data GetData([Body]Stream s);
对应的 Accept 设置为
- AcceptJsonAttribute
- AcceptXmlAttribute
- AcceptOctetStreamAttribute
举例如:
[AcceptOctetStream]
public Stream GetData();
json 序列化器默认为 System.Text.Json
更换 json 序列化器为 NewtonsoftJson
- 引入
Norns.Urd.HttpClient.NewtonsoftJson
- 在 ioc 注册办法, 如
new ServiceCollection().AddHttpClientNewtonsoftJosn()
自定义序列化器
当现有序列化器不足以反对需要时,
只需实现 IHttpContentSerializer
并向 ioc 容器注册即可
自定义 Header
除了上述曾经提到的 header 之外,还能够通过增加其余 header
同样有以下两种形式:
- 应用
HeaderAttribute
在接口或办法动态配置
[Header("x-data", "money")]
public interface ITestClient {}
//or
[Header("x-data", "money")]
public Data GetData();
- 办法参数动静配置
public Data GetData([SetRequestHeader("x-data")]string header);
自定义 HttpRequestMessageSettingsAttribute
当现有 HttpRequestMessageSettingsAttribute
不足以反对需要时,
只需继承 HttpRequestMessageSettingsAttribute
实现本人的性能,
在对应的接口 / 办法应用即可
通过参数设置获取 Response Header
当有时咱们须要获取 response 返回的 header 时,
咱们能够 out 参数 + OutResponseHeaderAttribute
获取 Response Header 的值
(需注意,只有同步办法,out 参数能力起作用)
举例如:
public Data GetData([OutResponseHeader("x-data")] out string header);
HttpClient 一些参数设置办法
MaxResponseContentBufferSize
[MaxResponseContentBufferSize(20480)]
public interface ITestClient {}
//or
[MaxResponseContentBufferSize(20480)]
public Data GetData()
Timeout
[Timeout("00:03:00")]
public interface ITestClient {}
//or
[Timeout("00:03:00")]
public Data GetData()
ClientName
当须要联合 HttpClientFactory 获取非凡设置的 HttpClient 时,能够通过ClientNameAttribute
指定
如
[ClientName("MyClient")]
public interface ITestClient {}
//or
[ClientName("MyClient")]
public Data GetData()
就能够获取到这样指定的 HttpClient
services.AddHttpClient("MyClient", i => i.MaxResponseContentBufferSize = 204800);
HttpCompletionOption
HttpClient 调用时的 CompletionOption 参数同样能够设置
HttpCompletionOption.ResponseHeadersRead 是默认配置
如
[HttpCompletionOption(HttpCompletionOption.ResponseContentRead)]
public interface ITestClient {}
//or
[HttpCompletionOption(HttpCompletionOption.ResponseContentRead)]
public Data GetData()
全局 HttpRequestMessage 和 HttpResponseMessage 解决
如果须要全局对 HttpRequestMessage 和 HttpResponseMessage 做一些解决,比方:
- 链路追踪 id 设置
- response 异样自定义解决
能够通过实现 IHttpClientHandler
并向 ioc 容器注册应用
举例默认的 status code 查看,如:
public class EnsureSuccessStatusCodeHandler : IHttpClientHandler
{
public int Order => 0;
public Task SetRequestAsync(HttpRequestMessage message, AspectContext context, CancellationToken token)
{return Task.CompletedTask;}
public Task SetResponseAsync(HttpResponseMessage resp, AspectContext context, CancellationToken token)
{resp.EnsureSuccessStatusCode();
return Task.CompletedTask;
}
}
当然,如果该 StatusCode 查看解决不需要的话,能够间接在 ioc 容器革除掉,如:
services.RemoveAll<IHttpClientHandler>();
// 而后增加本人的解决
services.AddSingleton<IHttpClientHandler, xxx>();
有任何问题欢送大家提 issue (^_^)