後端面試:如何用 HTTP Prefer 協商回應,又不破壞冪等與快取?
題干與適用場景
批次寫入 API 的客戶端有不同頻寬與延遲目標:有的只需要狀態,有的需要完整資源表示,還有的願意等待幾秒以避免輪詢。請依 RFC 7240 設計 Prefer 請求標頭、Preference-Applied 回應標頭、錯誤處理、快取與降級。
Prefer 是請求偏好,不是伺服器必須滿足的指令。本題考察協定語意與 API 契約設計,不代表所有代理都會完整保留偏好標頭。
面試官考察點
- 能否區分客戶端偏好與伺服器承諾,並在回應中明確實際採用的偏好。
- 能否正確使用
return=minimal、return=representation、respond-async與wait。 - 能否處理 Prefer 導致的回應差異、
Vary、快取鍵與代理相容性。 - 能否讓重試、冪等鍵與非同步任務狀態在偏好未滿足時仍然安全。
回答前需要釐清的問題
- API 是安全讀取還是有副作用的寫入,是否已有冪等鍵?
- 完整表示的大小、生成成本與最大等待時間是多少?
- 客戶端能否接受 202 與狀態資源,是否支援輪詢或回呼?
- 中間代理是否會轉送 Prefer,快取是否可能共享?
- 偏好未滿足時,客戶端需要哪些穩定欄位?
30 秒回答框架
「Prefer 表達客戶端偏好,伺服器可以忽略或只部分採用;採用後用 Preference-Applied 明確回應。寫入請求可用 return=minimal 減少回應,除錯或同步場景可用 return=representation,長任務可用 respond-async 與有上限的 wait。我會把冪等鍵、202 狀態資源、快取 Vary 與客戶端降級一起設計:沒有 Preference-Applied 就按預設回應解析,不能假設偏好一定生效。」
分步驟深入解答
1. 把偏好當作可忽略協商
RFC 7240 定義 Prefer 請求標頭及 Preference-Applied 回應標頭。伺服器可選擇不套用偏好;因此回應體與狀態碼必須有穩定的預設契約,客戶端不能只因送出 Prefer 就跳過解析。
2. 選擇合適的偏好令牌
return=minimal 適合只需要成功確認的寫入;return=representation 適合希望取得更新後資源的同步呼叫。respond-async 表示客戶端接受非同步處理,wait=n 表示願意等待的時間上限。把這些令牌當預算提示,不要把 wait 當 SLA 保證。
3. 設計回應確認
採用偏好時回傳 Preference-Applied;未採用時可以省略該標頭,並按預設契約回應。非同步場景回傳 202、任務狀態 URI 與可追蹤 ID;同步超過等待預算後也應保持可查詢的任務狀態,而不是讓客戶端重複提交副作用。
POST /v1/imports HTTP/1.1
Prefer: return=minimal, respond-async, wait=3
Idempotency-Key: imp-8f2
HTTP/1.1 202 Accepted
Preference-Applied: respond-async
Location: https://api.example/imports/jobs/42
Cache-Control: no-store4. 處理快取變體
如果同一安全 GET 的表示會隨 Prefer 改變,回應需要正確宣告 Vary,或避免把偏好相關回應放入共享快取。寫入回應通常使用 no-store;非同步狀態資源應定義短快取、ETag 或明確輪詢條件,避免中介層回傳過期進度。
5. 保證冪等與降級
Prefer 不改變操作語意,重試仍需遵守冪等性。寫入介面使用冪等鍵或業務去重鍵;客戶端看到 202、逾時或沒有 Preference-Applied 時,應查詢任務或按預設回應處理,不能因偏好未確認就再次建立資源。
6. 設定觀測與界限
記錄偏好令牌、是否採用、等待時長、回應大小、202 比例與代理鏈路。限制允許的 wait 範圍,拒絕過大值或將其截斷;對未知偏好採用忽略並記錄,避免把任意客戶端字串變成昂貴的執行路徑。
高品質示範回答
「我會把 Prefer 當作可忽略的客戶端偏好,而不是承諾。寫入介面預設回傳穩定狀態;客戶端需要輕量回應時送出 return=minimal,需要資源表示時送出 return=representation,長任務使用 respond-async 與受限的 wait。伺服器實際採用才回傳 Preference-Applied;非同步處理回傳 202、Location 與任務 ID。寫入使用冪等鍵,回應按安全性設定 no-store,表示差異透過 Vary 或快取隔離處理。客戶端沒有 Preference-Applied 時走預設解析並查詢任務,絕不因偏好不確定而重複副作用。」
常見錯誤
- 把 Prefer 當強制指令 → 伺服器或代理可忽略它 → 用預設契約和 Preference-Applied 確認。
- 把 wait 當完成保證 → 長任務仍可能逾時 → 限制預算並提供 202 狀態資源。
- 非同步逾時後再次提交 → 產生重複副作用 → 使用冪等鍵並先查詢任務。
- 忽略回應變體快取 → 客戶端拿到不匹配的表示 → 設定 Vary 或隔離快取。
- 接受任意未知偏好並執行昂貴邏輯 → 攻擊者可放大資源消耗 → 未知偏好忽略、記錄並限制令牌。
追問及應對
沒有 Preference-Applied 是否代表請求失敗?
不代表。伺服器可能選擇預設行為或忽略偏好;客戶端應依穩定預設契約解析回應,只有協定或業務狀態明確失敗時才判定失敗。
return=minimal 能否用於所有寫入操作?
不能。它只表達客戶端不需要完整表示;若客戶端必須取得伺服器產生的版本號、校驗摘要或後續連結,就應請求表示或查詢資源,不能從空回應推斷欄位。
wait=5 是否會讓伺服器阻塞五秒?
不會構成硬性保證。它表示客戶端願意等待的偏好上限,伺服器可更早回應、忽略或轉為非同步;伺服器仍需執行自身逾時、並發與資源預算。