☰
curl Alt-Svc 支持完全解析:缓存文件格式、构建开关与 libcurl 编程实践
2026/9/28 20:36:49 网站建设 项目流程
  • 人工智能
  • AI Agent
  • 多模态
  • 语音
  • AI 应用

【免费下载链接】ten-framework

Open-source framework for conversational voice AI agents

项目地址:https://gitcode.com/TEN-framework/ten-framework
点击查看免费下载

本仓库(ten-framework)在third_party/curl下以源码形式内置了 curl,本指南以仓库内的 ALTSVC.md 为骨架,结合 lib/altsvc.c、lib/altsvc.h、命令行选项文档与示例代码,系统讲解 curl 对Alt-Svc:HTTP 响应头的支持:如何开启编译开关、如何读懂并维护 Alt-Svc 缓存文件、如何用命令行与 libcurl API 启用该特性。读完本文,你将能够独立解释缓存文件的每一列含义、手动校验缓存行、并通过--alt-svc或CURLOPT_ALTSVC在自己的 HTTP/2、HTTP/3 客户端中落地 Alt-Svc 加速能力。

Alt-Svc 是什么

Alt-Svc(Alternative Services,替代服务)是 curl 对 HTTP 响应头Alt-Svc:的特性支持,其规范定义于 RFC 7838《HTTP Alternative Services》。当服务端希望告知客户端"除了当前这个源(origin)之外,还可以用另一个协议/主机/端口组合来访问我"时,会通过该响应头下发候选地址。客户端将其缓存下来,后续请求即可尝试直接连接替代端点,从而获得更优路径或更高协议版本(例如从 HTTP/2 平滑切换到 HTTP/3/QUIC)。

curl 对这一特性的落地包含三个层面:

  1. 解析层:识别并解析服务端返回的Alt-Svc:响应头(见 lib/altsvc.c 中的Curl_altsvc_parse);
  2. 缓存层:将解析结果持久化为磁盘上的纯文本缓存文件(对应本文主题——缓存文件格式);
  3. 查询层:后续连接时根据源(src)匹配替代端点,并在命中后直接使用(Curl_altsvc_lookup)。

构建时启用 Alt-Svc

curl 的 Alt-Svc 支持由构建开关控制,在 configure 阶段显式启用:

./configure --enable-alt-svc

值得注意的前提:自 7.73.0 起该特性默认开启,因此大多数现代发行版与内置构建无需额外指定此选项。与之对应,源码层面存在一个总开关宏CURL_DISABLE_ALTSVC——当同时定义了CURL_DISABLE_HTTP或CURL_DISABLE_ALTSVC时,lib/altsvc.c 与 lib/altsvc.h 中的实现会被整体编译排除,公共 API 退化为空操作(见altsvc.h末尾的 disabled 分支)。

此外,缓存查询所支持的协议版本与编译选项强相关:从 lib/altsvc.c 的Curl_altsvc_init()可以看到,默认启用的版本位掩码为CURLALTSVC_H1,并在构建了USE_HTTP2时追加CURLALTSVC_H2、在构建了ENABLE_QUIC时追加CURLALTSVC_H3。也就是说:Alt-Svc 缓存中能实际"使用"哪些替代协议,取决于你的 curl 编译进了哪些 HTTP 版本。

命令行用法:--alt-svc

命令行工具侧由--alt-svc <file name>选项启用(仅适用于 HTTPS 协议),其完整定义见 docs/cmdline-opts/alt-svc.d:

curl --alt-svc svc.txt https://example.com

关键行为(源自该选项文档与 src/tool_getparam.c 的实现):

  • 若指定的文件名已存在,curl 会先加载其中的缓存条目;传输结束后,若缓存有变更,会重新写回同一文件;
  • 传入零长度文件名(空字符串)时,curl 只在内存中维护缓存,不加载也不落盘;
  • 该选项可多次使用:curl 会依次加载所有指定文件,但只有最后一个文件用于保存;
  • 若构建未包含 Alt-Svc 特性,使用该选项会直接返回"libcurl 不支持"错误(PARAM_LIBCURL_DOESNT_SUPPORT),命令参数表中该选项注册于 src/tool_getparam.c;
  • 实际生效路径为 src/tool_operate.c:把config->altsvc字符串通过CURLOPT_ALTSVC注入到 easy handle。

在 HTTP/3 场景中,该选项常与 QUIC 端点配合使用,例如 docs/HTTP3.md 中的示例:

curl --alt-svc altsvc.cache https://quic.aiortc.org/

Alt-Svc 缓存文件格式

缓存文件是纯文本、逐行一条记录的格式,每行由9 个以空格分隔的字段组成。

官方示例行

h2 quic.tech 8443 h3-22 quic.tech 8443 "20190808 06:18:37" 0 0

9 个字段逐一拆解

字段序号含义
1源 origin 的 ALPN 协议标识(如h2)
2源 origin 的主机名
3源 origin 的端口号
4目标(替代)主机的 ALPN 协议标识
5目标主机的主机名
6目标主机的端口号
7条目的过期时间,必须用双引号包裹,格式为"YYYYMMDD HH:MM:SS",时区为 GMT
8布尔值(1 或 0),表示该条目是否设置了persist(持久化)标记
9整数优先级值(当前未使用,写 0 即可)

对照示例行可得到完整的语义:源 origin 为h2://quic.tech:8443,其替代端点为同一主机 8443 端口上的h3-22协议(HTTP/3 草案版本标识),过期时间为 2019-08-08 06:18:37(GMT),未标记 persist,优先级为 0。

文件格式的源码级约束

解析器对每一行的尺寸与取值有硬性限制,超出即整行丢弃(见 lib/altsvc.c):

  • 单行最大长度:4095 字符(MAX_ALTSVC_LINE);
  • 主机名字段最长:512 字符(MAX_ALTSVC_HOSTLEN);
  • ALPN 标识字段最长:10 字符(MAX_ALTSVC_ALPNLEN);
  • 日期字段缓冲区:64 字符(MAX_ALTSVC_DATELEN)。

加载逻辑(altsvc_load)以sscanf严格匹配九字段布局(lib/altsvc.c),只有恰好解析出 9 个字段才插入缓存链表。此外:

  • 行首空白会被跳过,以#开头的行作为注释被忽略(lib/altsvc.c);
  • 从源码的alpn2alpnid()(lib/altsvc.c)可以推断:当前读取器只识别h1、h2、h3三种 ALPN 标识,其余字符串(包括示例中遗留的h3-22这类草案标识)会被视为未知协议并跳过该条目;
  • 主机名匹配是大小写不敏感的,且忽略主机名末尾的单个点号(hostcompare,见 lib/altsvc.c);
  • 日期解析经由Curl_getdate_capped完成(lib/altsvc.c),写回时由altsvc_out按YYYYMMDD HH:MM:SS(4 位年份、GMT)重新格式化(lib/altsvc.c)。

写回时附加的头部注释

libcurl 落盘保存时,会先写入两行说明性注释(lib/altsvc.c):

# Your alt-svc cache. https://curl.se/docs/alt-svc.html # This file was generated by libcurl! Edit at your own risk.

保存过程采用临时文件 + 原子重命名策略(Curl_fopen写临时文件、Curl_rename替换目标文件),避免中途崩溃导致缓存文件损坏(lib/altsvc.c)。

libcurl API 编程实践

除了命令行,开发者可以直接在 libcurl 编程中使用两个专属选项(定义于 include/curl/curl.h):

  • CURLOPT_ALTSVC(选项号 287):字符串参数,指定缓存文件名;空字符串表示仅在内存中维护;
  • CURLOPT_ALTSVC_CTRL(选项号 286):长整型参数,位掩码,控制允许使用的替代协议版本与文件行为。

控制位掩码 CURLALTSVC_*

位定义见 include/curl/curl.h:

宏值含义
CURLALTSVC_H11<<3允许使用 h1 替代协议
CURLALTSVC_H21<<4允许使用 h2 替代协议
CURLALTSVC_H31<<5允许使用 h3 替代协议
CURLALTSVC_READONLYFILE1<<2缓存文件只读,不写回磁盘

其中READONLYFILE的语义可以从源码确认:当该位被置位(或未指定保存文件名)时,Curl_altsvc_save直接返回、不做任何磁盘写入(lib/altsvc.c)。此外,Curl_altsvc_ctrl要求掩码非零,否则返回CURLE_BAD_FUNCTION_ARGUMENT(lib/altsvc.c)。

最小可运行示例

仓库内置了完整的 API 示例 docs/examples/altsvc.c,核心逻辑如下:

#include <curl/curl.h> CURL *curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* 将替代端点缓存到该文件 */ curl_easy_setopt(curl, CURLOPT_ALTSVC, "altsvc.txt"); /* 限定允许使用的替代协议版本 */ curl_easy_setopt(curl, CURLOPT_ALTSVC_CTRL, (long) CURLALTSVC_H1|CURLALTSVC_H2|CURLALTSVC_H3); CURLcode res = curl_easy_perform(curl); if(res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); }

缓存条目的生命周期:解析、匹配与过期

理解缓存文件格式后,再看一看条目在内存中的完整生命周期,这有助于判断手动编辑缓存文件时的正确姿势。

响应头解析:Curl_altsvc_parse逐项解析Alt-Svc:响应头值(lib/altsvc.c)。其中有两个值得注意的细节:

  • 响应头值中的clear是一个"魔法关键字":遇到它时,curl 会清空该源 origin 对应的全部缓存条目(altsvc_flush,见 lib/altsvc.c);
  • 每条替代项支持两个可选参数:ma(max-age,以秒为单位,默认 24 小时,即 86400 秒)与persist(值为 1 时置位)。过期时间expires = maxage + 当前时间(lib/altsvc.c),而不是直接采用服务端给定的绝对时间。

查询匹配:Curl_altsvc_lookup遍历缓存链表(lib/altsvc.c),匹配条件为:源 ALPN id、源主机(忽略末尾点号、大小写不敏感)、源端口三者一致,且目标 ALPN id 在CURLALTSVC_CTRL传入的版本位掩码内;同时,已过期条目会在遍历时被即时删除,保证缓存不残留僵尸记录。

字段含义对齐:缓存文件第 8 字段persist与响应头中的persist参数相对应——当服务端标记持久化时,缓存条目即使跨进程也会被保留;第 9 字段优先级目前仅存储、不参与调度(lib/altsvc.c),文档亦明确标注"当前未使用"。

已知限制与待办项

原文档在 TODO 一节列出了三个未完成事项,结合源码可进一步确认其现状:

  1. 多个响应头的clear覆盖问题:当一次响应中出现多个Alt-Svc:响应头、且其中一个值为clear时,规范要求该clear应覆盖(清除)其余全部条目,当前实现尚未对此场景做整体合并处理;
  2. Age:响应头的使用:按 RFC 7838 第 3.1 节,缓存年龄应综合考虑Age:响应头的取值,当前实现尚未纳入(lib/altsvc.c 的注释即对应此待办);
  3. CURLALTSVC_IMMEDIATELY支持:立即生效模式的位标志尚未实现,当前 include/curl/curl.h 中只有READONLYFILE、H1、H2、H3四个位。

这些限制意味着:在 HTTP/3 调研与客户端开发中,若遇到服务端下发多个 Alt-Svc 头或依赖Age:的场景,需要留意 curl 当前版本(本仓库内 vendored 的 curl)的行为边界。

在仓库中的位置与延伸阅读

本仓库以三方源码形式内置 curl(位于third_party/curl/,构建入口见 BUILD.gn),相关文档与代码清单如下:

  • 本文骨架文档:docs/ALTSVC.md
  • 核心实现:lib/altsvc.c、lib/altsvc.h
  • 命令行选项定义:docs/cmdline-opts/alt-svc.d
  • 编程示例:docs/examples/altsvc.c
  • 公共头文件常量:include/curl/curl.h
  • HTTP/3 下的典型用法:docs/HTTP3.md

若要进一步验证缓存文件的读写行为,可重点阅读altsvc_add(加载行)、altsvc_out(写出行)与Curl_altsvc_parse(响应头解析)三处函数,它们共同构成了 Alt-Svc 特性在磁盘与协议两侧的完整闭环。

  • 人工智能
  • AI Agent
  • 多模态
  • 语音
  • AI 应用

【免费下载链接】ten-framework

Open-source framework for conversational voice AI agents

项目地址:https://gitcode.com/TEN-framework/ten-framework
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询