題幹與適用場景
這道後端題考察 API 契約與故障邊界。重點不是把所有例外包成一個 JSON,而是讓客戶端能根據穩定的類型與狀態採取行動,同時讓日誌、追蹤、權限與使用者文案保持分層。
面試官考察什麼
- 是否理解
application/problem+json與 HTTP 狀態碼的關係。 - 能否區分驗證失敗、認證授權、資源衝突、限流、暫時不可用與未知錯誤。
- 能否設計欄位級錯誤、可追蹤實例與安全的擴充成員。
- 能否避免洩露堆疊、內部 ID、個人資訊與不可信的原始例外。
回答前需要釐清的問題
先確認客戶端需要機器決策還是僅展示訊息;是否有多語言、批次校驗與非同步任務;錯誤類型是否由跨服務共享;哪些狀態可重試;以及閘道、服務與客戶端各自負責記錄什麼、展示什麼與生成請求追蹤 ID。
30 秒回答框架
我會使用 application/problem+json,以 type、title、status、detail 與 instance 作為穩定骨架,再用受控擴充表達錯誤碼、欄位路徑、重試時間與文件版本。HTTP 狀態表示通用語意,type 表示可程式化分類;服務端日誌保存內部原因,回應只返回安全、可行動的資訊。
分步驟深入解答
1. 先建立狀態碼與類型邊界
400 表示請求無法按語法或通用規則處理,401 表示需要認證,403 表示已識別但不允許,404 表示資源不存在,409 表示目前狀態衝突,429 表示超出限流,5xx 表示服務端或依賴暫時失敗。type 應是穩定、可文件化的 URI;不要讓客戶端只解析易變的 title 或 detail。
2. 設計 Problem Details 欄位
type 用於程式分類,title 是穩定的人類摘要,status 複製回應狀態,detail 解釋目前請求,instance 關聯這一次具體發生。擴充成員可包含 code、欄位路徑、參數名、重試時間或支援文件版本,但應限制詞彙與長度。批次校驗可返回錯誤陣列,每項都指向輸入位置。
3. 處理驗證、衝突與重試
驗證失敗應讓客戶端知道如何修正欄位,不應要求重試;衝突需要重新讀取或改變業務動作;429 或依賴暫時不可用可提供 Retry-After,但客戶端仍要遵守退避與上限。把可重試與不可重試作為明確契約,不要因為所有回應都是 200 就讓客戶端猜測。
4. 保護安全與隱私邊界
回應不應包含堆疊、SQL、金鑰、內部主機名、租戶越權資訊或完整個人資料。detail 只說明可行動的事實,instance 使用不可預測或受控的引用;內部日誌透過請求 ID 關聯原始例外。認證失敗要避免透過文案洩露帳戶存在性,欄位錯誤也要按權限過濾。
5. 保持跨服務與版本演進
把共享 type、狀態與擴充寫入版本化文件與契約測試,閘道不要擅自改寫服務語意。新增欄位應向後相容,廢棄類型要提供遷移期;客戶端遇到未知 type 應回退到 status 與安全 detail。透過錯誤類型分布、重試成功率、欄位錯誤熱點與請求 ID 追蹤品質。
高品質示範回答
我會把所有錯誤回應宣告為 application/problem+json,使用穩定的 type URI、title、status、detail 與 instance。400/401/403/404/409/429 與 5xx 按通用 HTTP 語意區分,驗證錯誤增加欄位路徑與安全 code,429 或暫時依賴故障可帶 Retry-After。客戶端按 type 決定修正、重新讀取、退避或聯絡支援,不解析易變 detail。服務端日誌保留堆疊、依賴狀態與請求 ID,回應絕不洩露 SQL、金鑰、租戶資訊或個人資料。共享類型和擴充做版本化與契約測試,未知 type 回退到 status;上線後監控錯誤類型、重試結果與欄位熱點。
常見錯誤
- 所有錯誤都返回 200 和一段文字,讓客戶端無法做機器決策。
- 讓客戶端依賴 title 或 detail 的字面文案,改一個翻譯就破壞邏輯。
- 把驗證失敗、衝突、限流與暫時不可用都標成 500。
- 在 detail 中返回堆疊、SQL、內部主機名或完整使用者資料。
- 用內部例外類名直接作公開 type,導致實作細節變成長期契約。
- 沒有未知 type 的回退策略與跨服務契約測試。
追問與應對
type 一定要是真實可訪問的 URL 嗎?
它應是穩定的 URI,通常可指向解釋該問題的文件,但客戶端不應依賴每次都能訪問。重點是標識語意、版本與遷移說明,而不是把錯誤處理變成一次額外網路請求。
detail 需要做國際化嗎?
機器欄位和 type 保持穩定,使用者可見文案由客戶端按語言與場景渲染。若服務端必須返回 detail,應提供安全模板與語言協商,不能把未翻譯的內部例外直接暴露。
閘道應該統一改寫錯誤嗎?
閘道可以補充請求 ID、逾時與協定層錯誤,但不應抹平服務的業務 type。改寫必須有版本化規則與觀測,否則客戶端看到的語意與真正失敗原因會脫節。
如何處理批次請求中部分成功?
定義明確的批次結果模型,逐項返回狀態、輸入位置與可重試性,並說明整體 HTTP 狀態代表什麼。部分成功不能靠一個模糊 detail 表達,也不能讓客戶端重複提交已成功項目。