題幹與適用場景
一個 API 閘道要求用戶端改用 HTTP/3,但仍收到 HTTP/1.1 請求。請說明何時回傳 426、回應應包含什麼、用戶端如何恢復,以及為什麼不能把所有協定不匹配都回傳 426。
HTTP 426 表示伺服器拒絕使用目前協定處理請求,但用戶端升級到另一個協定後可能成功。RFC 9110 的例子是在回應中攜帶 Upgrade: HTTP/3.0。它表達可行動的協定升級要求,不是普通參數錯誤、TLS 交握失敗或伺服器完全不支援該資源。
面試官考察點
面試官會觀察你是否準確引用 426 語義,能否區分 Upgrade 標頭與 TLS、HTTP 版本協商,是否考慮快取、代理、冪等重試、觀測和用戶端相容性,並能解釋 400、421、505 等相近狀態碼的邊界。
回答前需要釐清的問題
先確認升級的是 HTTP 協定、TLS 連線還是應用層版本;確認用戶端是否能建立目標協定、請求方法是否可安全重試、閘道前是否有代理,以及升級後原請求是否需要重新送出。再確認是否有部分租戶仍必須使用舊協定,以及是否需要灰度和回滾。
30 秒回答框架
「只有伺服器仍願意在目標協定上處理同一資源,而目前協定阻止處理時,我才回傳 426,並在回應中給出明確的 Upgrade 值和可讀說明。用戶端應重新建立目標協定連線,再按方法語義決定是否重試;不能假設請求已執行或可以盲目重放。若伺服器完全不支援該版本,使用 505;若是錯誤的連線路由,考慮 421;普通請求格式問題則用 400。閘道還要記錄協定、代理鏈和升級結果,避免快取或重試放大流量。」
分步驟深入解答
第一步:確認 426 觸發條件
426 的關鍵是「目前協定不適用,但升級後可能成功」。伺服器必須知道目標協定和升級路徑,不能把未知用戶端、缺少參數或應用版本落後都歸入 426。
第二步:建立可行動的回應
回應應包含 Upgrade 標頭,值列出伺服器接受的目標協定,例如 HTTP/3.0,並提供簡短正文或機器可讀錯誤碼。不要只回傳模糊的「please upgrade」,也不要把敏感內部拓撲寫進正文。
HTTP/1.1 426 Upgrade Required
Upgrade: HTTP/3.0
Content-Type: application/problem+json
{"type":"https://example.test/problems/upgrade-required","title":"Upgrade required"}第三步:區分連線升級與應用重試
用戶端需要先建立目標協定連線,再決定是否重新送出原請求。連線升級是傳輸層或協定層動作,不能靠修改一個應用欄位完成。對 POST 等非冪等請求,用戶端必須依照冪等鍵、伺服器執行紀錄和 API 契約決定是否重試。
第四步:處理 TLS 情境
HTTP 426 不能取代 TLS 交握失敗或憑證錯誤。RFC 2817 討論過在 HTTP/1.1 中升級到 TLS 的路徑,但現代部署通常在連線建立階段協商 TLS 和 HTTP 版本。若請求根本沒有到達可產生 HTTP 回應的階段,應記錄交握錯誤,而不是偽造 426。
第五步:劃清相近狀態碼
400 表示請求語法或內容無效;421 表示請求被送到無法產生回應的伺服器;505 表示伺服器不支援請求使用的 HTTP 版本。426 強調「升級後可能繼續服務」,因此不能把完全不支援目標協定或資源不存在包裝成 426。
第六步:設計代理、快取與重試策略
代理可能終止連線並重新發起請求,用戶端也可能自動重試。回應應明確 Cache-Control 策略,避免舊協定錯誤被長期快取;閘道記錄原始協定、協商結果、代理鏈和重試次數。重試預算必須與速率限制及熔斷策略一致。
第七步:保護灰度與回滾
先對具備目標協定能力的用戶端灰度,觀察成功率、延遲、錯誤類型和重複寫入,再擴大範圍。保留舊協定入口直到遷移完成,並準備按用戶端、租戶或區域回滾。不要僅憑 426 數量判斷遷移成功,因為中間代理可能吞掉或改寫回應。
第八步:驗證用戶端恢復
測試 GET、冪等 PUT、非冪等 POST、長連線、代理轉發、快取命中、TLS 失敗、未知升級值和目標協定不可用。驗證用戶端是否重新連線、是否重複寫入、是否保留認證上下文,以及日誌和指標能否區分 426、421、505 與交握失敗。
高品質示範回答
我會先確認目前協定確實阻止伺服器處理請求,而目標協定可用且有明確升級路徑。此時回傳 426,帶 Upgrade: HTTP/3.0 和機器可讀錯誤資訊;正文不洩露內部細節。用戶端要重新建立 HTTP/3 連線,再按方法冪等性、冪等鍵和執行紀錄決定是否重試,不能假設原請求未執行。TLS 交握失敗應在連線層處理,完全不支援 HTTP 版本應使用 505,錯誤路由考慮 421,語法錯誤使用 400。遷移透過用戶端能力灰度,監控協定、代理鏈、重複寫入和成功率,設定快取與重試邊界,並保留舊協定回滾入口。最後覆蓋不同方法、代理、快取、長連線和目標協定不可用的測試。
常見錯誤
把 426 當成所有用戶端版本過舊的通用錯誤
426 針對協定升級,而且升級後伺服器可能繼續處理。應用版本過舊、缺少欄位或權限不足應使用各自的業務錯誤契約。
認為加上 Upgrade 標頭就完成升級
回應只是告訴用戶端下一步,用戶端仍需重新建立合適連線。伺服器和代理還必須真正支援目標協定及認證、路由、限流和觀測鏈路。
對非冪等請求自動重放
426 發生在請求處理邊界附近,用戶端不能憑狀態碼推斷寫入一定沒有發生。沒有冪等鍵或執行查詢能力時,自動重放 POST 可能產生重複副作用。
延伸追問與參考答案
426 與 505 的核心差異是什麼?
426 表示升級後可能成功,回應會指向目標協定;505 表示伺服器不支援請求使用的 HTTP 版本,通常沒有可用的升級承諾。
代理在邊緣終止 HTTP/3,源站還會回傳 426 嗎?
邊緣代理應在能力和路由邊界處理協商,並把必要上下文傳給源站。若源站看不到真實用戶端協定,不能僅憑連線欄位做錯誤判斷,應記錄代理協定和轉發語義。
426 回應可以快取嗎?
只有在明確知道快取鍵、用戶端能力和遷移策略時才考慮快取。預設應避免讓共享快取長期保存協定遷移錯誤,並用回應標頭表達短時策略。
POST 收到 426 後如何安全恢復?
使用冪等鍵、伺服器執行狀態查詢和用戶端重試預算。先建立目標協定連線,再確認原請求是否已執行;無法確認時向使用者報告待確認狀態,而不是盲目重放。
什麼時候應在連線層拒絕,而不是回傳 426?
當 TLS、ALPN 或底層協定協商在產生 HTTP 回應前失敗時,應在連線層關閉並記錄原因。426 只適用於伺服器能傳送 HTTP 回應、且升級建議可行動的情境。
如何證明協定遷移沒有傷害使用者?
按用戶端能力灰度,比較 426 後成功率、延遲、重複寫入、認證失敗、代理分布和回滾耗時。指標要能區分邊緣、源站和用戶端重試,不能只看 426 總量。