Zeek.Http.Refit 10.0.27

Zeek.Http.Refit

Zeek.Http.RefitZeek.Http 的可选 Refit 薄适配模块包。

它只提供 RefitModule 和 Refit 注册捷径,复用 Zeek.Http 的 endpoint、通用 header 和 authorization handler;它不扫描程序集、不生成代码、不定义 REST DSL,也不改变 Refit 自身行为。

源码结构

模块源码按薄适配边界分目录,但 public API namespace 不变:

Extensions/      # ModuleContext / IServiceCollection 注册入口
Building/        # Refit API builder
Authorization/   # [AllowAnonymous] 标记
Internal/        # Refit -> Zeek request option bridge

安装

<ItemGroup>
  <PackageReference Include="Zeek.Http.Refit" />
</ItemGroup>

业务模块通过依赖 RefitModule 接入;RefitModule 会声明对 HttpModule 的依赖。

注册 Refit API

模块依赖:

public static IReadOnlyList<ModuleDependency> Dependencies =>
    [ModuleDependency.Of<RefitModule>()];

默认 endpoint:

context.AddZeekRefitApi<OrderAuthorizationProvider>(refitSettings, api => api
    .Add<IOrderApi>()
    .Add<ICustomerApi>()
    .Add<IProductApi>());

指定 endpoint:

context.AddZeekRefitApi<ReportAuthorizationProvider>("ReportApi", refitSettings, api => api
    .Add<IReportApi>());

每个 API client 都应绑定自己的 provider 类型,不要集中到一个 provider 里按 endpoint switch:

context.AddZeekRefitApi<IdentityAuthorizationProvider>("IdentityApi", refitSettings, api => api
    .Add<IIdentityApi>());

context.AddZeekRefitApi<OrderAuthorizationProvider>("OrderApi", refitSettings, api => api
    .Add<IOrderApi>()
    .Add<ICustomerApi>());

context.AddZeekRefitApi<ReportAuthorizationProvider>("ReportApi", refitSettings, api => api
    .Add<IReportApi>());

AddZeekRefitApi<TAuthorizationProvider>(...) 只是把多个 AddZeekRefitClient<TApi, TAuthorizationProvider>(...) 聚合到同一 endpoint 和同一 provider 下;每个 Refit interface 仍然显式注册,不扫描程序集。

TAuthorizationProvider 必须是具体 provider 类型;接口或抽象类型会在注册阶段失败。

JWT refresh 推荐结构

Zeek.Http.Refit 不内置 JWT refresh。登录态、bearer token、ERP header credential、refresh token rotation、401 retry 和 UI 跳转都属于应用自己的认证 workflow 或业务 API 模块。

推荐对外暴露后端级入口:

context.AddGtrApis(refitSettings);
context.AddErpApis(refitSettings);

推荐请求链路:

flowchart TD UI["UI / ViewModel"] Api["IGtrOrderApi protected Refit client"] Provider["GtrAuthProvider"] Refresh["GtrAuthService"] AuthApi["IGtrAuthApi anonymous Refit client"] Retry["Gtr401RetryHandler"] Server["Server"] UI --> Api Api --> Provider Provider --> Refresh Refresh --> AuthApi Api --> Retry Retry --> Server Retry -->|401 forced refresh once| Refresh

核心伪代码:

public sealed class GtrAuthProvider(
    GtrAuthService authService) : IZeekHttpAuthorizationProvider
{
    public async ValueTask ApplyAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken = default)
    {
        string? token = await authService.EnsureAccessTokenAsync(cancellationToken);
        if (!string.IsNullOrWhiteSpace(token))
        {
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
        }
    }
}

EnsureAccessTokenAsync(...) 应使用“过期时间驱动懒刷新”:access token 未临近过期时直接返回;即将过期时进入 single-flight 锁,调用匿名 IAuthApi.RefreshAsync(...),保存新 token 后返回。401 retry 应放在应用自定义 DelegatingHandler,retry 只做一次,并且只对可重放请求自动执行。

完整的两种刷新方案、流程图、状态机、single-flight 伪代码和 request body 重放注意事项见:

docs/topics/Zeek.Http 客户端授权与刷新指南.md

响应 envelope 解包

Zeek.Http.Refit 不内置统一业务返回值解包。GTR { code, message, data }、ERP { success, msg, result } 或其它业务 envelope 应由应用 API 模块自己解释。

推荐模式是应用侧自定义 response processor handler:HTTP 非成功状态码原样交给 401 retry 或错误分类;业务成功时把 response content 替换为 data / result JSON;业务失败时抛出后端自己的业务异常。这样 Refit interface 可以直接返回 DTO,同时不会把 GTR 或 ERP 的协议塞进 Zeek.Http.Refit

IZeekHttpResponseProcessorGtrResponseProcessorErpResponseProcessor 在专题中只是伪代码命名,不是当前框架 public API。完整流程图和伪代码见:

docs/topics/Zeek.Http 客户端授权与刷新指南.md

匿名请求

默认请求会经过注册时绑定的 authorization provider。受保护 client 中的少数匿名方法使用 [AllowAnonymous]

[AllowAnonymous]
[Get("/health")]
Task<HealthDto> HealthAsync(CancellationToken cancellationToken = default);

[AllowAnonymous] 会被适配为 ZeekHttpRequestOptions.AllowAnonymous,不会写入真实 HTTP header。登录、刷新等整体匿名 API 优先使用 AddZeekRefitAnonymousClient<TApi>(...)

边界

  • Zeek.Http.Refit 依赖 Refit;Zeek.Http 主包不依赖 Refit。
  • 不自动发现 API interface。
  • 不负责 token 保存、refresh 或 UI 跳转。
  • 不提供 AddZeekRefitBearerClient、JWT scheme registry 或 refresh token store。
  • 不提供统一业务 response unwrap 平台。
  • Refit serializer、attribute、ApiException 行为仍由 Refit 负责。

AOT / Trim

  • AOT 支持等级:Limited。
  • Trim 策略:显式注册 Refit interface,不扫描程序集发现 API interface。
  • 反射策略:Zeek 适配层不引入运行时扫描;Refit 自身代理、attribute、serializer 和 NativeAOT warning 由 Refit 与应用配置承担。

NativeAOT 场景应显式配置 source-generated System.Text.Json serializer;本模块不承诺 Refit upstream warning-clean。

Sample

  • ../../samples/Zeek.HttpRefitSample/
  • ../../samples/Zeek.HttpRefitAuthSample/
  • ../../samples/Zeek.HttpRefitSample.Server/

Zeek.HttpRefitSampleZeek.HttpRefitAuthSample 当前按发布态 sample 处理,通过 PackageReference 消费已发布的 Zeek.Http.Refit 包;Zeek.HttpRefitSample.Server 只是 sample-only HTTP 验收载体。

完整文档

  • ../../docs/modules/Zeek.Http.md
  • ../../docs/topics/Zeek.Http 使用指南.md
  • ../../docs/topics/Zeek.Http 客户端授权与刷新指南.md

当前边界

  • Zeek.Http.Refit 是已发布的可选 Refit 薄适配包;业务项目不使用 Refit 时无需引用。
  • Refit 的 NativeAOT、接口代理、attribute、ApiException 和 serializer 行为不由 Zeek 重新封装。
  • 本模块不提供 token refresh、业务 envelope 解包平台、接口自动发现、上传下载任务管理或传输历史。

No packages depend on Zeek.Http.Refit.

.NET 10.0

Version Downloads Last updated
10.0.42 4 07/29/2026
10.0.41 15 07/22/2026
10.0.40 10 07/22/2026
10.0.39 19 07/19/2026
10.0.38 12 07/17/2026
10.0.37 1 07/16/2026
10.0.36 5 06/29/2026
10.0.35 1 06/29/2026
10.0.31 5 06/27/2026
10.0.30 2 06/27/2026
10.0.29 2 06/26/2026
10.0.28 2 06/26/2026
10.0.27 2 06/26/2026
10.0.26 4 06/25/2026
10.0.25 3 06/24/2026