面接問題:POST /users でユーザー作成後に返すステータスコードは200か201か
問題¶
POST /users should return 200 or 201 after creating user?
解答¶
201 Created が正しい。
解説¶
HTTP ステータスコードの意味¶
200 OK → リクエストが成功した(汎用)
主に GET・PUT・PATCH の成功レスポンス
201 Created → リクエストが成功し、新しいリソースが作成された
POST でリソースを新規作成した場合に使う
RFC 9110 (HTTP Semantics) より:
"The 201 (Created) status code indicates that the request has been
fulfilled and has resulted in one or more new resources being created."
なぜ 201 を使うべきか¶
1. セマンティクスの明確化
→ API の利用者が「新規作成されたのか」「既存が更新されたのか」を
ステータスコードだけで判別できる
2. Location ヘッダとの組み合わせ
→ 201 レスポンスには Location ヘッダで作成されたリソースの URI を含める
HTTP/1.1 201 Created
Location: /users/12345
Content-Type: application/json
{ "id": "12345", "name": "Alice", ... }
3. べき等性との区別
→ 200 は「もう一度やっても同じ結果」というニュアンスがある
→ 201 は「新しいものが作られた」という事実を正確に表現
ステータスコードまとめ(REST API)¶
GET /users → 200 OK
GET /users/:id → 200 OK / 404 Not Found
POST /users → 201 Created
PUT /users/:id → 200 OK(更新後のリソースを返す)
PATCH /users/:id → 200 OK
DELETE /users/:id → 204 No Content(ボディなし)
POST でリソース作成以外の用途(例: /login, /search):
→ 200 OK でよい(リソース作成ではないため)
実装例(Go)¶
func CreateUser(w http.ResponseWriter, r *http.Request) {
var req CreateUserRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "invalid request", http.StatusBadRequest)
return
}
user, err := userService.Create(r.Context(), req)
if err != nil {
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Location", fmt.Sprintf("/users/%s", user.ID))
w.WriteHeader(http.StatusCreated) // 201
json.NewEncoder(w).Encode(user)
}
面接でのポイント¶
- 「201 で、Location ヘッダにリソース URI を含める」まで言えると完答
- 「200 でも動くけど意味的に不正確」という説明ができるとベスト
- POST が常に 201 とは限らない(/login は 200)という例外も押さえておく