.NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
Flurl.Http-3.2.4 升级到 4.0.0 版本后,https请求异常:Call failed. The SSL connection could not be established.
如下图:
Flurl.Http-3.2.4版本绕过https的代码,对于 Flurl.Http-4.0.0 版本来说方法不再适用,3.2.4及4.0.0版本绕过https代码成果在文章最后有展示。
查看了Flurl.Http4.0的文档,地址:Configuration - Flurl
配置相关文档内容简单翻译(翻译可能不够精准,请点击上面链接查看官方文档)如下:
配置
Flurl.Http 包含一组强大的选项和技术,用于在各个级别配置其行为。
设置
Flurl 主要通过 Settings上可用的属性进行配置。以下是可用的设置:IFlurlClient IFlurlRequest IFlurlClientBuilder HttpTest
Setting | Type | Default Value |
---|---|---|
Timeout | TimeSpan? | 100 seconds |
HttpVersion | string | "1.1" |
AllowedHttpStatusRange | string | null ("2xx,3xx", effectively) |
Redirects.Enabled | bool | true |
Redirects.AllowSecureToInsecure | bool | false |
Redirects.ForwardHeaders | bool | false |
Redirects.ForwardAuthorizationHeader | bool | false |
Redirects.MaxAutoRedirects | int | 10 |
JsonSerializer | ISerializer | DefaultJsonSerializer |
UrlEncodedSerializer | ISerializer | UrlEncodedSerializer |
所有属性都是读/写的,可以直接设置:
// set default on the client:
var client = new FlurlClient("https://some-api.com");
client.Settings.Timeout = TimeSpan.FromSeconds(600);
client.Settings.Redirects.Enabled = false;
// override on the request:
var request = client.Request("endpoint");
request.Settings.Timeout = TimeSpan.FromSeconds(1200);
request.Settings.Redirects.Enabled = true;
您还可以流畅地配置它们:
clientOrRequest.WithSettings(settings => {
settings.Timeout = TimeSpan.FromSeconds(600);
settings.AllowedHttpStatusRange = "*";
settings.Redirects.Enabled = false;
})...
或者在很多情况下甚至更流利:
clientOrRequest
.WithTimeout(600)
.AllowAnyHttpStatus()
.WithAutoRedirect(false)
...
当同时使用客户端、请求和流畅配置时,您需要密切关注正在配置的对象,因为它可以确定对该客户端的后续调用是否受到影响:
await client
.WithSettings(...) // configures the client, affects all subsequent requests
.Request("endpoint") // creates and returns a request
.WithSettings(...) // configures just this request
.GetAsync();
无客户端模式支持所有相同的扩展方法。配置并发送请求而无需显式引用客户端:
var result = await "https://some-api.com/endpoint"
.WithSettings(...) // configures just this request
.WithTimeout(...) // ditto
.GetJsonAsync<T>();
上述所有设置和扩展方法也可以在 上使用IFlurlClientBuilder,这对于在启动时进行配置非常有用:
// clientless pattern, all clients:
FlurlHttp.Clients.WithDefaults(builder =>
builder.WithSettings(...));
// clientless pattern, for a specific site/service:
FlurlHttp.ConfigureClientForUrl("https://some-api.com")
.WtihSettings(...);
// DI pattern:
services.AddSingleton<IFlurlClientCache>(_ => new FlurlClientCache()
// all clients:
.WithDefaults(builder =>
builder.WithSettings(...))
// specific named client:
.Add("MyClient", "https://some-api.com", builder =>
builder.WithSettings(...))
Settings支持(以及所有相关的流畅优点)的第四个也是最后一个对象是HttpTest,并且它优先于所有内容:
using var test = new HttpTest.AllowAnyHttpStatus();
await sut.DoThingAsync(); // no matter how things are configured in the SUT,
// test settings always win
序列化器
和设置值得特别注意JsonSerializer。UrlEncodedSerializer正如您所料,它们分别控制(反)序列化 JSON 请求和响应以及 URL 编码的表单帖子的详细信息。两者都实现了ISerializer,定义了 3 个方法:
string Serialize(object obj);
T Deserialize<T>(string s);
T Deserialize<T>(Stream stream);
Flurl 为两者提供了默认实现。您不太可能需要使用不同的UrlEncodedSerializer,但您可能出于以下几个原因想要更换JsonSerializer:
-
您更喜欢3.x 及更早版本的基于Newtonsoft的版本。(4.0 将其替换为基于System.Text.Json的版本。)这可以通过 Flurl.Http.Newtsonsoft配套包获得。
-
您想要使用默认实现,但使用自定义JsonSerializerOptions。这可以通过提供您自己的实例来完成:
clientOrRequest.Settings.JsonSerializer = new DefaultJsonSerializer(new JsonSerializerOptions {PropertyNameCaseInsensitive = true,IgnoreReadOnlyProperties = true
});
事件处理程序
将日志记录和错误处理等横切关注点与正常逻辑流程分开通常会产生更清晰的代码。Flurl.Http 定义了 4 个事件 - BeforeCall、AfterCall、OnError和OnRedirect- 以及、和EventHandlers上的集合。(与 不同,事件处理程序在 上不可用。)IFlurlClient IFlurlRequest IFlurlClientBuilder Settings HttpTest
与 类似Settings,所有具有EventHandlers属性的东西都会带来一些流畅的快捷方式:
clientOrRequest.BeforeCall(call => DoSomething(call)) // attach a synchronous handler.OnError(call => LogErrorAsync(call)) // attach an async handler
在上面的示例中,call是 的一个实例FlurlCall,其中包含与请求和响应的各个方面相关的一组可靠的信息和选项:
IFlurlRequest Request
HttpRequestMessage HttpRequestMessage
string RequestBody
IFlurlResponse Response
HttpResponseMessage HttpResponseMessage
FlurlRedirect Redirect
Exception Exception
bool ExceptionHandled
DateTime StartedUtc
DateTime? EndedUtc
TimeSpan? Duration
bool Completed
bool Succeeded
OnError在 之前触发AfterCall,并让您有机会决定是否允许异常冒泡:
clientOrRequest.OnError(async call => {await LogTheErrorAsync(call.Exception);call.ExceptionHandled = true; // otherwise, the exeption will bubble up
});
OnRedirect允许精确处理 3xx 响应:
clientOrRequest.OnRedirect(call => {if (call.Redirect.Count > 5) {call.Redirect.Follow = false;}else {log.WriteInfo($"redirecting from {call.Request.Url} to {call.Redirect.Url}");call.Redirect.ChangeVerbToGet = (call.Response.Status == 301);call.Redirect.Follow = true;}
});
在较低级别,事件处理程序是实现 的对象IFlurlEventHandler,它定义了 2 个方法:
void Handle(FlurlEventType eventType, FlurlCall call);
Task HandleAsync(FlurlEventType eventType, FlurlCall call);
通常,您只需要实现一个或另一个,因此 Flurl 提供了一个默认实现 ,FlurlEventHanler它构成了一个方便的基类 - 两种方法都是虚拟无操作的,因此只需重写您需要的方法即可。处理程序可以这样分配:
clientOrRequest.EventHandlers.Add((FlurlEventType.BeforeCall, new MyEventHandler()));
请注意,EventHanlers项目的类型为Tuple<EventType, IFlurlEventHandler>。保持处理程序与偶数类型分离意味着给定的处理程序可以重用于不同的事件类型。
您可能更喜欢基于对象的方法而不是前面描述的更简单的基于 lambda 的方法,原因之一是如果您使用 DI 并且您的处理程序需要注入某些依赖项:
public interface IFlurlErrorLogger : IFlurlEventHandler { }public class FlurlErrorLogger : FlurlEventHandler, IFlurlErrorLogger
{private readonly ILogger _logger;public FlurlErrorLogger(ILogger logger) {_logger = logger;}
}
以下是如何使用 Microsoft 的 DI 框架进行连接:
// register ILogger:
services.AddLogging();
// register service that implements IFlurlEventHander and has dependency on ILogger
services.AddSingleton<IFlurlErrorLogger, FlurlErrorLogger>();// register event hanlder with Flurl, using IServiceProvider to wire up dependencies:
services.AddSingleton<IFlurlClientCache>(sp => new FlurlClientCache().WithDefaults(builder =>builder.EventHandlers.Add((FlurlEventType.OnError, sp.GetService<IFlurlErrorLogger>()))
消息处理程序
Flurl.Http 构建于 之上HttpClient,它(默认情况下)使用它HttpClientHandler来完成大部分繁重的工作。IFlurlClientBuilder公开配置两者的方法:
// clientless pattern:
FlurlHttp.Clients.WithDefaults(builder => builder.ConfigureHttpClient(hc => ...).ConfigureInnerHandler(hch => {hch.Proxy = new WebProxy("https://my-proxy.com");hch.UseProxy = true;}));// DI pattern:
services.AddSingleton<IFlurlClientCache>(_ => new FlurlClientCache().WithDefaults(builder => builder..ConfigureHttpClient(hc => ...).ConfigureInnerHandler(hch => ...)));
温馨提示:
1、Flurl 禁用AllowAutoRedirect和UseCookies以便重新实现自己的这些功能概念。如果您将 via 设置为 true ConfigureInnerHander,则可能会破坏 Flurl 中的这些功能。
2、DefaultRequestHeaders Flurl 还实现了自己的和概念Timeout,因此您可能不需要配置HttpClient.
也许您已经阅读过SocketsHttpHandler并且想知道如何在 Flurl 中使用它。您可能会惊讶地发现您可能已经是这样了。如前所述,FlurlClient
将其大部分工作委托给HttpClient
,而后者又将其大部分工作委托给HttpClientHandler
。但鲜为人知的是,自 .NET Core 2.1 以来,HttpClientHandler
几乎将所有工作委托给SocketsHttpHandler
所有支持它的平台,这基本上是除基于浏览器(即 Blazor)平台之外的所有平台。(如果需要说服力,请浏览源代码。)
FlurlClient → HttpClient → HttpClientHandler → SocketsHttpHandler (on all supported platforms)
HttpClientHandler
尽管如此,您可能还是想绕过并直接使用,有一个原因SocketsHttpHander
:它的某些可配置性HttpClientHandler
在. 只要您不需要支持 Blazor,您就可以这样做:
// clientless pattern:
FlurlHttp.Clients.WithDefaults(builder =>builder.UseSocketsHttpHandler(shh => {shh.PooledConnectionLifetime = TimeSpan.FromMinutes(10);...}));// DI pattern:
services.AddSingleton<IFlurlClientCache>(_ => new FlurlClientCache().WithDefaults(builder => builder.UseSocketsHttpHandler(shh => {...})));
注意:在同一构建器上调用ConfigureInnerHandler和UseSocketsHttpHandler会导致运行时异常。使用其中之一,切勿同时使用。
Flurl 直接支持的最后一种消息处理程序类型是DelegatingHandler,这是一种可链接的处理程序类型,通常称为中间件,通常由第三方库实现。
// clientless pattern:
FlurlHttp.Clients.WithDefaults(builder => builder.AddMiddleare(new MyDelegatingHandler()));// DI pattern:
services.AddSingleton<IFlurlClientCache>(sp => new FlurlClientCache().WithDefaults(builder => builder.AddMiddleware(sp.GetService<IMyDelegatingHandler>())
此示例使用流行的弹性库Polly以及在 DI 场景中配置 Flurl:
using Microsoft.Extensions.Http;var policy = Policy.Handle<HttpRequestException>()...services.AddSingleton<IFlurlClientCache>(_ => new FlurlClientCache().WithDefaults(builder => builder.AddMiddleware(() => new PolicyHttpMessageHandler(policy))));
上面的示例需要安装Microsoft.Extensions.Http.Polly。
以上是配置相关的文档,我并没有在文档中发现关于https的相关配置。
Flurl.Http-3.2.4版本绕过https证书代码:
//Startup的ConfigureServices方法中配置
Flurl.Http.FlurlHttp.ConfigureClient(AppSettings.SFGZAPI.serversUrl, cli =>cli.Settings.HttpClientFactory = new UntrustedCertClientFactory()); //此类建立你觉得方便的地方即可
public class UntrustedCertClientFactory : DefaultHttpClientFactory
{public override HttpMessageHandler CreateMessageHandler(){return new HttpClientHandler{ServerCertificateCustomValidationCallback = (a, b, c, d) => true};}
}
对于4.0.0版本,经过一番阅读源代码【https://github.com/tmenier/Flurl】并测试,测试如下图:
上面截图代码均测试,依然还是:无法建立SSL连接。
又一次阅读文档无客户端使用,发现FlurlHttp.UseClientCachingStrategy说明:
看到可以在这个方法中设置FlurlHttp,一直以为是配置,原来我自己进入了坑,请阅读管理客户端相关文档:Managing Clients - Flurl 或阅读译文:.NetCore Flurl.Http 4.0.0 以上管理客户端-CSDN博客,于是开始了尝试并可以正常访问:
//无客户端使用
FlurlHttp.UseClientCachingStrategy(request =>
{FlurlHttp.Clients.GetOrAdd("https://xxx", "https://xxx", builder =>builder.ConfigureInnerHandler(hch =>{hch.ServerCertificateCustomValidationCallback = (a, b, c, d) => true;}));return "https://xxx";
});
测试:
/// <summary>
/// 无客户端模式
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("FlurlHttp")]
public async Task<ActionResult> FlurlHttp()
{try{var a = await "https://xxx".WithHeader("xx", "xxx").PostAsync().ReceiveJson<dynamic>();return Ok(a);}catch (Exception ex){return BadRequest(ex.Message);}
}
还有依赖注入模式经过测试也是可以的:
希望本文对你有帮助。
相关文章:

.NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
Flurl.Http-3.2.4 升级到 4.0.0 版本后,https请求异常:Call failed. The SSL connection could not be established. 如下图: Flurl.Http-3.2.4版本绕过https的代码,对于 Flurl.Http-4.0.0 版本来说方法不再适用,3.2.…...

【每周AI简讯】GPT-5将有指数级提升,GPT Store正式上线
AI7 - Chat中文版最强人工智能 OpenAI的CEO奥特曼表示GPT-5将有指数级提升 GPT奥特曼参加Y-Combinator W24启动会上表示,我们已经非常接近AGI。GPT-5将具有更好的推理能力、更高的准确性和视频支持。 GPT Store正式上线 OpenAI正式推出GPT store,目前…...

QT上位机开发(MFC vs QT)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 在qt之前,上位机开发的主要方法就是mfc。后来出现了c#语言之后,上位机的开发就有一部分人转成了c#。这些开发都是在windows平台完成的,而linux上面的界面,则都是通过各种小众库…...

线性代数:矩阵的定义
目录 一、定义 二、方阵 三、对角阵 四、单位阵 五、数量阵 六、行(列)矩阵 七、同型矩阵 八、矩阵相等 九、零矩阵 十、方阵的行列式 一、定义 二、方阵 三、对角阵 四、单位阵 五、数量阵 六、行(列)矩阵 七、同型矩…...

k8s 使用cert-manager证书管理自签
个人建议使用安装更快,比helm快,还要等待安装crd kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.yaml#官网 https://cert-manager.io/docs/installation/kubectl/#创建自签的ClusterIssuer c…...

SpringSecurity+JWT前后端分离架构登录认证
目录 1. 数据库设计 2. 代码设计 登录认证过滤器 认证成功处理器AuthenticationSuccessHandler 认证失败处理器AuthenticationFailureHandler AuthenticationEntryPoint配置 AccessDeniedHandler配置 UserDetailsService配置 Token校验过滤器 登录认证过滤器接口配置…...

笔试面试题——二叉树进阶(一)
📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、根据二叉树创建字符串1、题目讲解2、思路讲解3、代码实现 二、二叉树的分层遍历1、题目讲…...

Java反射示例
Java反射示例 创建数据类型ReflectPoint.java package com.reflection;import java.util.Date;public class ReflectPoint {private Date birthday new Date();private int x;public int y;public String str1 "ball";public String str2 "basketball"…...

【WinForm.NET开发】实现使用后台操作的窗体
本文内容 创建使用后台操作的窗体使用设计器创建 BackgroundWorker添加异步事件处理程序添加进度报告和取消支持Checkpoint 如果某项操作需要很长的时间才能完成,并且不希望用户界面 (UI) 停止响应或阻塞,则可以使用 BackgroundWorker 类在另一个线程上…...

【操作系统和计网从入门到深入】(四)基础IO和文件系统
前言 这个专栏其实是博主在复习操作系统和计算机网络时候的笔记,所以如果是博主比较熟悉的知识点,博主可能就直接跳过了,但是所有重要的知识点,在这个专栏里面都会提到!而且我也一定会保证这个专栏知识点的完整性&…...

四.Winform使用Webview2加载本地HTML页面并互相通信
Winform使用Webview2加载本地HTML页面并互相通信 往期目录本节目标核心代码实现HTML代码实现的窗体Demo2代码效果图 往期目录 往期相关文章目录 专栏目录 本节目标 实现刷新按钮点击 C# winform按钮可以调用C# winform代码显示到html上点击HTML按钮可以调用C# winform代码更…...

如何有效清理您的Python环境:清除Pip缓存
Python是一个广泛使用的高级编程语言,以其强大的库和框架而闻名。然而,随着时间的推移和不断安装新的包,Python环境可能会变得混乱不堪,尤其是pip缓存可能占用大量的磁盘空间。本文将向您展示如何有效地清理pip缓存,保…...

Jira 母公司全面停服 Server 产品,用户如何迁移至极狐GitLab
Jira 母公司即将全面停服旗下部分 Server 端产品的销售和服务支持! Jira 母公司 Atlassian 在几年前确定了公司的战略为“全面上云”,为此做出了停止 Server 产品的销售和支持。整个时间线从 2021 年 2 月 2 日开始,直到今年 2 月 15 日&…...

Docker安装配置OnlyOffice
OnlyOffice 是一款强大的办公套件,你可以通过 Docker 轻松安装和部署它。本文将指导你完成安装过程。 步骤 1:拉取 OnlyOffice Docker 镜像 首先,使用以下命令从 Docker Hub 拉取 OnlyOffice Document Server 镜像: sudo docke…...

启动低轨道卫星LEO通讯产业与6G 3GPP NTN标准
通讯技术10年一个大跃进,从1990年的2G至2000年的3G网路,2010年的4G到近期2020年蓬勃发展的5G,当通讯技术迈入融合网路,当前的 5G 技术不仅可提供高频宽、低延迟,同时可针对企业与特殊需求以 5G 专网的模式提供各式服务…...

PICO Developer Center 创建和调试 ADB 命令
PICO 开发者中心概览 ADB 是一个轻量级的 Android 调试桥(Android Debug Bridge,简称 ADB),用于与 Android 设备进行通信和调试。ADB提供了许多有用的功能,使开发人员能够轻松地管理和调试设备上的应用程序。 你可以使用 PDC 工具来调试系统…...

【VRTK】【PICO】如何快速创建一个用VRTK开发的PICO项目
【背景】 每次新建一个VRTK的PICO项目总是做一些重复工作,于是就想着搞成一个基本的包,把基本的设置都放进去,今后新做项目直接导这个包就行了。 完整资源包请见本篇博客的绑定资源。 【内容简介】 这个包是我为了快速开发基于VRTK的PICO应用设置的基础项目包。每次开发…...

国产操作系统:VirtualBox安装openKylin-1.0.1虚拟机并配置网络
国产操作系统:VirtualBox安装openKylin-1.0.1虚拟机并配置网络 openKylin 操作系统目前适配支持X86、ARM、RISC-V三个架构的个人电脑、平板电脑及教育开发板,可以满足绝大多数个人用户及开发者的使用需求。适用于在VirtualBox平台上安装openKylin-1.0.1…...

本地git切换地区后,无法使用ssh访问github 22端口解决方案
问题 由于放假回家,发现之前一直使用正常的git,与github无法通讯,pull和push都无法连接。报错如下: connect to host github.com port 22: Connection timed out fatal: Could not read from remote repository. 原因 可能是所…...

Chat2DB:AI赋能的多数据库客户端工具,开源领航未来数据库管理
Chat2DB:开源多数据库客户端的AI革新 Chat2DB使用教程:Chat2DB使用教程_哔哩哔哩_bilibili 引言: 随着企业数据的快速膨胀,数据库管理的复杂性也在增加。此时,一个能够跨越数据库边界、并且集成先进的AI功能的工具,不…...

SQL Server修改数据字段名的方法
1. ALTER TABLE语句修改 这是一种最常用的数据库更改字段的方法,使用Alter Table语句来更改数据库字段的名称。 一般格式如下: ALTER TABLE 表名 RENAME COLUMN 原字段名 TO 新字段名; 例如,修改字段名字段名从UserName到Uname:…...

Flutter编译报错Connection timed out: connect
背景:用Android Studo 创建了Flutter项目,编译运行报错java.net.ConnectException: Connection timed out: connect 我自己的环境: windows11 Android Studio Flutter 截图如下: 将错误日志展开之后: Exception…...

PG DBA培训26:PostgreSQL运维诊断与监控分析
本课程由风哥发布的基于PostgreSQL数据库的系列课程,本课程属于PostgreSQL Diagnosis and monitoring analysis,学完本课程可以掌握PostgreSQL日常运维检查-风哥PGSQL工具箱,风哥专用PGSQL工具箱介绍,风哥专用PGSQL工具箱使用&…...

运维之道—生产环境安装Redis
目录 1.前言 2.环境准备 2.1 安装gcc依赖 3.部署安装 3.1 下载redis安装包 3.2 解压并编译安装redis 3.3 配置redis 编辑3.4 启动redis并测试 4. 总结 1.前言 大家好,运维之道的系列文章继续进行,我们今天整理的是Redis生产环境的安装,Redis的安装以及生产环境的…...

人工智能数学验证工具LEAN4【入门介绍3】乘法世界-证明乘法的所有运算律
视频链接,创作不易记得投币哦: import Game.Levels.Multiplication.L08add_mul World "Multiplication" Level 9 Title "mul_assoc" namespace MyNat Introduction " We now have enough to prove that multiplication is a…...

Armv8-M的TrustZone技术简介
TrustZone技术是适用于Armv8-M的可选安全扩展,旨在为各种嵌入式应用提供改进的系统安全基础。 TrustZone技术的概念并不新鲜。该技术已经在Arm Cortex-A系列处理器上使用了几年,现在已经扩展到Armv8-M处理器。 在high level上,TrustZone技术适用于Armv8-M的概念与Arm Cort…...

ctfshow-反序列化(web267-web270)
目录 web267 web268 web269 web270 总结 web267 页面用的什么框架不知道 看源码看一下 框架就是一种软件工具,它提供了一些基础功能和规范,可以帮助开发者更快地构建应用程序。比如Yii框架和ThinkPHP框架就是两个流行的PHP框架,它们提供…...

决策树的分类
概念 决策树是一种树形结构 树中每个内部节点表示一个特征上的判断,每个分支代表一个判断结果的输出,每个叶子节点代表一种分类结果 决策树的建立过程 1.特征选择:选取有较强分类能力的特征。 2.决策树生成:根据选择的特征生…...

LateX--插入伪代码类型详解
文章目录 1.算法伪代码流程图----循环带范围1.1.算法伪代码示例图11.2.算法伪代码示例图2 2.算法伪代码流程图----循环不带范围3.算法伪代码流程图---不带行数数字4.参考文献 1.算法伪代码流程图----循环带范围 #需要插入这个宏包 \usepackage[ruled,linesnumbered]{algorithm…...

《Python数据分析技术栈》第06章使用 Pandas 准备数据 04 DataFrames
04 DataFrames 《Python数据分析技术栈》第06章使用 Pandas 准备数据 04 DataFrames A DataFrame is an extension of a Series. It is a two-dimensional data structure for storing data. While the Series object contains two components - a set of values, and index …...