19. 远程请求
以下内容仅限 Furion 1.16.0 +
版本使用。
19.1 关于远程请求
在互联网大数据的驱动下,平台或系统免不了需要和第三方进行数据交互,而第三方往往提供了 RESTful API
接口规范,这个时候就需要通过 Http
请求第三方接口进行数据传输交互。
也就是本章节所说的远程请求。
19.2 远程请求的作用
- 跨系统、跨设备通信
- 实现多个系统数据传输交互
- 跨编程语言协同开发
19.3 基础使用
19.3.1 注册服务
使用之前需在 Startup.cs
注册 远程请求服务
public void ConfigureServices(IServiceCollection services){ services.AddRemoteRequest();}
19.3.2 使用方式
Furion
提供两种方式访问发送远程请求。
- IHttpDispatchProxy 代理方式
- 字符串拓展方式
定义代理请求的 接口
并继承 IHttpDispatchProxy
接口
public interface IHttp : IHttpDispatchProxy{ [Get("https://www.furion.icu/get")] Task<Result> GetXXXAsync(); [Post("https://www.furion.icu/post")] Task<Result> PostXXXAsync(); [Put("https://www.furion.icu/put")] Task<Result> PutXXXAsync(); [Delete("https://www.furion.icu/delete")] Task<Result> DeleteXXXAsync(); [Patch("https://www.furion.icu/patch")] Task<Result> PatchXXXAsync(); [Head("https://www.furion.icu/head")] Task<Result> HeadXXXAsync();}
通过构造函数注入 接口
using Furion.DynamicApiController;using Furion.RemoteRequest.Extensions;namespace Furion.Application{ public class RemoteRequestService : IDynamicApiController { private readonly IHttp _http; public RemoteRequestService(IHttp http) { _http = http; } public async Task GetData() { var data = await _http.GetXXXAsync(); } }}
var response = await "https://www.furion.icu/get".GetAsync();var response = await "https://www.furion.icu/post".PostAsync();var response = await "https://www.furion.icu/put".PutAsync();var response = await "https://www.furion.icu/delete".DeleteAsync();var response = await "https://www.furion.icu/patch".PatchAsync();var response = await "https://www.furion.icu/head".HeadAsync();
需引入 using Furion.RemoteRequest.Extensions
命名空间。
19.4 字符串方式使用示例
19.4.1 内置请求方式
// 发送 Get 请求var response = await "https://www.furion.icu/get".GetAsync();// 发送 Post 请求var response = await "https://www.furion.icu/post".PostAsync();// 发送 Put 请求var response = await "https://www.furion.icu/put".PutAsync();// 发送 Delete 请求var response = await "https://www.furion.icu/delete".DeleteAsync();// 发送 Patch 请求var response = await "https://www.furion.icu/patch".PatchAsync();// 发送 Head 请求var response = await "https://www.furion.icu/head".HeadAsync();// 手动指定发送特定请求var response = await "https://www.furion.icu/post".SetHttpMethod(HttpMethod.Post) .SendAsync();
19.4.2 设置请求地址
// 该方式在 Furion v3.0.0 已移除,多此一举了await "".SetRequestUrl("https://www.furion.icu/");
19.4.3 设置请求方式
await "https://www.furion.icu/post".SetHttpMethod(HttpMethod.Get);
19.4.4 设置地址模板
// 字典方式await "https://www.furion.icu/post/{id}?name={name}&id={p.Id}".SetTemplates(new Dictionary<string , object> { { "id", 1 }, { "name", "Furion" }, { "p.Id", new Person { Id = 1 } }});// 对象/匿名对象方式await "https://www.furion.icu/post/{id}?name={name}".SetTemplates(new { id = 1, name = "Furion"});
注:模板替换区分大小写。
19.4.5 设置请求报文头
// 字典方式await "https://www.furion.icu/post".SetHeaders(new Dictionary<string , object> { { "Authorization", "Bearer 你的token"}, { "X-Authorization", "Bearer 你的刷新token"}});// 对象/匿名对象方式await "https://www.furion.icu/post".SetHeaders(new { Authorization = "Bearer 你的token"});
19.4.6 设置 URL
地址参数
// 字典方式await "https://www.furion.icu/get".SetQueries(new Dictionary<string , object> { { "id", 1 }, { "name", "Furion"}});// 对象/匿名对象方式await "https://www.furion.icu/get".SetQueries(new { id = 1, name = "Furion"});
最终输出格式为:https://www.furion.icu/get?id=1&name=Furion
。
19.4.7 设置请求客户端
services.AddRemoteRequest(options=>{ // 配置 Github 基本信息 options.AddHttpClient("github", c => { c.BaseAddress = new Uri("https://api.github.com/"); c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample"); });});await "get".SetClient("github");
最终生成请求地址为:https://api.github.com/get
。
19.4.8 设置 Body
参数
// 传入对象await "https://www.furion.icu/api/user/add".SetBody(new User { Id = 1, Name = "Furion" });// 配置 Content-Typeawait "https://www.furion.icu/api/user/add".SetBody(new { Id = 1, Name = "Furion" }, "application/json");// 设置 Encoding 编码await "https://www.furion.icu/api/user/add".SetBody(new User { Id = 1, Name = "Furion" }, "application/json", Encoding.UTF8);// 处理 application/x-www-form-urlencoded 请求await "https://www.furion.icu/api/user/add".SetBody(new Dictionary<string , object> { { "Id", 1 }, { "Name", "Furion"}}, "application/x-www-form-urlencoded");// 处理 application/xml、text/xmlawait "https://www.furion.icu/api/user/add".SetBody("<SomeDto><SomeTag>somevalue</SomeTag></SomeDto>", "application/xml");
如果请求 Content-Type
设置为 application/x-www-form-urlencoded
类型,那么底层自动将数据进行 UrlEncode
编码处理,无需外部处理。
19.4.9 设置 Content-Type
await "https://www.furion.icu/post".SetContentType("application/json");
19.4.10 设置内容编码
await "https://www.furion.icu/post".SetContentEncoding(Encoding.UTF8);
19.4.11 设置 JSON
序列化提供程序
Furion
默认情况下采用 System.Text.Json
进行 JSON
序列化处理,如需设置第三方 JSON
提供器,则可以通过以下配置:
// 泛型方式await "https://www.furion.icu/api/user/add".SetJsonSerialization<NewtonsoftJsonSerializerProvider>();// 非泛型方式await "https://www.furion.icu/api/user/add".SetJsonSerialization(typeof(NewtonsoftJsonSerializerProvider));// 添加更多配置await "https://www.furion.icu/api/user/add".SetJsonSerialization<NewtonsoftJsonSerializerProvider>(new JsonSerializerSettings {});
JSON
序列化提供器如需了解更多 JSON
序列化知识可查阅 23. JSON 序列化 章节
19.4.12 启用 Body
参数验证
await "https://www.furion.icu/api/user/add".SetValidationState();// 设置不验证 null 值await "https://www.furion.icu/api/user/add".SetValidationState(includeNull: true);
支持类中 [Required]
等完整模型验证特性。
19.4.13 请求拦截
await "https://www.furion.icu/".OnRequesting(req => { // req 为 HttpRequestMessage 对象 // 追加更多参数 req.AppendQueries(new Dictionary<string, object> { { "access_token", "xxxx"} });});
支持多次拦截
19.4.14 HttpClient
拦截
await "https://www.furion.icu/".OnClientCreating(client => { // client 为 HttpClient 对象 client.Timeout = 30000; // 设置超时时间});
支持多次拦截
19.4.15 请求之前拦截
await "https://www.furion.icu/".OnRequesting(req => { // req 为 HttpRequestMessage 对象});
支持多次拦截
19.4.16 成功请求拦截
await "https://www.furion.icu/".OnResponsing(res => { // res 为 HttpResponseMessage 对象});
支持多次拦截
19.4.17 请求异常拦截
await "https://www.furion.icu/".OnException((res,errors) => { // res 为 HttpResponseMessage 对象});
支持多次拦截
19.4.18 各种返回值处理
Furion
远程请求默认提供四种返回值类型:
HttpResponseMessage
:请求响应消息类型Stream
:流类型T
:泛型T
类型String
:字符串类型,也就是直接将网络请求结果内容字符串化Byte[]
:字节数组类型
如:
// HttpResponseMessagevar res = await "https://www.furion.icu/".GetAsync();// Streamvar stream = await "https://www.furion.icu/".GetAsStreamAsync();// Tvar user = await "https://www.furion.icu/".GetAsAsync<User>();// Stringvar str = await "https://www.baidu.com".GetAsStringAsync();
19.4.19 设置 Byte[]
类型/上传文件
有时候我们需要上传文件,需要设置 Content-Type
为 multipart/form-data
类型,如:
// bytes 可以通过 File.ReadAllBytes(文件路径) 获取var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data") .SetBodyBytes(("键", bytes, "文件名")).PostAsync();// 支持多个文件var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data") .SetBodyBytes(("键", bytes, "文件名"),("键", bytes, "文件名")).PostAsync();
如果遇到微信上传出现问题,则可设置 Content-Type
为:application/octet-stream
,如:
var result = await $"https://api.weixin.qq.com/wxa/img_sec_check?access_token={token}" .SetBodyBytes(("media", bytes, Path.GetFileName(imgPath))) .SetContentType("application/octet-stream") .PostAsStringAsync();
19.4.20 设置 IServiceProvider
有时候我们需要构建一个作用域的 IServiceProvider
,这时只需要设置即可:
var res = await "https://www.furion.icu/upload".SetRequestScoped(services);
19.4.21 设置 Timeout
超时时间
var res = await "https://www.furion.icu/upload".SetClientTimeout(10); // 单位秒
19.4.22 支持模板配置
模板格式为:#(配置路径)
var res = await "#(Furion:Address)/upload".GetAsync();
{ "Furion": { "Address": "https://www.furion.icu" }}
19.4.23 重试策略
在 Furion v2.18+
版本支持配置重试策略,如:
var res = await "https://www.furion.icu".SetRetryPolicy(3, 1000).GetAsync();
以上代码表示请求失败重试 3
次,每次延迟 1000ms
。
19.4.24 支持 GZip
压缩
在 Furion v3.2.0+
版本支持GZip
压缩,如:
var res = await "https://www.furion.icu".WithGZip().GetAsync();
19.4.25 设置 Url
转码
过去版本会对所有的 Url
进行 Uri.EscapeDataString
转码,在 Furion v3.8.0+
版本支持 Url
转码设置,如:
var res = await "https://www.furion.icu".WithEncodeUrl(false).GetAsync();
19.5 IHttpDispatchProxy
代理方式
19.5.1 支持多种代理方式
public interface IHttp : IHttpDispatchProxy{ // 发送 Get 请求 [Get("https://www.furion.icu/get")] Task<HttpResponseMessage> GetXXXAsync(); // 发送 Post 请求 [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync(); // 发送 Put 请求 [Put("https://www.furion.icu/put")] Task<HttpResponseMessage> PutXXXAsync(); // 发送 Delete 请求 [Delete("https://www.furion.icu/delete")] Task<HttpResponseMessage> DeleteXXXAsync(); // 发送 Patch 请求 [Patch("https://www.furion.icu/patch")] Task<HttpResponseMessage> PatchXXXAsync(); // 发送 Head 请求 [Head("https://www.furion.icu/head")] Task<HttpResponseMessage> HeadXXXAsync();}
19.5.2 设置地址模板
public interface IHttp : IHttpDispatchProxy{ [Get("https://www.furion.icu/get/{id}?name={name}&number={p.PersonDetail.PhonNumber}")] Task<HttpResponseMessage> GetXXXAsync(int id, string name, Person p);}
注:模板替换区分大小写。
19.5.3 设置请求报文头
Furion
框架远程请求代理模式提供三种方式设置请求报文头:
- 支持在接口中声明
- 支持在方法中声明
- 支持在参数中声明
[Headers("key","value")][Headers("key1","value2")] // 设置多个public interface IHttp : IHttpDispatchProxy{ [Get("https://www.furion.icu/get/{id}?name={name}"), Headers("key2","value2")] Task<HttpResponseMessage> GetXXXAsync(int id, string name); [Get("https://www.furion.icu")] Task<HttpResponseMessage> GetXXX2Async(int id, [Headers]string token = default); [Get("https://www.furion.icu")] Task<HttpResponseMessage> GetXXX2Async(int id, string name, [Headers("别名")]string token = default);}
19.5.4 设置 URL
地址参数
public interface IHttp : IHttpDispatchProxy{ [Get("https://www.furion.icu/get")] Task<HttpResponseMessage> GetXXXAsync([QueryString]int id, [QueryString]string name); [Get("https://www.furion.icu/get")] Task<HttpResponseMessage> GetXXXAsync([QueryString]int id, [QueryString("别名")]string name);}
最终输出格式为:https://www.furion.icu/get?id=1&name=Furion
。
19.5.5 设置请求客户端
services.AddRemoteRequest(options=>{ // 配置 Github 基本信息 options.AddHttpClient("github", c => { c.BaseAddress = new Uri("https://api.github.com/"); c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample"); });});public interface IHttp : IHttpDispatchProxy{ [Get("get"), Client("github")] Task<HttpResponseMessage> GetXXXAsync();}
最终生成请求地址为:https://api.github.com/get
。
19.5.6 设置 Body
参数
public interface IHttp : IHttpDispatchProxy{ [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync([Body]User user); [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync([Body("application/x-www-form-urlencoded")]User user); [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync([Body("application/x-www-form-urlencoded", "UTF-8")]User user);}
19.5.7 设置 JSON
序列化提供程序
Furion
默认情况下采用 System.Text.Json
进行 JSON
序列化处理,如需设置第三方 JSON
提供器,则可以通过以下配置:
public interface IHttp : IHttpDispatchProxy{ [Post("https://www.furion.icu/post"), JsonSerialization(typeof(NewtonsoftJsonSerializerProvider))] Task<HttpResponseMessage> PostXXXAsync([Body]User user); [Post("https://www.furion.icu/post"), JsonSerialization(typeof(NewtonsoftJsonSerializerProvider))] Task<HttpResponseMessage> PostXXXAsync([Body]User user, [JsonSerializerOptions]object jsonSerializerOptions = default); /// <summary> /// 缺省序列化配置 /// </summary> /// <returns></returns> [JsonSerializerOptions] static object GetJsonSerializerOptions() { // 这里也可以通过 JSON.GetSerializerOptions<JsonSerializerOptions>() 获取 Startup.cs 中的配置 return new JsonSerializerOptions { }; }}
[JsonSerializerOptions]
可以标记参数是一个 JSON
序列化配置参数。
JSON
序列化提供器如需了解更多 JSON
序列化知识可查阅 23. JSON 序列化 章节
19.5.8 参数验证
public interface IHttp : IHttpDispatchProxy{ [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync([Range(1,10)]int id, [Required, MaxLength(10)]string name); [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync([Required]User user); // 对象类型支持属性配置特性验证}
19.5.9 请求拦截
Furion
远程请求代理方式提供两种拦截方式:
- 接口静态方法拦截
- 参数标记拦截
public interface IHttp : IHttpDispatchProxy{ // 通过参数拦截 [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Request)] Action<HttpRequestMessage> action = default); // 全局拦截,类中每一个方法都会触发 [Interceptor(InterceptorTypes.Request)] static void OnRequesting1(HttpRequestMessage req) { // 追加更多参数 req.AppendQueries(new Dictionary<string, object> { { "access_token", "xxxx"} }); } // 全局拦截,类中每一个方法都会触发 [Interceptor(InterceptorTypes.Request)] static void OnRequesting2(HttpRequestMessage req) { }}
支持多次拦截
19.5.10 HttpClient
拦截
Furion
远程请求代理方式提供两种拦截方式:
- 接口静态方法拦截
- 参数标记拦截
public interface IHttp : IHttpDispatchProxy{ // 通过参数拦截 [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Client)] Action<HttpRequestMessage> action = default); // 全局拦截,类中每一个方法都会触发 [Interceptor(InterceptorTypes.Client)] static void onClientCreating1(HttpClient req) { } // 全局拦截,类中每一个方法都会触发 [Interceptor(InterceptorTypes.Client)] static void onClientCreating2(HttpClient req) { }}
支持多次拦截
19.5.11 请求之前拦截
Furion
远程请求代理方式提供两种拦截方式:
- 接口静态方法拦截
- 参数标记拦截
public interface IHttp : IHttpDispatchProxy{ // 通过参数拦截 [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Request)] Action<HttpRequestMessage> action = default); // 全局拦截,类中每一个方法都会触发 [Interceptor(InterceptorTypes.Request)] static void OnRequest1(HttpRequestMessage req) { } // 全局拦截,类中每一个方法都会触发 [Interceptor(InterceptorTypes.Request)] static void OnRequest2(HttpRequestMessage req) { }}
支持多次拦截
19.5.12 成功请求拦截
Furion
远程请求代理方式提供两种拦截方式:
- 接口静态方法拦截
- 参数标记拦截
public interface IHttp : IHttpDispatchProxy{ // 通过参数拦截 [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Response)] Action<HttpResponseMessage> action = default); // 全局拦截,类中每一个方法都会触发 [Interceptor(InterceptorTypes.Response)] static void OnResponsing1(HttpResponseMessage res) { } // 全局拦截,类中每一个方法都会触发 [Interceptor(InterceptorTypes.Response)] static void OnResponsing2(HttpResponseMessage res) { }}
支持多次拦截
19.5.13 请求异常拦截
Furion
远程请求代理方式提供两种拦截方式:
- 接口静态方法拦截
- 参数标记拦截
public interface IHttp : IHttpDispatchProxy{ // 通过参数拦截 [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Exception)] Action<HttpResponseMessage, string> action = default); // 全局拦截,类中每一个方法都会触发 [Interceptor(InterceptorTypes.Exception)] static void OnException1(HttpResponseMessage res, string errors) { } // 全局拦截,类中每一个方法都会触发 [Interceptor(InterceptorTypes.Exception)] static void OnException2(HttpResponseMessage res, string errors) { }}
支持多次拦截
19.5.14 各种返回值处理
Furion
远程请求默认提供四种返回值类型:
HttpResponseMessage
:请求响应消息类型Stream
:流类型T
:泛型T
类型String
:字符串类型,也就是直接将网络请求结果内容字符串化
如:
public interface IHttp : IHttpDispatchProxy{ [Post("https://www.furion.icu/post")] Task<HttpResponseMessage> PostXXXAsync(); [Post("https://www.furion.icu/post")] Task<Stream> PostXXXAsync(); [Post("https://www.furion.icu/post")] Task<User> PostXXXAsync(); [Post("https://www.furion.icu/post")] Task<string> PostXXXAsync();}
19.5.15 设置 Byte[]
类型/上传文件
有时候我们需要上传文件,需要设置 Content-Type
为 multipart/form-data
类型,如:
public interface IHttp : IHttpDispatchProxy{ [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] // bytes 可以通过 File.ReadAllBytes(文件路径) 获取 Task<HttpResponseMessage> PostXXXAsync([BodyBytes("键","文件名")]Byte[] bytes); // 支持多个文件 [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] // bytes 可以通过 File.ReadAllBytes(文件路径) 获取 Task<HttpResponseMessage> PostXXXAsync([BodyBytes("键","文件名")]Byte[] bytes,[BodyBytes("键","文件名")]Byte[] bytes2);}
19.5.16 设置 Timeout
超时时间
[Timeout(1000)]public interface IHttp : IHttpDispatchProxy{ [Post("https://www.furion.icu/upload"), Timeout(500)] // 单位秒 Task<HttpResponseMessage> PostXXXAsync([Body]User user);}
19.5.17 支持模板配置
模板格式为:#(配置路径)
public interface IHttp : IHttpDispatchProxy{ [Post("#(Furion:Address)/upload")] Task<HttpResponseMessage> PostXXXAsync([Body]User user);}
{ "Furion": { "Address": "https://www.furion.icu" }}
方法的优先级高于接口定义的优先级。
19.5.18 重试策略
在 Furion v2.18+
版本支持配置重试策略,如:
[RetryPolicy(3, 1000)] // 支持全局public interface IHttp : IHttpDispatchProxy{ [Post("https://www.furion.icu"), RetryPolicy(3, 1000)] // 支持局部 Task<HttpResponseMessage> PostXXXAsync([Body]User user);}
以上代码表示请求失败重试 3
次,每次延迟 1000ms
。
19.5.19 支持 GZip
在 Furion v3.2.0+
版本支持 GZip
,如:
public interface IHttp : IHttpDispatchProxy{ [Post("https://www.furion.icu", WithGZip = true)] Task<HttpResponseMessage> PostXXXAsync([Body]User user);}
19.5.20 设置 Url
转码
过去版本会对所有的 Url
进行 Uri.EscapeDataString
转码,在 Furion v3.8.0+
版本支持 Url
转码设置,如:
public interface IHttp : IHttpDispatchProxy{ [Post("https://www.furion.icu", WithEncodeUrl = false)] Task<HttpResponseMessage> PostXXXAsync([Body]User user);}
19.6 多个请求客户端配置
Furion
框架也提供了多个请求客户端配置,可以为多个客户端请求配置默认请求信息,如:
services.AddRemoteRequest(options=>{ // 配置默认 HttpClient options.AddHttpClient(string.Empty, c => { // 其他配置 }); // 配置特定客户端 options.AddHttpClient("github", c => { c.BaseAddress = new Uri("https://api.github.com/"); c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample"); });})
配置了命名客户端后,每次请求都会自动加上这些配置。
- 在
代理请求
使用
[Get("api/getdata"), Client("github")]Task<User> GetData();[Put("api/getdata"), Client("facebook")]Task<User> GetData();
- 在
字符串拓展
使用
// 设置请求拦截var response = await "http://47.100.247.61/api/sysdata/categories".SetClient("github").PostAsync();
19.7 SSL/https
证书配置
有时候我们请求远程接口时会遇到 The SSL connection could not be established, see inner exception.
这样的错误,原因是证书配置不正确问题,下面有几种解决方法。
19.7.1 忽略特定客户端 SSL
证书检查
services.AddRemoteRequest(options=>{ // 默认 HttpClient 在 Furion 框架内部已经配置了该操作 options.AddHttpClient(string.Empty) .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler { ServerCertificateCustomValidationCallback = (_, _, _, _) => true, }); // 配置特定客户端 options.AddHttpClient("github", c => { /*其他配置*/ }) .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler { ServerCertificateCustomValidationCallback = (_, _, _, _) => true, });});
HttpClientHandler
和 SocketsHttpHandler
在 .NET6
之后默认使用 SocketsHttpHandler
作为默认底层网络通信,但比 HttpClientHandler
提供了更多平台无差异的功能,对 HttpClientHandler
的任何设置都会转发到 SocketsHttpHandler
中,如需使用 SocketsHttpHandler
配置可参考:
// 忽略 SSL 不安全检查,或 https 不安全或 https 证书有误options.AddHttpClient(string.Empty) .ConfigurePrimaryHttpMessageHandler(u => new SocketsHttpHandler { SslOptions = new SslClientAuthenticationOptions { RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true } });
19.7.2 手动指定 SSL
证书
services.AddRemoteRequest(options=>{ // 配置特定客户端 options.AddHttpClient("github", c => { /*其他配置*/ }) .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler { // 手动配置证书 ClientCertificateOptions = ClientCertificateOption.Manual, ClientCertificates = { new X509Certificate2("...","..."), new X509Certificate2("...","..."), new X509Certificate2("...","...") } });});
19.7.3 忽略所有客户端证书检查
以下内容仅限 Furion v3.6.6+
版本使用。
services.AddRemoteRequest(options=>{ // 需在所有客户端注册之前注册 options.ApproveAllCerts();});
19.8 关于返回值非 200
时忽略 Http状态
Furion
提供了非常方便的请求并且序列化请求结果 PostAsAsync<T>
在 2.8.8
及以下版本,当返回结果的 Http
状态为非 200
时,会直接截断。考虑到请求接口的多样性,在 2.8.9
及以上版本增加忽略返回 Http
状态,直接序列化结果的方式。
//请求并且序列化请求结果var result = await "https://api.facebook.com/" //如果不加OnException,则会直接截断 .OnException((res,errors)=> { //激活异步拦截 此处可以做记录日志操作 也可保持现状 }) .PostAsAsync<T>();
PostAsStringAsync()
也使用同样的 OnException
操作使得忽略返回 Http
状态,原样返回 Http
请求结果
如果不加 OnException
,则会直接截断。
如果需要复杂的 Http Post
请求,建议直接使用 PostAsync
,返回值为 HttpResponseMessage
,可以更灵活的控制结果。
19.9 关于同步请求
Furion
框架内部默认不提供同步请求操作,建议总是使用异步的方式请求。如在不能使用异步的情况下,可自行转换为同步执行。
19.10 多线程共享作用域
默认情况下,所有的 字符串
和 实体
拓展都有自己独立维护的 ServiceProvider
作用域。
在 Web
请求中,默认是 HttpContext.RequestServices
,但在 非 Web
,如多线程操作,后台任务,事件总线等场景下会自动创建新的作用域,实际上这是非常不必要的内存开销。
这时,我们只需要通过 .SetXXXScoped(service)
共享当前服务提供器作用域即可,如:
Scoped.Create(async (fac, scope) => { var response = await "https://www.furion.icu".SetRequestScoped(scope.ServiceProvider).PostAsync();});
19.11 静态 Default
方式构建
await HttpRequestPart.Default.SetRequestUrl("https://www.baidu.com").GetAsStringAsync();
19.12 反馈与建议
给 Furion 提 Issue。
想了解更多 HttpClient
知识可查阅 ASP.NET Core - HTTP 请求 章节