Common.HttpClients 2.0.0

dotnet add package Common.HttpClients --version 2.0.0
                    
NuGet\Install-Package Common.HttpClients -Version 2.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Common.HttpClients" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Common.HttpClients" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Common.HttpClients" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Common.HttpClients --version 2.0.0
                    
#r "nuget: Common.HttpClients, 2.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Common.HttpClients@2.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Common.HttpClients&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Common.HttpClients&version=2.0.0
                    
Install as a Cake Tool

Common.HttpClients

一个功能丰富的HTTP客户端库,基于 Microsoft.Extensions.Http.Resilience 和 Polly,提供强大的弹性和韧性功能。

主要特性

  • 🚀 高性能HTTP客户端
  • 📝 智能日志记录和审计(包含请求前后日志)
  • ⚙️ 灵活的配置管理(支持运行时验证)
  • 🔒 请求/响应拦截
  • 📊 响应内容长度控制
  • 🎯 请求级别的日志控制
  • 🔄 异常或超时自动重试(支持自定义超时时间、重试次数、延迟)
  • 🛡️ 完整的 Polly 弹性策略(降级、并发限制、重试、熔断器、超时)
  • 🔍 分布式追踪支持(X-Trace-Id 自动传播)
  • 🔐 支持忽略不安全的SSL证书(仅建议开发/测试环境使用)
  • ⚡ 401未授权错误可配置重试
  • 🔏 可扩展的日志脱敏(支持自定义敏感头和字段)

安装

dotnet add package Common.HttpClients

快速开始

1. 注册服务

// 使用默认配置
services.AddHttpClientService();

// 或自定义配置
services.AddHttpClientService(options =>
{
    options.AuditLog = true;                        // 启用审计日志
    options.FailThrowException = false;              // 失败时不抛出异常,返回 null
    options.Timeout = 30;                            // 自定义超时时间(秒),范围:1-3600
    options.MaxRetryAttempts = 3;                    // 最大重试次数,范围:0-10
    options.RetryDelaySeconds = 1;                   // 重试基础延迟(秒),范围:1-300
    options.ConcurrencyLimit = 100;                  // 并发限制,范围:1-10000
    options.MaxOutputResponseLength = 1024 * 1024;   // 日志最大输出长度 1MB
    options.IgnoreUntrustedCertificate = false;      // ⚠️ 生产环境建议设为 false
    options.RetryOnUnauthorized = true;              // 401未授权错误时自动重试
    options.AdditionalSensitiveHeaders = new[] { "X-Secret" }; // 额外脱敏请求头
    options.AdditionalSensitiveFields = new[] { "mobile" };    // 额外脱敏字段
});

// ⚠️ 无效配置将抛出异常
// services.AddHttpClientService(options =>
// {
//     options.Timeout = 5000; // ❌ ArgumentOutOfRangeException: Timeout必须在1-3600秒之间
// });

2. 使用HTTP客户端

public class MyService
{
    private readonly IHttpHelper _httpHelper;

    public MyService(IHttpHelper httpHelper)
    {
        _httpHelper = httpHelper;
    }

    public async Task<string> GetDataAsync()
    {
        var result = await _httpHelper.GetAsync<string>(Host + "/get?q1=11&q2=22");

        return result;
    }
}

配置选项 HttpClientOptions

属性 类型 默认值 说明
AuditLog bool true 是否启用审计日志
FailThrowException bool false 失败时是否抛出异常。false 时返回 null,true 时抛出异常
EnableLogRedaction bool true 是否启用日志脱敏
Timeout int 100 超时时间(秒),范围:1-3600
ConcurrencyLimit int 100 并发限制,范围:1-10000,建议按下游容量调整
MaxRetryAttempts int 3 最大重试次数,范围:0-10
RetryDelaySeconds int 1 重试基础延迟(秒),指数退避,范围:1-300
MaxOutputResponseLength int 0 日志最大输出响应长度(字节),≥0。0 表示不限制
IgnoreUntrustedCertificate bool false 是否忽略不安全的SSL证书,⚠️ 仅建议开发/测试环境使用
RetryOnUnauthorized bool false 401未授权错误时是否重试
AdditionalSensitiveHeaders ICollection<string> 额外需要脱敏的请求头(不区分大小写)
AdditionalSensitiveFields ICollection<string> 额外需要脱敏的字段名(JSON/key=value,不区分大小写)

配置验证:所有参数都有范围限制,超出范围将抛出 ArgumentOutOfRangeException

请求

下面示例已经注入IHttpHelper

Get

var result = await _httpHelper.GetAsync<string>(Host + "/get?q1=11&q2=22");

还支持传递token以及传递请求头

Post

Json格式

支持传递字符串以及对象

var content = "{\"q\":\"123456\",\"a\":\"222\"}";
var result = await _httpHelper.PostAsync<string>(Host + "/post", content);
PostFormData
  • Task<T> PostFormDataAsync<T>(string url, MultipartFormDataContent formDataContent);
请求示例
using var form = new MultipartFormDataContent();

// bytes为文件字节数组
using var fileContent = new ByteArrayContent(bytes);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                                         {
                                             Name = "file", // 表单字段名称
                                             FileName = fileName // 文件名
                                         };
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
form.Add(fileContent);

// 其他参数
using var content = new StringContent("其他参数值");
form.Add(content, "其他参数名称");

var requestUrl = $"{_difyApiBase}/v1/files/upload";
var response = await _httpHelper.PostFormDataAsync<FileUploadResponse>(requestUrl, form,
    new Dictionary<string, string> { { "Authorization", $"Bearer {_difyApiKey}" } });

日志

可以设置配置AuditLog来设置是否启用审计日志,默认为启用状态。

builder.Services.AddHttpClientService();

也可以为指定地址请求设置关闭审计日志,例如

var result = await _httpHelper.PostAsync<string>(Host + "/anything", list,
    headers: new Dictionary<string, string>() { { "X-Logger", "skip" } });

var result2 = await _httpHelper.PostAsync<string>(Host + "/anything", list,
    headers: new Dictionary<string, string>() { { "X-Skip-Logger", "" } });

可以通过在请求头设置X-Skip-Logger或者设置X-Logger值为none、skip进行跳过日志

日志脱敏说明

  • 默认脱敏字段包含:passwordtokenaccess_tokenrefresh_tokenapi_key 等常见字段
  • 默认脱敏请求头包含:AuthorizationCookieX-Api-Key
  • 可通过 AdditionalSensitiveFieldsAdditionalSensitiveHeaders 扩展脱敏范围
  • 当前脱敏主要覆盖 JSON 和 key=value 文本,不保证覆盖所有嵌套/编码场景(例如复杂嵌套 JSON、base64 token)

GetStreamAsync 会自动跳过响应体审计,避免流式读取场景下日志提前消费响应流。

弹性策略

本库使用 Polly 实现了完整的弹性策略链,按以下顺序执行(从外层到内层):

1. 降级处理(Fallback)

当所有策略都失败时的最后保障:

  • 如果 FailThrowException = false:返回 503 响应,方法返回 null
    • 响应包含 X-Fallback-Response: true 头,可区分真实服务端错误
  • 如果 FailThrowException = true:重新抛出原始异常

2. 并发限制(Concurrency Limiter)

限制同时进行的HTTP请求数量,默认 ConcurrencyLimit = 100,可按业务压测结果调整

3. 重试策略(Retry)

自动重试失败的请求:

  • 重试次数MaxRetryAttempts(默认 3)
  • 重试延迟RetryDelaySeconds(默认 1 秒)作为基础值,使用指数退避
  • 重试条件
    • HTTP 5xx 服务器错误
    • HTTP 408 请求超时
    • HTTP 401 未授权(如果 RetryOnUnauthorized = true
    • 超时异常(TimeoutExceptionTaskCanceledExceptionTimeoutRejectedException
    • HTTP 请求异常(HttpRequestException

4. 熔断器(Circuit Breaker)

当错误率达到阈值时暂时停止请求,保护下游系统

5. 超时策略(Timeout)

防止请求长时间阻塞:

  • 使用配置的 Timeout 值(默认 100 秒)
  • 每次重试都会重新应用超时限制
  • 超时后会触发重试机制

重要说明:超时策略放在最内层,每次重试都会应用超时限制。总超时上界约为:Timeout × (MaxRetryAttempts + 1) + 重试延迟总和

分布式追踪

本库自动支持分布式追踪,通过 X-Trace-Id 请求头传播追踪ID:

追踪ID获取优先级

  1. 从当前请求的 X-Trace-Id 请求头获取
  2. HttpContext.Request.Headers 中获取 X-Trace-Id
  3. 使用 ASP.NET Core 的 HttpContext.TraceIdentifier
  4. 如果都没有,自动生成新的 GUID

日志示例

所有日志都包含 TraceId,方便追踪整个请求链路:

Http请求开始.TraceId:a1b2c3d4e5f6 Url:https://api.example.com/data Method:GET
Http请求审计日志.TraceId:a1b2c3d4e5f6 Url:https://api.example.com/data Method:GET StatusCode:OK 耗时:1234.56ms

超时与重试说明

超时机制

  • HttpClient.Timeout:设置为无限,不控制超时
  • Polly Timeout 策略:完全控制超时行为,使用配置的 Timeout
  • CancellationToken:用于调用方主动取消请求,不与 Resilience 超时策略冲突

重试机制示例

场景1:自定义超时 30 秒
options.Timeout = 30;
options.MaxRetryAttempts = 2;
options.RetryDelaySeconds = 1;
  • 单次请求超过 30 秒 → 触发重试
  • 最多重试 2 次(共 3 次尝试),每次都有 30 秒超时限制
  • 重试延迟:1s → 2s
  • 总耗时:最长约 93 秒(30s×3 + 1s + 2s)
场景2:使用默认超时 100 秒
// 不设置 Timeout,使用默认值 100 秒
  • 单次请求超过 100 秒 → 触发重试
  • 默认最多重试 3 次(共 4 次尝试),每次都有 100 秒超时限制
  • 默认总耗时:最长约 407 秒(100s×4 + 1s + 2s + 4s)
场景3:401 未授权重试
options.RetryOnUnauthorized = true;
  • 收到 401 响应 → 触发重试
  • 适用于 token 自动刷新场景
  • 重试延迟:1s → 2s → 4s

异常处理

FailThrowException = false(默认)

options.FailThrowException = false;
  • 请求失败或超时:返回 nulldefault(T)
  • 错误信息记录在日志中
  • 适合不需要中断业务流程的场景
  • Fallback 产生的 503 响应包含 X-Fallback-Response: true 头,可据此判断是否为 Fallback 响应

FailThrowException = true

options.FailThrowException = true;
  • 请求失败或超时:抛出异常
  • 需要业务代码使用 try-catch 处理
  • 适合需要明确处理错误的场景

识别 Fallback 响应示例

// 使用原始 SendAsync 获取完整响应
using var request = new HttpRequestMessage(HttpMethod.Get, url);
var response = await _httpHelper.SendAsync(request);

if (response.StatusCode == HttpStatusCode.ServiceUnavailable)
{
    var isFallback = response.Headers.Contains("X-Fallback-Response");
    if (isFallback)
    {
        // 这是 Fallback 产生的响应,说明所有重试都失败了
        _logger.LogWarning("All retries failed for {Url}", url);
    }
    else
    {
        // 这是真实的服务端 503 错误
        _logger.LogWarning("Service unavailable at {Url}", url);
    }
}

安全注意事项

SSL证书验证

⚠️ 生产环境安全警告

// ❌ 不要在生产环境使用
options.IgnoreUntrustedCertificate = true;

IgnoreUntrustedCertificate 选项会完全禁用SSL证书验证,这会使您的应用容易受到中间人攻击(MITM)。

建议做法

  • 仅在开发/测试环境使用此选项
  • 生产环境应使用有效的SSL证书
  • 考虑使用环境变量控制:
    #if DEBUG
    options.IgnoreUntrustedCertificate = true;
    #else
    options.IgnoreUntrustedCertificate = false;
    #endif
    

敏感信息日志

默认情况下,库会自动脱敏常见的敏感字段和请求头。但如果您的 API 使用自定义字段名(如 userSecretapiKey 等),请务必配置:

options.AdditionalSensitiveFields = new[] { "userSecret", "customToken" };
options.AdditionalSensitiveHeaders = new[] { "X-Custom-Auth" };

版本更新记录

  • 2.0.0
    • [破坏性变更] 移除 IHttpHelper 全部方法中的 int? timeout 参数,避免与 Resilience Timeout 策略冲突
    • 请求超时统一由 AddHttpClientService(options => options.Timeout = xx) 全局配置控制
    • 单次请求如需提前终止,请使用 CancellationToken
    • 新增可配置项:
      • ConcurrencyLimit:并发限制数量(默认 100)
      • MaxRetryAttempts:最大重试次数(默认 3)
      • RetryDelaySeconds:重试基础延迟(默认 1 秒)
      • AdditionalSensitiveHeaders:额外脱敏请求头
      • AdditionalSensitiveFields:额外脱敏字段
    • 日志脱敏支持自定义扩展字段与请求头
    • 新增配置参数验证(范围限制)
    • Fallback 响应添加 X-Fallback-Response 标识头
    • 优化 JsonHelper 性能(使用静态配置)
    • 优化 ResponseStream.DisposeAsync 释放顺序
    • 修复流式请求日志审计冲突(GetStreamAsync 自动跳过响应体审计)
  • 1.3.3
    • 传递bearerToken的时候主动判断是否拼接Bearer头
  • 1.3.2
    • 更新jwtToken命名为bearerToken
  • 1.3.1
    • 支持.Net10
    • 支持超时或者错误后自动重试
  • 1.3.1-beta3
    • 引用.Net10正式包
  • 1.3.1-beta2
    • 重试测试
    • 日志输出增加请求耗时
  • 1.3.1-beta1
    • 支持设置是否忽略不安全的SSL证书
  • 1.3.0-beta9
    • 更新响应日志输出内容
    • 增加支持CancellationToken
    • 移除对.NetStandard2.1支持
  • 1.3.0-beta8
    • 优化单独请求的日志输出
  • 1.3.0-beta7
    • 修复调用接口报错在忽略异常的情况下扔抛出错误
  • 1.3.0-beta6
    • 优化审计日志
  • 1.3.0-beta5
    • 增加全局设置超时时间以及针对指定请求设置超时时间
  • 1.3.0-beta4
    • 修改PostFormDataAsync方法,增加直接传递jwtToken入参
  • 1.3.0-beta3
    • 修复LoggingHandler被错误重用的问题,将其生命周期改为Transient
  • 1.3.0-beta2
    • 增加流式响应PostGetStreamAsync
    • 暴漏基础的SendAsync
  • 1.3.0-beta1
    • 支持.Net9
    • 增加请求审计日志
  • 1.2.3
    • 注入的时候支持设置是否异常直接抛出
  • 1.2.2
    • 增加x-www-form-urlencoded请求方式代码
    • 升级支持.Net8
  • 1.2.1
    • 增加get获取文件流的方法
  • 1.2.0
    • 升级支持.net7
  • 1.1.5
    • 修改put请求命名问题
    • 增加patch请求
  • 1.1.4
    • 处理多个构造函数的报错
    • 增加更加灵活的请求方式Send
  • 1.1.3
    • 增加http请求FormData形式去提交文件
    • 支持框架netstandard2.1、net6.0
  • 1.1.2
    • 更新post方法同时兼容string和其他类型
  • 1.1.1
    • 更新post方法,配置多个目标框架
  • 1.1.0
    • 更新框架版本为5.0
  • 1.0.0
    • 3.1版本的http请求公共库
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 80 3/3/2026
1.3.3 113 1/23/2026
1.3.2 110 1/22/2026
1.3.1 402 11/15/2025
1.3.1-beta3 287 11/12/2025
1.3.1-beta2 163 11/2/2025
1.3.1-beta1 242 10/14/2025
1.3.0 626 7/1/2025
1.3.0-beta9 240 9/29/2025
1.3.0-beta8 209 8/12/2025
1.3.0-beta7 364 5/21/2025
1.3.0-beta6 262 4/23/2025
1.3.0-beta5 163 4/19/2025
1.3.0-beta4 165 3/21/2025
1.3.0-beta3 272 3/19/2025
1.3.0-beta2 206 3/18/2025
1.3.0-beta1 158 1/12/2025
1.2.3 4,282 9/24/2024
1.2.2 2,204 6/18/2024
1.2.1 5,476 3/18/2023
Loading failed