3.38扩展构建器
框架提供了 Clone() 和 CopyTo() 方法,用于复制或迁移 HttpRequestBuilder 的配置。这在需要复用一组公共配置(如认证头、超时时间等)并应用到多个不同请求时尤为有用。
克隆和复制#
框架提供了 Clone() 和 CopyTo() 方法,用于复制或迁移 HttpRequestBuilder 的配置。这在需要复用一组公共配置(如认证头、超时时间等)并应用到多个不同请求时尤为有用。
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 远程请求的方法的返回类型为 HttpRequestBuilder 或 HttpRequestMessage 时,框架将直接构建并返回该对象,跳过实际的网络传输。示例如下:
// 获取构建器,可继续链式配置后手动发送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 方法中为所有请求添加了一个公共请求头:
public class HttpRequestBuilderConfigurator : IHttpRequestBuilderConfigurator{ /// <inheritdoc /> public void Configure(HttpRequestBuilder httpRequestBuilder) { httpRequestBuilder.WithHeader("global", "form_furion"); }}实现自定义配置器后,需在配置 HttpRemoteOptions 时将其赋值给 HttpRequestBuilderConfigurator 属性:
services.AddHttpRemote(builder => {}) .ConfigureOptions(options => { options.HttpRequestBuilderConfigurator = new HttpRequestBuilderConfigurator(); });配置生效后,所有 HttpRequestBuilder 实例在调用 Build() 方法构建 HttpRequestMessage 之前,均会执行此统一配置逻辑。
自定义 HttpRequestBuilder 扩展方法#
除了框架自带的 HttpRequestBuilder 方法外,您还可以通过自定义扩展方法来简化代码、减少重复逻辑。例如,添加一个 SetAccept 方法,用于快速设置 HTTP 请求头中的 Accept 字段:
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 实例中链式调用该方法:
HttpRequestBuilder.Get("https://furion.net") .SetAccept("text/html");借助 C# 扩展方法的特性,您可以轻松扩展 HttpRequestBuilder 的功能,从而提升代码的可读性、可维护性,并有效减少重复代码。
自定义扩展其他构建器#
以下构建器均派生自 HttpRequestBuilderConfigurator<THttpBuilder> 抽象类型:
HttpFileDownloadBuilderHttpFileUploadBuilderHttpLongPollingBuilderHttpServerSentEventsBuilderHttpStressTestHarnessBuilder
这些构建器共享统一的扩展机制。例如,它们都支持通过 With(builder => { ... }) 方法为底层 HttpRequestBuilder 配置额外的请求参数。
HttpRequestBuilderConfigurator<THttpBuilder> 已内置了一些常用方法(如 Profiler())。如果需要进一步扩展,可以按照如下方式编写扩展方法:
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() 方法,并返回自身构建器实例,保持流畅的链式调用体验。