5.6标头 / 路径参数 / Cookie

添加、修改或移除请求标头。

设置请求标头#

添加、修改或移除请求标头。

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

1. 添加请求标头

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

cs
// 在接口定义上应用,影响所有方法[Header("header1", "value1")][Header("header2", "value2")]public interface IHttpService : IHttpDeclarative{    // 在方法上应用    [Header("header3", "value3")]    [Header("header4", "value4")]    [Get("https://furion.net/")]    Task<string> GetStringAsync();    // 在参数上应用,支持 AliasAs 属性指定别名,且可多重指定    [Header("header3", "value3")]    [Get("https://furion.net/")]    Task<string> GetStringAsync([Header] string header4, [Header][Header(AliasAs = "header5")] int lastHeader);    // 在参数上可通过 Value 属性设定默认值,同样可为 age 参数设定,例如 int? age = 30    [Get("https://furion.net/")]    Task<string> GetStringAsync([Header(Value = 30)] int? age);    // 支持 [AliasAs] 定义别名    [Get("https://furion.net/")]    Task<string> GetStringAsync([Header][AliasAs("header5")] int lastHeader);    // 支持使用冒号(:)配置    [Get("https://furion.net/")]    [Header("User-Agent: HttpAgent")]    Task<string> GetStringAsync();    // 支持 format 格式化    [Get("https://furion.net/")]    Task<string> GetStringAsync([Header(Format = "yyyyMMdd")] DateTime date);    // 冻结参数类型将被忽略    [Get("https://furion.net/")]    Task<string> GetStringAsync([Header] CancellationToken cancellationToken);}

若存在重复的请求标头,它们将被合并,并用逗号加空格(, )分隔多个值。通过设置 Replace = true 属性,可以覆盖先前的请求标头设置。

2. 移除请求标头

HeaderAttribute 特性中,仅指定请求标头键而不赋值,即表示移除该标头。在接口或方法上应用有效。

cs
[Header("header1", "value1")] // 添加 header1 标头[Header("header2")]           // 标记 header2 为待移除public interface IHttpService : IHttpDeclarative{    [Header("header2", "value2")] // 添加 header2 标头    [Header("header3", "value3")] // 添加 header3 标头    [Header("header3")]           // 标记 header3 为待移除    [Get("https://furion.net/")]    Task<string> GetStringAsync();}

在发送 HTTP 请求之前,将移除配置中指定的待移除请求标头集合。也就是说,移除操作会在所有设置操作调用之后执行。

在上述示例中,尽管 GetStringAsync 方法尝试通过 [Header] 特性添加 header2header3 标头,但由于随后分别有 [Header("header2")][Header("header3")] 特性仅指定了请求标头键而未赋值,因此这两个键在最终构建请求标头时会被移除。只有 header1 标头会保留在请求标头中。

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

  • 构造函数

    • new():作用于参数时有效,表示添加请求标头,默认键为参数名。
    • new(name):作用于方法或接口时,若配置字符串不含冒号(:),则表示移除指定请求标头;若含冒号,则以第一个冒号为分隔,左侧为键,右侧为值。作用于参数时,表示添加请求标头,键为参数 name 的值。
    • new(name, value):作用于接口、方法或参数,表示添加请求标头,键为参数 name 的值,优先级低于 AliasAs 属性。
  • 属性

    • Name:请求标头键(string 类型),优先级低于 AliasAs 属性。
    • Value:请求标头的值(object 类型),当特性作用于参数时,表示默认值。
    • AliasAs:请求标头键别名(string 类型),优先级高于 Name 属性。
    • Escape:是否转义请求标头值(bool 类型),默认值为 false(不转义)。
    • Replace:是否替换已存在的请求标头(bool 类型),默认值为 false(追加)。
    • Format:要使用的格式(string? 类型),仅当 Value 实现 IFormattable 时有效。

设置路径参数(模板/配置参数)#

URL 路径中替换对象模板字符串。

HTTP 声明式请求通过 PathAttribute 特性和方法定义的非冻结类型参数来配置路径参数。相应的 HTTP 声明式提取器为 PathDeclarativeExtractor 类型,它负责解析这些 PathAttribute 特性及方法中定义的非冻结类型参数,并构建 HttpRequestBuilder 实例所需的路径参数配置。

cs
// 在接口定义上应用,影响所有方法[Path("path1", "value1")][Path("path2", "value2")]public interface IHttpService : IHttpDeclarative{    // 在方法上应用    [Path("path3", "value3")]    [Get("https://furion.net/{path1}/{path2}/{path3}")]    Task<string> GetStringAsync();    // 方法上定义的非冻结类型参数默认会添加到路径参数中,可在 URL 地址中直接使用    [Get("https://furion.net/{path1}/{path2}/?id={id}&name={name}&address={address}&age={age}&name1={user.Name}&obj={obj}")]    Task<string> GetStringAsync(int id, string name, string[] address, int age, User user, object? obj);    [Get("https://furion.net/{name?}")] // "?" 结尾表示键不存在时替换为空字符串,可结合 [RemoveTrailingSlash] 特性使用    Task<string> GetStringAsync(string name);    [Get("https://furion.net/{**path}")] // "**" 开头表示不对路径分割符 "/" 转义    Task<string> GetStringAsync(string path);    // 冻结参数类型将被忽略    [Get("https://furion.net/")]    Task<string> GetStringAsync(CancellationToken cancellationToken);}

若存在重复的路径参数键,则后设置的键值会覆盖先前的设置。

模板路径语法

模板路径除了直接使用 {key} 外,还支持通过 . 访问对象的属性、嵌套属性,以及通过 [index] 访问集合中的元素。此外,对象类型的属性在未找到同名属性时,会自动尝试将其视为字典,并以路径标识符作为键进行取值(等同于 dict["key"])。

  • {key}:直接替换对应的值。
  • {key.property}:访问 key 对象的 property 属性,或当 key 为字典时访问键为 "property" 的值。
  • {key.property.nested}:多级属性/键访问。
  • {list[0]}:访问 list 集合(数组、List<T> 等)中索引为 0 的元素。
  • {user.names[1]}:先访问 user 对象的 names 属性,再取其索引 1 处的元素。
  • {dic.key}:当 dic 是字典时(包括 Dictionary<string, T>Hashtable 等),dic.key 会作为 dic["key"] 取值。
  • {obj.dictProp.someKey[0].another}:混合使用点号和索引,逐级深入取值。

以上路径都支持在结尾添加 ? 表示值不存在时替换为空字符串,以及添加 ** 前缀表示不对路径分隔符 / 进行转义。

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

  • 构造函数

    • new(name, value):作用于接口或方法,表示添加路径参数,键为参数 name 的值。
  • 属性

    • Name:路径参数键(string 类型)。
    • Value:路径参数的值(object 类型)。

配置参数

除了通过 {key} 模板语法设置路径参数外,框架还提供了配置参数,用于读取配置信息进行替换操作。配置参数使用 [[key]] 语法,例如:

cs
public interface IHttpService : IHttpDeclarative{    [Get("https://furion.net?id=[[id]]&name=[[name]]")]    Task<string> GetStringAsync();}

启用配置参数支持

要在 HttpRemote 服务中启用配置参数支持,请按照以下步骤进行配置:

cs
services.AddHttpRemote(builder => {})    .ConfigureOptions(options =>    {        // 设置用于替换 URL 地址中配置模板参数的提供源        options.Configuration = builder.Configuration;  // 若使用 Furion 框架可直接设置 App.Configuration    });

配置参数的使用

配置参数将从您的配置文件中读取并替换到 URL 中。例如,您的配置文件可能如下所示:

appsettings.json
{  "id": 1,  "name": "Furion"}

配置参数的键支持多种格式语法,以便更灵活地访问配置文件中的值:

  • [[key]]:直接访问 key 对应的值。
  • [[key:sub]]:访问 key 下的 sub 子项的值。
  • [[key:sub:nest]]:访问 key 下的 sub 子项中的 nest 子项的值。
  • 备用值查找:
    • [[notfound | bak]]:如果 notfound 不存在,则查找 bak
    • [[notfound | bak | other]]:如果 notfoundbak 都不存在,则查找 other
    • [[notfound | bak:sub | other:sub:nest]]:支持更深层次的备用查找。
  • 默认值:
    • [[notfound || default]]:如果 notfound 不存在,则使用 default 作为值。
    • [[notfound | bak | other || 默认值]]:结合备用查找和默认值,确保总有值可用。

添加、修改或移除 Cookie

HTTP 声明式请求通过 CookieAttribute 特性来设置或移除 Cookie 。相应的 HTTP 声明式提取器实现为 CookieDeclarativeExtractor 类型,该类型负责解析 CookieAttribute 特性并构建 HttpRequestBuilder 实例所需的 Cookie 配置。

1. 添加 Cookie

利用 CookieAttribute 特性,可以便捷地在接口、方法或参数上添加 Cookie

cs
// 在接口定义上应用,影响所有方法[Cookie("cookie1", "value1")][Cookie("cookie2", "value2")]public interface IHttpService : IHttpDeclarative{    // 在方法上应用    [Cookie("cookie3", "value3")]    [Cookie("cookie4", "value4")]    [Get("https://furion.net/")]    Task<string> GetStringAsync();    // 在参数上应用,支持 AliasAs 属性指定别名,且可多重指定    [Cookie("cookie3", "value3")]    [Get("https://furion.net/")]    Task<string> GetStringAsync([Cookie] string cookie4, [Cookie][Cookie(AliasAs = "cookie5")] int lastCookie);    // 在参数上可通过 Value 属性设定默认值,同样可为 age 参数设定,例如 int? age = 30    [Get("https://furion.net/")]    Task<string> GetStringAsync([Cookie(Value = 30)] int? age);    // 支持 [AliasAs] 定义别名    [Get("https://furion.net/")]    Task<string> GetStringAsync([Cookie][AliasAs("cookie5")] int lastCookie);    // 支持 format 格式化    [Get("https://furion.net/")]    Task<string> GetStringAsync([Cookie(Format = "yyyyMMdd")] DateTime date);    // 冻结参数类型将被忽略    [Get("https://furion.net/")]    Task<string> GetStringAsync([Cookie] CancellationToken cancellationToken);}

若存在重复的 Cookie 键,则后设置的键值会覆盖先前的设置。

2. 移除 Cookie

CookieAttribute 特性中,仅指定 Cookie 键而不赋值,即表示移除该 Cookie。在接口或方法上应用有效。

cs
[Cookie("cookie1", "value1")] // 添加 cookie1[Cookie("cookie2")]           // 标记 cookie2 为待移除public interface IHttpService : IHttpDeclarative{    [Cookie("cookie2", "value2")] // 添加 cookie2    [Cookie("cookie3", "value3")] // 添加 cookie3    [Cookie("cookie3")]           // 标记 cookie3 为待移除    [Get("https://furion.net/")]    Task<string> GetStringAsync();}

在发送 HTTP 请求之前,将移除配置中指定的待移除 Cookie 集合。也就是说,移除操作会在所有设置操作调用之后执行。

在上述示例中,尽管 GetStringAsync 方法尝试通过 [Cookie] 特性添加 cookie2cookie3,但由于随后分别有 [Cookie("cookie2")][Cookie("cookie3")] 特性仅指定了 Cookie 键而未赋值,因此这两个键在最终构建请求标头 Cookie 时会被移除。只有 cookie1 参数会保留在请求标头 Cookie 中。

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

  • 构造函数

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

    • NameCookie 键(string 类型),优先级低于 AliasAs 属性。
    • ValueCookie 的值(object 类型),当特性作用于参数时,表示默认值。
    • AliasAsCookie 键别名(string 类型),优先级高于 Name 属性。
    • Format:要使用的格式(string? 类型),仅当 Value 实现 IFormattable 时有效。