首頁 / 技術文章 / Markdown 內容協商怎麼驗收:用 curl 檢查 Accept、Vary 與 CDN 快取

技術文章

Markdown 內容協商怎麼驗收:用 curl 檢查 Accept、Vary 與 CDN 快取

同一網址依 Accept 回傳 HTML 或 Markdown,應同時驗證格式選擇、Content-Type、Vary 與快取隔離,才算完成實作驗收。單次取得 Markdown,只能證明該次轉換成功,無法證明瀏覽器與 agent 的後續請求都會收到正確版本。

發布 2026-10-15更新 2026-10-15topcc.me 編輯部

先分清楚:RFC 7763 註冊格式,RFC 9110 定義協商語意

RFC 7763 註冊了 text/markdown 媒體類型,文件類別是 Informational,並非 Standards Track。它讓回應能標示 Markdown 格式,並未替網站制定一套依請求選擇 HTML 或 Markdown 的協商機制。

內容協商的規範依據是 RFC 9110:HTTP Semantics,它已取代 RFC 7231。檢查時應把幾個角色分開:Accept 表達客戶端接受的媒體類型與偏好;Content-Type 描述實際回傳的內容;Vary 則告知快取,哪些請求欄位參與了表示法的選擇。

以下驗收建議以同一網址提供兩種表示法、允許共用快取,且預期依 Accept 選擇格式的網站為對象。產品是否能轉換、協商是否符合網站承諾、快取是否分開處理,是不同問題。尤其不能把選錯格式直接等同於快取串版:前者可能發生在選擇邏輯,後者才是回應被錯誤重用。

用成對請求檢查 Accept,並交換 q 值

先挑選預期能產生 Markdown 的公開頁面,固定網址與其他請求條件,只改變 Accept。下表中的 q 值是測試輸入;它們用來確認選擇邏輯是否讀取偏好權重,而非只搜尋標頭內有沒有 text/markdown。Accept 的品質權重與萬用媒體範圍屬於 RFC 9110 的內容協商語意;http.dev 的說明也整理了相關用法。

建議驗收矩陣:兩種表示法皆可提供時,檢查網站宣告的選擇政策
請求條件Accept 測試輸入應核對的結果
只接受 HTMLtext/htmlHTML 主體與 text/html 類型相符,並檢查 Vary 是否包含 Accept
只接受 Markdowntext/markdown成功轉換時,Markdown 主體與 text/markdown 類型相符,並檢查 Vary
偏好 Markdowntext/html;q=0.9, text/markdown;q=1若採客戶端偏好優先政策,應選 Markdown
偏好 HTMLtext/html;q=1, text/markdown;q=0.9在相同政策下應改選 HTML,不能只因出現 text/markdown 就轉換
接受任意類型*/*記錄預設選擇;此條件沒有單獨偏好 Markdown
沒有 Accept不傳送此標頭記錄預設選擇,與網站設定的政策比對

將下方的示意網址換成待驗證頁面後,可整段執行。每組輸出都保留回應標頭與主體,讓格式選擇、類型標示與 Vary 能一起核對。最後一組明確移除 Accept;不能把沒有手動加入標頭,直接當成沒有傳送標頭。

#!/usr/bin/env bash
set -eu

target_url='https://example.com/'

probe() {
  printf '\n===== %s =====\n' "$1"
  curl --silent --show-error --include \
    --header "$2" \
    "$target_url"
  printf '\n'
}

probe 'HTML only' 'Accept: text/html'
probe 'Markdown only' 'Accept: text/markdown'
probe 'Prefer Markdown' 'Accept: text/html;q=0.9, text/markdown;q=1'
probe 'Prefer HTML' 'Accept: text/html;q=1, text/markdown;q=0.9'
probe 'Wildcard' 'Accept: */*'
probe 'No Accept' 'Accept:'

交換 q 值後結果不變,是需要追查的訊號,不能單憑這點判定所有情境都違反規範。依 RFC 9110,主動式內容協商涉及可用表示法與伺服器的選擇,不能簡化成無條件採用最高 q 值。若兩種格式都可產生,而且網站承諾依客戶端偏好選擇,結果卻始終是 Markdown,就應檢查是否只做字串比對。這是具體的驗收失敗條件,也比把所有差異都歸咎於 CDN 更容易定位問題。

Content-Type 要對得上主體,HTML 回應也要檢查 Vary

執行矩陣後,先讀 Content-Type,再檢查主體。Cloudflare 的官方示範使用 content-type: text/markdown; charset=utf-8,並帶有 vary: accept。對採用這組輸出設定的網站,應確認實際內容確實是 Markdown,且編碼與宣告一致;若仍是 HTML,就不能只因請求指定 Markdown 而把測試標記為成功。

這裡的 charset=utf-8 是 Cloudflare 示範的具體值,不應據此推導成所有 Markdown 回應的完整參數規則。驗收應分開記錄媒體類型、字元編碼宣告與主體內容,避免把符合廠商範例和符合媒體類型規格混為一談。

接著逐筆看 Vary,包括只接受 HTML、偏好 HTML,以及預設回傳 HTML 的請求。RFC 9110 的 Vary 語意讓快取知道,重用回應時需要考慮哪些請求欄位。對依 Accept 分流且可共用快取的實作,建議將兩種回應都包含 Vary: Accept 列為驗收條件;只在 Markdown 回應加上它,仍留下 HTML 被不當重用的風險。

檢查重點是 Vary 是否涵蓋 Accept,而非整行是否只等於 Accept。網站也應確認 CDN 的實際快取設定配合這項選擇條件。標頭正確是重要證據,但無法單靠一行標頭證明整條傳遞路徑都正確處理了分版。

交錯請求同一網址,檢查 CDN 是否重用錯誤版本

快取驗收要觀察請求順序是否改變結果。以下先交錯要求 HTML 與 Markdown,再反過來要求;每次都使用完全相同的網址。不要為了辨認請求而加入不同查詢參數,否則可能避開原本要檢查的共用快取項目。

#!/usr/bin/env bash
set -eu

target_url='https://example.com/'

for accepted_type in \
  text/html text/markdown text/html text/markdown \
  text/markdown text/html text/markdown text/html
do
  printf '\n===== Accept: %s =====\n' "$accepted_type"
  curl --silent --show-error --include \
    --header "Accept: $accepted_type" \
    "$target_url"
  printf '\n'
done

每筆都對照實際主體、Content-Type、Vary,以及 CDN 供應商提供的快取命中標頭。若先要求 Markdown,接著只接受 HTML 的請求卻取得 Markdown,而且回應顯示快取命中,就形成值得追查的串版線索。反方向也要檢查:HTML 先進入快取後,是否讓原本可轉換的 Markdown 請求一直取得 HTML。

快取命中本身不是錯誤,命中後收到不符合選擇政策的表示法才是問題。如果每次都是未命中,這組結果只能支持當下的格式選擇,還沒有驗證快取重用是否安全。若沒有可辨識的命中資訊,應搭配 CDN 設定與請求紀錄追查,不能從主體相同就推定發生串版。短時間交錯測試也不能涵蓋所有節點與快取狀態。

Cloudflare 的轉換有條件,agent 必須讀取實際格式

依 Cloudflare 官方文件,Markdown for Agents 只適用於已啟用功能的 zone。客戶端在 Accept 中列出 text/markdown 後,邊緣會取回來源 HTML,再於可轉換時產生 Markdown。這項條件意味著:送出偏好不等於取得保證,沒有轉換時仍可能收到 HTML。

因此,agent 或 RAG 管線應依實際 Content-Type 選擇解析器。若服務允許 HTML 後備,就走 HTML 處理路徑;若管線只能接受 Markdown,應把格式不符列為明確失敗,避免將 HTML 直接交給 Markdown 解析器。對 */* 與沒有 Accept 的請求,網站可考慮以 HTML 為預設,但這是相容性政策建議,不應寫成一律必須回 HTML 的規範要求。

不能把 Accept 當成要求伺服器一定轉換格式的指令,也不能把 Vary 當成 CDN 已正確分版的證明。前者要用實際回應驗證,後者要用連續請求與快取資訊驗證。

上線判斷應落在正確性與需求,不能跳到 AI 曝光

對網站維運者,開啟轉換之後的工作是確認格式政策、快取行為與內容品質;對 agent 開發者,重點是可預期的解析與後備處理。自動轉換能否完整保留表格、導覽與互動內容,仍應挑選具代表性的頁面檢查,不能由協商標頭通過就推定內容品質也通過。

至於實際需求,較合理的投入順序是先確認請求紀錄中是否出現相關 Accept,再評估維護成本,可延伸參考如何從伺服器日誌確認 Markdown 的取用需求。目前可用證據不足以判定主流 AI 搜尋會因 Markdown 表示法而提高引用率;格式驗收與搜尋成效應分開評估,相關證據界線可參考AI 搜尋取得條件與引用選擇的差別。

驗收的終點應是:網站能說清楚不同 Accept 如何選擇格式,客戶端能辨認實際回應,共用快取也不會讓結果隨先前請求而錯置。若只能展示一次成功的 Markdown 回應,仍不足以支持上線判斷;應先補齊 HTML 路徑、q 值交換與快取命中後的驗證,再決定擴大提供的範圍。

常見問題

只在 Markdown 回應加入 Vary: Accept 就夠了嗎?

對同一網址依 Accept 分流且可共用快取的網站,建議 HTML 與 Markdown 回應都涵蓋 Vary: Accept,並確認 CDN 實際分版。否則 HTML 路徑仍可能留下不當重用的風險。其語意依據是 RFC 9110。

交換 q 值後仍收到 Markdown,就一定違反 HTTP 規範嗎?

不能只憑這項結果判定。應先確認兩種表示法是否都可提供,以及伺服器採用的選擇政策。若網站承諾依客戶端偏好選擇,交換權重後卻完全不變,就需要追查是否忽略 q 值。規範依據應使用 RFC 9110,不能把測試預期直接當成無條件的規範要求。

送出 Accept: text/markdown,為什麼仍收到 HTML?

Cloudflare 的轉換只適用於已啟用功能的 zone,而且以能夠轉換為前提。收到 HTML 時應先檢查功能設定與轉換條件,再排查快取;客戶端始終應依實際 Content-Type 處理內容。

Markdown 回應一定要與 text/markdown; charset=utf-8 完全相同嗎?

這是 Cloudflare 官方示範的值,可用來驗收採用相同設定的服務,但不能僅憑示範推導所有 Markdown 回應的參數要求。應分開確認媒體類型、編碼宣告與實際主體是否一致。

資料來源