ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

curl `--time-cond` 条件请求指南:基于时间戳的增量下载与缓存验证

curl `--time-cond` 条件请求指南:基于时间戳的增量下载与缓存验证 curl--time-cond条件请求指南基于时间戳的增量下载与缓存验证【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl导读--time-cond短选项-z让 curl 在 HTTP 与 FTP 场景下按文件的最后修改时间发起条件请求实现只下载比指定时间更新或更旧的文件这一经典增量同步能力。本文以 time-cond.md 为骨架结合 tool_getparam.c 的参数解析实现、transfer.c 的条件判定逻辑以及 libcurl 的配套选项文档完整讲解时间表达式语法、/-/前缀语义、文件 mtime 回退机制并延伸介绍 libcurl API 层面的CURLOPT_TIMECONDITION/CURLOPT_TIMEVALUE与--etag-compare、--remote-time的配合使用。读完你将能写出可靠的缓存刷新、增量备份与未修改不下载脚本。一、选项概览与基本用法在 curl 命令行中--time-cond的完整定义位于 docs/cmdline-opts/time-cond.md属性值长选项--time-cond短选项-z参数time时间字符串或文件名适用协议HTTP、FTP类别http、ftp加入版本5.8Multisingle单 URL 场景该选项的核心语义请求一个比给定时间更晚修改的文件或者比给定时间更早修改的文件。默认情况下请求比指定时间更新的文件在时间表达式前加一个-前缀则反转为请求比指定时间更旧的文件。文档自带的三个示例见 time-cond.md# 请求在 2021-09-01 12:18:00 之后被修改过的文件默认 If-Modified-Since 语义 curl -z Wed 01 Sep 2021 12:18:00 $URL # 请求在 2021-09-01 12:18:00 之前被修改过的文件加 - 前缀 curl -z -Wed 01 Sep 2021 12:18:00 $URL # 以 file 作为时间来源读取该文件的 mtime 作为比较基准 curl -z file $URL二、时间表达式字符串解析与文件 mtime 回退--time-cond的参数time支持两种形态日期字符串可以是各种常见的日期格式最终由curl_getdate(3)解析为 Unix 时间戳自 1970-01-01 00:00:00 UTC 起的秒数。完整语法参见 docs/libcurl/curl_getdate.md。文件名如果参数不匹配任何内置日期格式则被当作文件名处理curl 会尝试读取该文件的修改时间mtime作为比较基准——这是脚本中最常用的以上次下载的文件时间为准模式。从命令行解析的实现来看src/tool_getparam.c中的parse_time_cond()tool_getparam.c不仅处理了默认语义还支持三种显式前缀static ParameterError parse_time_cond(struct OperationConfig *config, const char *nextarg) { switch(*nextarg) { case : nextarg; FALLTHROUGH(); default: /* If-Modified-Since: (section 14.28 in RFC2068) */ config-timecond CURL_TIMECOND_IFMODSINCE; break; case -: /* If-Unmodified-Since: (section 14.24 in RFC2068) */ config-timecond CURL_TIMECOND_IFUNMODSINCE; nextarg; break; case : /* Last-Modified: (section 14.29 in RFC2068) */ config-timecond CURL_TIMECOND_LASTMOD; nextarg; break; } config-condtime (curl_off_t)curl_getdate(nextarg, NULL); ... }由此可以得到完整的语义映射前缀含义底层枚举对应 HTTP 语义无默认请求比指定时间更新的文件CURL_TIMECOND_IFMODSINCEIf-Modified-SinceRFC 2068 §14.28同上显式写出的更新于CURL_TIMECOND_IFMODSINCEIf-Modified-Since-请求比指定时间更旧的文件CURL_TIMECOND_IFUNMODSINCEIf-Unmodified-SinceRFC 2068 §14.24请求文件的修改时间恰好等于给定时间CURL_TIMECOND_LASTMODLast-ModifiedRFC 2068 §14.29用于校验响应头2.1 curl_getdate 支持的日期格式curl_getdate的解析规则docs/libcurl/curl_getdate.md相当宽松日期字符串由空格分隔的若干条目组成条目顺序无关紧要支持日历日期月份名只接受三个字母的英文缩写数字可带前导零年份可用 2 位或 4 位。例如06 Nov 1994、06-Nov-94、Nov-94 6。两位年份的推断规则大于 70 视为1900 年其余视为2000 年。当日时间必须用 6 位数字加两个冒号即HH:MM:SS省略时默认00:00:00。例如18:19:21。时区支持少量缩写如MST更通用的是相对 UTC 的偏移量如-1200、0100。星期几可写全称Sunday、Monday...或前三个字母缩写通常不影响解析结果。纯数字形如YYYYMMDD的十进制数会被解读为年/月/日例如20040912表示 2004-09-12。curl_getdate遵循的标准包括 RFC 822及其更新 RFC 1123、RFC 850已被 RFC 1036 取代以及 ANSI C 的asctime()格式——这正是 RFC 7231 允许 HTTP 应用使用的日期格式集合。2.2 解析失败与边界解析失败时curl_getdate返回-1。具体边界docs/libcurl/curl_getdate.md有符号 32 位time_t年份大于 2037 或小于 1903 返回-1无符号 32 位time_t年份大于 2106 或小于 1970 返回-164 位time_t年份小于 1583 返回-1格里高利历 1582 年才引入此前无真实日期。该函数对合法日期正常解析但并不总能检测并拒绝错误日期例如 2 月 30 日文档原文声明。时间来源为不存在文件时curl 会输出一条警告然后不附带任何时间条件继续传输即退化为普通下载。这在 time-cond.md 中有明确说明也是脚本化时需要注意的静默降级行为。三、底层原理条件如何在请求与响应中生效3.1 条件判定函数libcurl 内部通过 transfer.c 中的Curl_meets_timecondition()判断远程文件时间是否满足条件bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc) { if((timeofdoc 0) || (data-set.timevalue 0)) return TRUE; switch(data-set.timecondition) { case CURL_TIMECOND_IFMODSINCE: default: if(timeofdoc >CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMECONDITION, long cond);枚举值定义在 include/curl/curl.h#define CURL_TIMECOND_IFMODSINCE 1L #define CURL_TIMECOND_IFUNMODSINCE 2L #define CURL_TIMECOND_LASTMOD 3L默认值为CURL_TIMECOND_NONE (0)即不启用时间条件。注意CURL_TIMECOND_*枚举在 8.13.0 起成为long类型此前版本传入curl_easy_setopt时需要显式long转换见 CURLOPT_TIMECONDITION.md 的 HISTORY 一节。4.2 CURLOPT_TIMEVALUE提供基准时间接口原型docs/libcurl/opts/CURLOPT_TIMEVALUE.mdCURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEVALUE, long val);val是自 1970-01-01 起的秒数Unix epoch。文档特别提醒在long为 32 位的系统如 Windows上该选项无法表示 2038 年之后的日期此时应改用CURLOPT_TIMEVALUE_LARGE见 docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.md。官方示例两个文档共用int main(void) { CURL *curl curl_easy_init(); if(curl) { CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, https://example.com); /* January 1, 2020 is 1577833200 */ curl_easy_setopt(curl, CURLOPT_TIMEVALUE, 1577833200L); /* If-Modified-Since the above time stamp */ curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE); /* Perform the request */ result curl_easy_perform(curl); curl_easy_cleanup(curl); } }这个 C 代码片段与命令行curl -z Wed 01 Sep 2021 12:18:00 $URL完全等价TIMEVALUE对应time解析后的时间戳TIMECONDITION对应默认的 IFMODSINCE 语义。命令行工具正是在 tool_getparam.c 中通过curl_getdate()把日期字符串换算成config-condtime再在后续 setopt 阶段写入这两个 option。五、实战场景与配套选项5.1 增量下载以上次文件时间为基准利用参数是文件名时取其 mtime的机制可以轻松实现只下载新内容# 首次下载file 不存在时会警告并降级为无条件下载 curl -z last.txt -o data.txt https://example.com/data.txt # 手动把本次下载的时间戳记录下来供下次比较 curl -z last.txt -o data.txt https://example.com/data.txt \ touch -r data.txt last.txt # 若文件未修改服务器返回 304curl 输出 0 字节成功结果结合--remote-timeremote-time.md可以更进一步该选项让 curl 解析远程文件的修改时间并把它赋给本地输出文件从而让本地文件时间始终反映远端状态# 下载后把本地文件时间设为远程文件的修改时间 curl -z last.txt --remote-time -o data.txt https://example.com/data.txt5.2 ETag 方案与 --etag-compare 的取舍基于时间戳的条件请求存在天然局限——时间粒度只能到秒且远程文件 mtime 不一定可靠。HTTP 生态更精确的做法是 ETag实体标签。curl 提供了 --etag-compare 与配套的--etag-save前者从文件中读取 ETag并通过自定义If-None-Match头发起条件请求后者把响应的 ETag 保存到文件。# 首次请求保存 ETag curl --etag-save etag.txt -o data.txt https://example.com/data.txt # 后续请求携带 If-None-Match内容未变则返回 304 curl --etag-compare etag.txt -o data.txt https://example.com/data.txt两者的差异值得注意--time-cond基于Last-Modified/If-Modified-Since时间比较适用 HTTP 与 FTP--etag-compare基于ETag/If-None-Match强校验仅适用 HTTP且要求 etag 文件只有单行内容--etag-compare只能配合单个 URL 使用时间条件在远程 mtime 未知时静默失效而 ETag 方案对内容变化的检测更可靠能捕获内容变了但时间没变的情况。两者可以互为补充时间方案简单、跨协议ETag 方案精确、仅限 HTTP。5.3 测试用例佐证仓库的测试数据可以印证该功能的实际行为tests/data/test1511以及tests/libtest/lib1511.c对应条件请求的 libtest 用例tests/data/test1593test1596与tests/libtest/lib1593.c覆盖时间条件相关场景。读者可以结合 tests/data 目录下的测试定义观察 304 响应、0 字节传输与CURLINFO_CONDITION_UNMET的配合关系。六、小结与注意事项--time-cond是 curl 中最实用的缓存/增量同步工具之一使用时注意以下几点默认语义不带前缀请求更新于指定时间的文件If-Modified-Since-前缀反转语义前缀对应Last-Modified。参数两种形态合法日期字符串走curl_getdate解析否则按文件名取其 mtime。静默降级参数文件不存在时仅输出警告并转为无条件传输远程文件 mtime 未知时条件不生效。零字节成功条件不满足时得到的是 0 字节成功传输脚本中可用CURLINFO_CONDITION_UNMETlibcurl API区分未修改与空内容。时间戳范围命令行内部使用curl_off_t保存时间API 层面CURLOPT_TIMEVALUE在 32 位long平台有 2038 年限制需用CURLOPT_TIMEVALUE_LARGE规避。Y2038 与解析边界curl_getdate对 32 位time_t系统存在 2037/2106 年边界超出范围返回 -1。相关文档索引time-cond.md、curl_getdate.md、CURLOPT_TIMECONDITION.md、CURLOPT_TIMEVALUE.md、CURLOPT_TIMEVALUE_LARGE.md、CURLINFO_CONDITION_UNMET.md、etag-compare.md、remote-time.md。【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表