踩坑合集!2025 年常見的 16 個 REST 狀態碼錯誤,你中了幾個?
狀態碼不是“隨便寫個 200 就完事”的擺設
構建一個高可用、高可維護的 REST API,從來不只是把功能“跑通”那么簡單。對于返回給客戶端的 HTTP 狀態碼,很多開發者(包括我自己)在初期都掉進了“200 一把梭”的誤區。一開始我也這么做:用戶點擊“生成報告”,這個操作比較耗時,我直接返回一個 200 OK + “稍等,馬上好”作為反饋,自以為穩了,結果被新入職的小伙伴一句“你這不是應該用 202 Accepted 嗎?”當場點醒。
為了搞清楚到底有哪些狀態碼使用誤區,我翻了 RFC 7231、研究了一些最佳實踐、審視了項目代碼,也總結出了一份“踩坑黑榜”——REST 接口中最容易犯錯的 16 個 HTTP 狀態碼使用場景。不僅如此,我還基于 Spring Boot 3.4 的架構給出優化實踐方案,讓我們少走彎路。
無論你是后端開發、架構師還是 API 網關工程師,這篇文章都能幫你全面排查狀態碼使用是否規范。
以下為本次匯總的 16 個最容易犯錯的狀態碼場景,每個錯誤都附帶優化實踐和建議:
1?? 異步任務卻返回了 200 OK?
? 錯誤示范:
POST /generate-report
HTTP/1.1 200 OK
{"message": "報告正在生成中"}
? 正確做法:使用 202 Accepted 說明任務已接收但尚未完成,并返回任務狀態查詢鏈接:
POST /reports
HTTP/1.1 202 Accepted
Location: /reports/12345
Content-Type: application/json
{"status": "Processing", "estimated_completion": "30 seconds"}
查詢狀態時:
GET /reports/12345
HTTP/1.1 202 Accepted
{"status": "Processing", "progress": "70%"}
2?? 請求失敗卻返回了 200?
? 錯誤示范:
HTTP/1.1 200 OK
{"status": "error", "message": "找不到用戶"}
? 正確做法:使用具體錯誤碼,如:
- 400 Bad Request:輸入參數有誤
- 401 Unauthorized:未認證
- 404 Not Found:資源不存在
3?? 使用 302 Found 重定向 POST?
? 錯誤示范:POST 提交后返回 302,可能導致表單重復提交。
? 正確做法:使用 303 See Other 告知客戶端重定向到 GET 頁面。
4?? 使用 404 來掩蓋方法不支持?
? 錯誤示范:
DELETE /users/123
HTTP/1.1 404 Not Found
? 正確做法:使用 405 Method Not Allowed,并提供 Allow 頭:
HTTP/1.1 405 Method Not Allowed
Allow: GET, POST
5?? 所有錯誤一律 500?
? 錯誤示范:
GET /search?query=
HTTP/1.1 500 Internal Server Error
? 正確做法:針對客戶端錯誤,使用 400 Bad Request 更明確。
6?? 不限流也不返回 429?
? 正確做法:對接口做限流,達到閾值返回 429 Too Many Requests:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
7?? 數據校驗錯誤卻只返回 400?
? 錯誤示范:郵箱格式錯誤返回 400。
? 正確做法:使用 422 Unprocessable Entity 表示參數格式合法但值無效。
8?? 忽略緩存頭?
? 正確做法:結合 ETag、If-Modified-Since 使用 304 Not Modified 節省帶寬。
9?? 刪除失敗還說成功?
? 錯誤示范:刪除不存在用戶返回 200。
? 正確做法:
- 成功刪除返回 204 No Content
- 對象不存在返回 404 Not Found
?? 數據庫連接失敗也用 500?
? 正確做法:數據庫不可用返回 503 Service Unavailable,并設置 Retry-After 頭。
1??1?? 創建成功卻不告訴位置?
? 正確做法:使用 201 Created 同時提供 Location:
HTTP/1.1 201 Created
Location: /users/123
1??2?? API 被廢棄卻返回 500?
? 正確做法:使用 410 Gone 明確提示接口已廢棄。
1??3?? 未登錄卻說禁止訪問?
? 錯誤示范:
HTTP/1.1 403 Forbidden
? 正確做法:使用 401 Unauthorized,提示需要登錄認證。
1??4?? 客戶端上傳的格式不對卻沒提示?
? 正確做法:返回 415 Unsupported Media Type,并告知支持的格式類型。
1??5?? CORS 錯誤混淆狀態碼?
? 正確做法:確保返回正確的跨域頭部,并返回具體錯誤而非模糊的 500。
1??6?? 資源沖突也返回成功?
? 正確做法:重復創建資源時使用 409 Conflict 提示沖突。
實戰優化建議(Spring Boot 3.4 示例)
控制器異常處理建議:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ApiError> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ApiError("資源不存在", 404));
}
@ExceptionHandler(InvalidInputException.class)
public ResponseEntity<ApiError> handleInvalidInput(InvalidInputException ex) {
return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY)
.body(new ApiError("參數校驗失敗", 422));
}
@ExceptionHandler(RateLimitExceededException.class)
public ResponseEntity<ApiError> handleRateLimit() {
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.RETRY_AFTER, "60");
return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
.headers(headers)
.body(new ApiError("請求過多,請稍后重試", 429));
}
}
返回體結構建議:
public class ApiError {
private String message;
private int code;
public ApiError(String message, int code) {
this.message = message;
this.code = code;
}
// Getter / Setter 省略
}
總結
一個優秀的 RESTful API,不僅要返回正確的業務數據,還要講究語義清晰、語義準確。狀態碼,是 API 與客戶端交流的第一層語言。
使用錯誤的狀態碼,輕則讓前端工程師一臉懵逼,重則引發安全隱患、重試失敗、用戶體驗差……它既是技術細節,也代表團隊的工程素養。
如果你在維護系統 API,不妨對照這 16 個坑,來一次自查:
- 我們是不是總是用 200 ?
- 遇到校驗失敗是不是忘了用 422?
- 緩存返回是不是該用 304?
- 報錯是不是一律甩個 500?