
libcurl 條件請求判定CURLINFO_CONDITION_UNMET 使用指南【免費下載鏈接】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本篇技術(shù)指南圍繞 libcurl 提供的CURLINFO_CONDITION_UNMET信息選項展開講解如何通過curl_easy_getinfo判斷一次基于時間條件的 HTTP/FTP/FILE 傳輸是否因條件未滿足而被跳過例如服務器返回 304 或資源未按預期更新并結(jié)合當前倉庫源碼剖析其底層實現(xiàn)與判定邏輯。讀完本文你將掌握條件請求的完整搭配方案、返回值語義與實戰(zhàn)代碼寫法。什么是 CURLINFO_CONDITION_UNMETCURLINFO_CONDITION_UNMET是 libcurl 的一個信息info選項用于在傳輸結(jié)束后查詢上一次請求設(shè)置的時間條件time condition是否未被滿足。它屬于long類型的 getinfo 選項枚舉值為CURLINFO_LONG 35定義見 include/curl/curl.h自 curl 7.19.4 版本起加入僅適用于 HTTP 協(xié)議。典型場景當客戶端發(fā)送帶If-Modified-Since之類的條件請求服務器判定資源未更新于是不返回文檔正文。此時curl_easy_perform仍然返回CURLE_OK畢竟請求本身成功了但下載到的數(shù)據(jù)量為零。如果不對返回內(nèi)容加以區(qū)分很容易把資源未更新誤當成下載失敗或空文件。CURLINFO_CONDITION_UNMET正是用來消解這種歧義的它告訴你這次成功的空傳輸?shù)降资菞l件未滿足還是本來就該這樣。接口原型#include curl/curl.h CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONDITION_UNMET, long *unmet);傳入一個指向long的指針curl_easy_getinfo會把結(jié)果寫入該變量返回1之前請求中設(shè)置的條件未匹配。即你沒有拿到數(shù)據(jù)是因為資源不滿足你提出的時間條件返回0條件已滿足或從未設(shè)置條件傳輸正常進行。此外即使你沒有顯式設(shè)置時間條件只要服務器以HTTP 304狀態(tài)碼響應例如客戶端主動發(fā)送了自定義的If-Match-*請求頭該選項同樣會返回 1。底層實現(xiàn)flag 如何被置位getinfo 的讀取邏輯curl_easy_getinfo對CURLINFO_CONDITION_UNMET的處理位于 lib/getinfo.ccase CURLINFO_CONDITION_UNMET: if(data-info.httpcode 304) *param_longp 1L; else /* return if the condition prevented the document to get transferred */ *param_longp >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 >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); if(result CURLE_OK) { /* check the time condition */ long unmet; result curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, unmet); if(result CURLE_OK) { printf(The time condition was %sfulfilled\n, unmet ? NOT : ); } } curl_easy_cleanup(curl); } return 0; }代碼要點CURLOPT_TIMEVALUE設(shè)置對比用的時間戳Unix 秒數(shù)示例中1577833200即 2020-01-01 00:00:00 UTCCURLOPT_TIMECONDITION設(shè)置為CURL_TIMECOND_IFMODSINCE表示只在資源修改時間晚于該時間戳時才傳輸curl_easy_perform返回CURLE_OK后用CURLINFO_CONDITION_UNMET查詢條件是否未滿足unmet為 1 時打印NOT fulfilled說明傳輸被條件跳過為 0 時打印fulfilled說明資源滿足條件、數(shù)據(jù)已正常接收。配套選項與時間條件語義CURLINFO_CONDITION_UNMET本身只負責查詢結(jié)果條件請求的建立依賴兩個 setopt 選項詳見 docs/libcurl/opts/CURLOPT_TIMECONDITION.md選項作用取值CURLOPT_TIMEVALUE指定對比用時間戳Unix 時間秒long 類型CURLOPT_TIMECONDITION定義時間值的處理方式CURL_TIMECOND_IFMODSINCE/CURL_TIMECOND_IFUNMODSINCE默認CURL_TIMECOND_NONE即 0相關(guān)枚舉定義見 include/curl/curl.h#define CURL_TIMECOND_NONE 0L #define CURL_TIMECOND_IFMODSINCE 1L #define CURL_TIMECOND_IFUNMODSINCE 2L #define CURL_TIMECOND_LASTMOD 3LHTTP 請求頭由 lib/http.c 根據(jù)條件類型生成CURL_TIMECOND_IFMODSINCE→ 發(fā)送If-Modified-Since頭CURL_TIMECOND_IFUNMODSINCE→ 發(fā)送If-Unmodified-Since頭CURL_TIMECOND_LASTMOD→ 發(fā)送Last-Modified頭僅影響響應處理。若代碼中已通過CURLOPT_HTTPHEADER顯式設(shè)置了同名自定義頭libcurl 會優(yōu)先使用自定義頭、不再重復生成見 lib/http.c。HTTP 時間頭按 RFC 2616 要求使用 GMT 格式輸出。與命令行工具的對應關(guān)系curl 命令行工具通過-z, --time-cond暴露同一能力見 docs/cmdline-opts/time-cond.md# 請求在指定時間之后修改過的資源 curl -z Wed 01 Sep 2021 12:18:00 https://example.com/ # 從文件讀取時間戳 curl -z file $URL--time-cond與CURLOPT_TIMECONDITIONCURLOPT_TIMEVALUE一一對應CURLINFO_CONDITION_UNMET則對應命令行模式下curl -z時的內(nèi)部判定結(jié)果。若需在命令行場景獲得等價信息可結(jié)合-w %{http_code}觀察 304 狀態(tài)碼。返回值與錯誤處理curl_easy_getinfo返回CURLE_OK (0)表示查詢成功返回非零值表示出錯具體錯誤碼見 docs/libcurl/opts/libcurl-errors.md如傳入非法句柄或選項類型不匹配等。需要強調(diào)的是該選項是查詢型接口必須在curl_easy_perform完成之后調(diào)用在傳輸過程中調(diào)用拿到的可能是舊值。另外CURLINFO_CONDITION_UNMET是long類型選項傳入的必須是long *指針與CURLINFO_STRING/CURLINFO_OFF_T等類型不可混用否則會因類型掩碼不匹配導致CURLE_BAD_FUNCTION_ARGUMENT。實戰(zhàn)建議緩存場景結(jié)合CURLOPT_TIMECONDITION做增量下載或緩存校驗時務必在傳輸后檢查CURLINFO_CONDITION_UNMET避免把 304 空響應誤判為失敗。條件與 Range 互斥從 lib/http.c 的源碼可以看出設(shè)置了時間條件且同時設(shè)置 Range 時客戶端側(cè)不會模擬 304判定路徑會有差異兩者同時使用需謹慎。時間戳一致性CURLOPT_TIMEVALUE使用 Unix 秒數(shù)比較的是 UTC 時間構(gòu)造時間戳時注意時區(qū)換算防止因時區(qū)偏移導致條件判斷與預期不符。協(xié)議適用性官方文檔聲明該選項僅適用于 HTTP但倉庫源碼顯示 FTPMDTM 路徑與 FILEstat 路徑同樣會置位timecond標志因此在 FTP/FILE 場景下該選項同樣具備參考價值。【免費下載鏈接】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創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考