3.38扩展构建器

框架提供了 Clone() 和 CopyTo() 方法,用于复制或迁移 HttpRequestBuilder 的配置。这在需要复用一组公共配置(如认证头、超时时间等)并应用到多个不同请求时尤为有用。

克隆和复制#

框架提供了 Clone()CopyTo() 方法,用于复制或迁移 HttpRequestBuilder 的配置。这在需要复用一组公共配置(如认证头、超时时间等)并应用到多个不同请求时尤为有用。

cs
var httpRequestBuilder = HttpRequestBuilder.Get("https://furion.net/").Profiler();// 克隆操作:返回一个全新的构建器var newBuilder = httpRequestBuilder.Clone();    // 完整克隆var newBuilder = httpRequestBuilder.Clone("RequestUri", "HttpMethod");  // 排除特定属性// 复制操作:将源构建器的配置复制到目标构建器var sourceBuilder = HttpRequestBuilder.Get("https://furion.net/api/user").UseETag().SetQuotaKey("api/user");sourceBuilder.CopyTo(httpRequestBuilder);   // 完整复制sourceBuilder.CopyTo(httpRequestBuilder, "RequestUri", "HttpMethod");   // 排除特定属性

获取请求构建器或请求消息(预检请求)#

在某些情况下,您可能希望只获取 HTTP 请求对象本身,而不实际发送请求。例如:在单元测试中验证生成的请求是否符合预期,或拿到请求构建器后进一步手动修改,亦或是将请求消息传递给另一个系统执行。

为此,当发送 HTTP 远程请求的方法的返回类型为 HttpRequestBuilderHttpRequestMessage 时,框架将直接构建并返回该对象,跳过实际的网络传输。示例如下:

cs
// 获取构建器,可继续链式配置后手动发送var builder = await httpRemoteService.GetAsAsync<HttpRequestBuilder>("https://furion.net");	// 不发送请求builder.WithHeader("X-Custom", "value");var httpResponseMessage = await httpRemoteService.SendAsync(builder);	// 发起网络请求// 获取 HttpRequestMessage,用于断言或外部传递var httpRequestMessage = await httpRemoteService.GetAsAsync<HttpRequestMessage>("https://furion.net");	// 不发送请求Assert.Equal("https://furion.net/", httpRequestMessage.RequestUri?.ToString());

应用场景#

  • 预检请求(Pre-flight Check):在正式发送前,检查生成的请求对象是否符合预期。确认 URL、请求头、Token 注入等都正确无误后,再手动发送或继续处理。
  • 单元测试:无需模拟网络环境,直接验证生成的 HttpRequestMessage 是否包含了正确的参数、头和认证信息。
  • 请求对象传递:将构造好的 HttpRequestMessage 传递给其他服务、库或进程执行,实现请求构造与请求执行的分离。
  • 混合编程:先通过构建器或声明式完成大部分配置(参数映射、Token 注入等),再拿到构建器进行少量动态修改后手动发送,兼顾声明式的简洁与命令式的灵活。

HttpRequestBuilder 统一配置器#

在通过 HttpRequestBuilder 类构建 HttpRequestMessage 对象时,若需对所有请求进行全局配置,框架提供了统一的配置机制。

开发者可通过实现 IHttpRequestBuilderConfigurator 接口,对 HttpRequestBuilder 实例进行统一设置。例如,以下 HttpRequestBuilderConfigurator 类在 Configure 方法中为所有请求添加了一个公共请求头:

cs
public class HttpRequestBuilderConfigurator : IHttpRequestBuilderConfigurator{    /// <inheritdoc />    public void Configure(HttpRequestBuilder httpRequestBuilder)    {        httpRequestBuilder.WithHeader("global", "form_furion");    }}

实现自定义配置器后,需在配置 HttpRemoteOptions 时将其赋值给 HttpRequestBuilderConfigurator 属性:

cs
services.AddHttpRemote(builder => {})    .ConfigureOptions(options =>    {        options.HttpRequestBuilderConfigurator = new HttpRequestBuilderConfigurator();    });

配置生效后,所有 HttpRequestBuilder 实例在调用 Build() 方法构建 HttpRequestMessage 之前,均会执行此统一配置逻辑。

自定义 HttpRequestBuilder 扩展方法#

除了框架自带的 HttpRequestBuilder 方法外,您还可以通过自定义扩展方法来简化代码、减少重复逻辑。例如,添加一个 SetAccept 方法,用于快速设置 HTTP 请求头中的 Accept 字段:

cs
public static class HttpRequestBuilderExtensions{    public static HttpRequestBuilder SetAccept(this HttpRequestBuilder httpRequestBuilder, string accept)    {        // 参数校验:确保 accept 不为空        ArgumentException.ThrowIfNullOrWhiteSpace(accept);        return httpRequestBuilder.WithHeader("Accept", accept, replace: true);    }}

定义完成后,即可在 HttpRequestBuilder 实例中链式调用该方法:

cs
HttpRequestBuilder.Get("https://furion.net")    .SetAccept("text/html");

借助 C# 扩展方法的特性,您可以轻松扩展 HttpRequestBuilder 的功能,从而提升代码的可读性可维护性,并有效减少重复代码。

自定义扩展其他构建器#

以下构建器均派生自 HttpRequestBuilderConfigurator<THttpBuilder> 抽象类型:

  • HttpFileDownloadBuilder
  • HttpFileUploadBuilder
  • HttpLongPollingBuilder
  • HttpServerSentEventsBuilder
  • HttpStressTestHarnessBuilder

这些构建器共享统一的扩展机制。例如,它们都支持通过 With(builder => { ... }) 方法为底层 HttpRequestBuilder 配置额外的请求参数。

HttpRequestBuilderConfigurator<THttpBuilder> 已内置了一些常用方法(如 Profiler())。如果需要进一步扩展,可以按照如下方式编写扩展方法:

cs
public static class HttpRequestBuilderConfiguratorExtensions{    /// <summary>    ///     当 HTTP 响应的 IsSuccessStatusCode 属性为 <c>false</c> 时,抛出异常。    /// </summary>    /// <param name="configurator">    ///     <see cref="HttpRequestBuilderConfigurator{THttpBuilder}" />    /// </param>    /// <typeparam name="THttpBuilder">派生构建器的具体类型</typeparam>    /// <returns>返回构建器自身实例,支持链式调用。</returns>    public static THttpBuilder EnsureSuccessStatusCode<THttpBuilder>(this HttpRequestBuilderConfigurator<THttpBuilder> configurator)        where THttpBuilder : HttpRequestBuilderConfigurator<THttpBuilder>    {        return configurator.With(builder => builder.EnsureSuccessStatusCode());    }}

这样,上述所有构建器都可以直接调用 EnsureSuccessStatusCode() 方法,并返回自身构建器实例,保持流畅的链式调用体验。