1. ספרייה
  2. HTTP והרשת
  3. קודי סטטוס HTTP

עודכן לפני חודש

כאשר שרת מחזיר 201 Created, הוא עושה הכרזה מדויקת: משהו חדש קיים עכשיו שלא היה קיים לפני. זו לא רק תגובה מוצלחת — זו תעודת לידה. השרת אומר לך: "יצרתי משהו. הוא לא היה קיים קודם. עכשיו הוא קיים. הנה היכן הוא נמצא."

זה שונה מ-200 OK, שמשמעותו "הבקשה שלך עבדה והנה התוצאה." 201 אומר שהבקשה שלך הביאה משהו לידי קיום.

כותרת Location: היכן המשאב החדש נמצא

תגובת 201 צריכה לכלול כותרת Location שמצביעה על המשאב שנוצר:

HTTP/1.1 201 Created
Location: /api/users/124
Content-Type: application/json

{
    "id": 124,
    "name": "Alice",
    "email": "alice@example.com",
    "createdAt": "2024-10-21T14:22:00Z"
}

כותרת Location עונה על השאלה המיידית: "מצוין, יצרת משהו — איפה הוא?" בלי כותרת זו, הלקוחות צריכים לנתח את גוף התגובה, למצוא מזהה, ולבנות את ה-URL בעצמם. כותרת Location פשוט אומרת להם.

מה לכלול בגוף התגובה

החזר את המשאב המלא שנוצר, כולל כל מה שהשרת יצר:

POST /api/users HTTP/1.1
Content-Type: application/json

{
    "name": "Alice",
    "email": "alice@example.com"
}

HTTP/1.1 201 Created
Location: /api/users/124
Content-Type: application/json

{
    "id": 124,
    "name": "Alice",
    "email": "alice@example.com",
    "createdAt": "2024-10-21T14:22:00Z",
    "updatedAt": "2024-10-21T14:22:00Z",
    "emailVerified": false
}

הלקוח שלח שני שדות. השרת מחזיר שישה. ארבעת השדות הנוספים — id, createdAt, updatedAt, emailVerified — הם תרומת השרת. הלקוח צריך לראות אותם מבלי לשלוח בקשה נוספת.

אפשר להחזיר גוף ריק ולאלץ לקוחות לבצע GET על המשאב מה-URL של Location. אבל זה שתי נסיעות הלוך-חזור במקום אחת. החזר את המשאב.

201 מול 200: יצירה מול פעולה

ההבחנה חשובה:

201 Created: משאב חדש קיים עכשיו שלא היה קיים לפני.

200 OK: הבקשה הצליחה — משהו קרה, אולי תקבל נתונים בחזרה, אבל שום דבר חדש שניתן לפנות אליו לא נוצר.

עדכון משתמש קיים? זה 200:

PUT /api/users/124 HTTP/1.1
{"name": "Alice Updated"}

HTTP/1.1 200 OK

יצירת משתמש חדש? זה 201:

POST /api/users HTTP/1.1
{"name": "Alice"}

HTTP/1.1 201 Created
Location: /api/users/124

PUT חושף משהו מוזר

PUT יכול ליצור או לעדכן בהתאם לאם המשאב קיים:

PUT /api/users/999 HTTP/1.1
{"name": "Charlie"}

אם משתמש 999 לא קיים, השרת יוצר אותו ומחזיר 201. אם משתמש 999 כבר קיים, השרת מעדכן אותו ומחזיר 200.

והנה מה שמוזר: כשאתה שולח בקשה זו, אינך יודע מה יקרה. הבייטים שלך נוסעים לשרת מבלי לדעת אם יגרמו ללידה או לשינוי. קוד הסטטוס בתגובה הוא הרגע הראשון שבו מישהו — כולל אתה — יודע מה באמת קרה.

בקשה ראשונה: 201 (משהו חדש קיים). אותה בקשה שוב: 200 (משהו עודכן). הבייטים היו זהים. המשמעות לא הייתה.

POST יוצר בכל פעם

POST אינו אידמפוטנטי. כל בקשה יוצרת משאב חדש:

POST /api/users → 201 Created, Location: /api/users/124
POST /api/users → 201 Created, Location: /api/users/125
POST /api/users → 201 Created, Location: /api/users/126

שלוש בקשות, שלושה משתמשים חדשים, שלוש כותרות Location שונות. כל 201 מכריז על יצירה נפרדת.

טיפול בצד הלקוח

const response = await fetch('/api/users', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ name: 'Alice', email: 'alice@example.com' })
});

if (response.status === 201) {
    const location = response.headers.get('Location');
    const user = await response.json();
    // user.id, user.createdAt, וכו' זמינים עכשיו
}

בדוק תחילה את קוד הסטטוס. 201 אומר שהיצירה הצליחה. לאחר מכן חלץ גם את כותרת Location (היכן למצוא אותו) וגם את גוף התגובה (המשאב עצמו).

טעויות נפוצות

החזרת 201 עבור עדכונים:

PUT /api/users/124  // המשתמש כבר קיים
HTTP/1.1 201 Created  // שגוי — צריך להיות 200 OK

החזרת 201 כאשר היצירה נכשלה:

POST /api/users
HTTP/1.1 201 Created
{"error": "Email already registered"}  // שגוי — צריך להיות 409 Conflict

השמטת כותרת Location:

HTTP/1.1 201 Created
{"id": 124, "name": "Alice"}  // היכן המשאב הזה נמצא?

תמיד כלול Location. זה כל הנקודה של 201 — לא רק "יצרתי משהו" אלא "יצרתי משהו והנה היכן הוא נמצא."

שאלות נפוצות על 201 Created

האם תמיד עלי להחזיר את המשאב שנוצר בגוף התגובה?

כן. מבחינה טכנית אפשר להחזיר גוף ריק ולתת ללקוחות לאחזר מה-URL של Location, אבל זה מבזבז נסיעת הלוך-חזור מיותרת. החזר את המשאב המלא, כולל כל השדות שנוצרו על ידי השרת כמו מזהים וחותמות זמן.

מה ההבדל בין 201 ל-200 עבור בקשות POST?

השתמש ב-201 כאשר ה-POST יצר משאב חדש שיש לו כעת URL משלו. השתמש ב-200 כאשר ה-POST עשה משהו אחר — עיבד נתונים, הפעיל פעולה, או החזיר חישוב. אם משהו חדש קיים שניתן לאחזר ב-URL, זה 201.

האם אפשר להשתמש ב-201 ליצירת אצווה של מספר משאבים?

זה לא חד-משמעי. 201 מרמז על כותרת Location בודדת, אבל יצירת אצווה מייצרת מספר משאבים. גם 200 וגם 201 סבירים. אם משתמשים ב-201, לא ניתן לספק Location בודד, לכן כלול את המשאבים שנוצרו בגוף התגובה עם ה-URL הייחודי של כל אחד.

מקורות

האם דף זה היה מועיל?

😔
🤨
😃
201 Created • ספרייה • Connected