5.11语言 / 消息属性 / 标准标头 / Host

全球化是互联网应用产品的发展趋势,因此,面向全球的应用产品应具备国际化功能。发送 HTTP 请求时,可通过添加 AcceptLanguageAttribute 特性来指定客户端偏好的自然语言和区域。

设置客户端偏好的语言和区域#

全球化是互联网应用产品的发展趋势,因此,面向全球的应用产品应具备国际化功能。发送 HTTP 请求时,可通过添加 AcceptLanguageAttribute 特性来指定客户端偏好的自然语言和区域。

HTTP 声明式请求通过 AcceptLanguageAttribute 特性来设置客户端偏好的语言和区域。相应的 HTTP 声明式提取器实现为 AcceptLanguageDeclarativeExtractor 类型,该类型负责解析 AcceptLanguageAttribute 特性并构建 HttpRequestBuilder 实例所需的客户端偏好的语言和区域配置。

cs
// 在接口定义上应用,影响所有方法[AcceptLanguage("en-US")]public interface IHttpService : IHttpDeclarative{    // 在方法上应用    [AcceptLanguage("zh-CN,en;q=0.5")]    [Get("https://furion.net/")]    Task<string> GetStringAsync();    [AcceptLanguage("fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5")]    [Get("https://furion.net/")]    Task<string> GetStringAsync();}

AcceptLanguageAttribute 包含以下构造函数和属性:

  • 构造函数

    • new(language):作用于方法或接口,配置客户端偏好的语言和区域。
  • 属性

    • Language:客户端偏好的语言和区域(string 类型)。

设置 HttpRequestMessage 属性#

在特定场景下,我们可能需要为 HttpRequestMessage 请求添加额外的属性,而非通过请求标头。

HTTP 声明式请求通过 PropertyAttribute 特性来设置 HttpRequestMessage 请求属性。相应的 HTTP 声明式提取器实现为 PropertyDeclarativeExtractor 类型,该类型负责解析 PropertyAttribute 特性并构建 HttpRequestBuilder 实例所需的 HttpRequestMessage 请求属性配置。

利用 PropertyAttribute 特性,可以便捷地在接口、方法或参数上添加 HttpRequestMessage 请求属性。

cs
// 在接口定义上应用,影响所有方法[Property("property1", "value1")][Property("property2", "value2")][Property("property0")] // 值为 nullpublic interface IHttpService : IHttpDeclarative{    // 在方法上应用    [Property("property3", "value3")]    [Property("property4", "value4")]    [Get("https://furion.net/")]    Task<string> GetStringAsync();    // 在参数上应用,支持 AliasAs 属性指定别名,且可多重指定    [Property("property3", "value3")]    [Get("https://furion.net/")]    Task<string> GetStringAsync([Property] string property4, [Property][Property(AliasAs = "property5")] int lastProperty);    // 在参数上可通过 Value 属性设定默认值,同样可为 age 参数设定,例如 int? age = 30    [Get("https://furion.net/")]    Task<string> GetStringAsync([Property(Value = 30)] int? age);    // 支持 [AliasAs] 定义别名    [Get("https://furion.net/")]    Task<string> GetStringAsync([Property][AliasAs("property5")] int lastProperty);    // 添加对象内容,AsItem 为 false 时,对象会被解析并遍历,其属性将作为独立的 HttpRequestMessage 请求属性项进行设置    [Get("https://furion.net/")]    Task<string> GetStringAsync([Property(AsItem = false)] object obj);    // 冻结参数类型将被忽略    [Get("https://furion.net/")]    Task<string> GetStringAsync([Property] CancellationToken cancellationToken);}

这些属性会被添加到 HttpRequestMessage 对象的 Options 属性中(参考文档)。要获取这些值,可以这样做:

cs
httpRequestMessage.Options.TryGetValue(new HttpRequestOptionsKey<string>("key1"), out var value);

若属性键出现重复,则后设置的键值会覆盖先前的设置。

PropertyAttribute 包含以下构造函数和属性:

  • 构造函数

    • new():作用于参数时有效,表示添加 HttpRequestMessage 请求属性,默认键为参数名。
    • new(name):作用于方法或接口时,则表示添加 HttpRequestMessage 请求属性操作,值为 null;作用于参数时,表示添加 HttpRequestMessage 请求属性,键为参数 name 的值。
    • new(name, value):作用于接口、方法或参数,表示添加 HttpRequestMessage 请求属性,键为参数 name 的值,优先级低于 AliasAs 属性。
  • 属性

    • NameHttpRequestMessage 请求属性键(string 类型),优先级低于 AliasAs 属性。
    • ValueHttpRequestMessage 请求属性的值(object 类型),当特性作用于参数时,表示默认值。
    • AliasAsHttpRequestMessage 请求属性键别名(string 类型),优先级高于 Name 属性。
    • AsItem:表示是否作为 HttpRequestMessage 请求属性的一项(bool 类型),默认值为 true(作为),仅当参数为对象类型时有效。为 false(不作为) 时,对象会被解析并遍历,其属性将作为独立的 HttpRequestMessage 请求属性项进行设置。

启用标准请求标头#

为了提升应用通过 HTTP 客户端发送网络请求的兼容性并避免被 WAFWeb 应用防火墙)拦截,框架提供了一键式配置方法,方便快速统一设置标准的请求头部。

HTTP 声明式请求通过 StandardRequestHeadersAttribute 特性来启用标准请求标头。相应的 HTTP 声明式提取器实现为 StandardRequestHeadersDeclarativeExtractor 类型,该类型负责解析 StandardRequestHeadersAttribute 特性并构建 HttpRequestBuilder 实例所需的配置。

cs
// 在接口定义上应用,影响所有方法[StandardRequestHeaders]public interface IHttpService : IHttpDeclarative{    // 在方法上应用    [StandardRequestHeaders]    [Get("https://furion.net/")]    Task<string> GetStringAsync();    [StandardRequestHeaders(false)]   // 关闭标准请求标头    [Get("https://furion.net/")]    Task<string> GetStringAsync();}

此外,除了为单个请求启用标准标头配置,还可以全局注册以在 HttpClient 中启用:

cs
// 为默认客户端启用services.AddHttpClient(string.Empty, client =>{    client.UseStandardRequestHeaders();});services.AddHttpRemote();

启用标准请求标头后,请求将自动添加以下头部:

  • Acceptapplication/jsontext/plain;q=0.9*/*;q=0.8(明确的媒体类型优先级,避免被 WAF 拦截)
  • Connection:启用持久连接(Keep-Alive),减少 TCP 连接建立和关闭的开销

StandardRequestHeadersAttribute 包含以下构造函数和属性:

  • 构造函数

    • new():作用于方法或接口,启用标准请求标头。
    • new(enabled):作用于方法或接口,设置是否启用标准请求标头。
  • 属性

    • Enabled:是否启用(bool 类型),默认值为 true(启用)。

设置自动 Host 标头#

Host 标头是 HTTP/1.1 协议中的一个必需标头。Host 标头用于指定请求的目标服务器的主机名和端口号,确保服务器能正确区分同一 IP 地址上的不同域名并进行相应处理。框架提供了简便的方法进行设置:

HTTP 声明式请求通过 AutoSetHostHeaderAttribute 特性来设置自动 Host 标头。相应的 HTTP 声明式提取器实现为 AutoSetHostHeaderDeclarativeExtractor 类型,该类型负责解析 AutoSetHostHeaderAttribute 特性并构建 HttpRequestBuilder 实例所需的自动 Host 标头配置。

cs
// 在接口定义上应用,影响所有方法[AutoSetHostHeader] // 启用public interface IHttpService : IHttpDeclarative{    // 在方法上应用    [AutoSetHostHeader]    [Get("https://furion.net/")]    Task<string> GetStringAsync();    [AutoSetHostHeader(false)]   // 关闭自动 Host 标头    [Get("https://furion.net/")]    Task<string> GetStringAsync();}

启用后,发送 HTTP 远程请求时会自动添加 Host: furion.net 标头。

AutoSetHostHeaderAttribute 包含以下构造函数和属性:

  • 构造函数

    • new():作用于方法或接口,设置自动 Host 标头。
    • new(enabled):作用于方法或接口,设置是否设置自动 Host 标头。
  • 属性

    • Enabled:是否启用(bool 类型),默认值为 true(启用)。