写点什么

介绍一个新库: Norns.Urd.HttpClient

用户头像
八苦-瞿昙
关注
发布于: 2021 年 01 月 03 日

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/Norns.Urd


如何启用 HttpClient 功能


  1. 引入 Norns.Urd.HttpClient

dotnet add package Norns.Urd.HttpClient
复制代码


  1. 代码中开启 HttpClient 功能,只需


new ServiceCollection()    .ConfigureAop(i => i.EnableHttpClient())
复制代码


  1. 定义 要使用的 HttpClient 接口


举例如:


[BaseAddress("http://localhost.:5000")]public interface ITestClient{    [Get("WeatherForecast/file")]    [AcceptOctetStream]    Task<Stream> DownloadAsync();
[Post("WeatherForecast/file")] [OctetStreamContentType] Task UpoladAsync([Body]Stream f);}
复制代码


  1. 注册到 ioc 中


new ServiceCollection()    .AddSingleton<ITestClient>()  // 按照自己需要设置生命周期就好,并且不需要写具体实现,Norns.Urd.HttpClient会为您生成对应IL代码    .ConfigureAop(i => i.EnableHttpClient())
复制代码


  1. 通过 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


  1. 引入 Norns.Urd.HttpClient.NewtonsoftJson

  2. 在 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 (^_^)


发布于: 2021 年 01 月 03 日阅读数: 23
用户头像

八苦-瞿昙

关注

一个假和尚,不懂人情世故。 2018.11.23 加入

会点点技术,能写些代码,只爱静静。 g hub: https://github.com/fs7744 黑历史:https://www.cnblogs.com/fs7744

评论

发布
暂无评论
介绍一个新库: Norns.Urd.HttpClient