Path Params, Query Parameters ו-Body

מטרות השיעור
  • להבחין בין Path Parameter, Query Parameter ו-Body
  • לבחור את הדרך הנכונה להעביר כל סוג של מידע
  • לבנות URL עם Query נכון, ולהבין למה תווים מיוחדים מקודדים
  • לזהות בבקשה אמיתית מה נמצא ב-Path, מה ב-Query ומה ב-Body

מה נלמד?

Client צריך להגיד לשרת מה בדיוק הוא רוצה. יש לו שלוש דרכים:

דרךאיפהדוגמה
Path Parameterחלק מהנתיב עצמו/students/7
Query Parametersאחרי ? ב-URL/students?city=Haifa&limit=10
Bodyבגוף הבקשה (JSON){"name": "Dana", "age": 24}

למה צריך את זה?

בשיעור הבא נכתוב את השרת הראשון, וב-FastAPI כל אחת מהשלוש מוגדרת בדרך אחרת. אם לא מבינים את ההבדל, שמים מידע במקום הלא נכון: מזהה ב-Body, או סיסמה ב-URL. וכל API אמיתי שתצרכו (GitHub, מזג אוויר, תשלומים) משתמש בשלושתן.

הסבר מהבסיס

Path Parameter — “איזה?”

חלק משתנה בתוך הנתיב, שמזהה משאב ספציפי:

GET /students/7
              └─ path parameter: which student
GET /users/octocat/repos
           └─ path parameter: which user

מתי: כשמזהים פריט אחד (בדרך כלל לפי id). בלי הפרמטר, הנתיב לא שלם.

Query Parameters — “איך? כמה? לפי מה לסנן?”

זוגות key=value אחרי ?, מופרדים ב-&:

GET /students?city=Haifa&min_age=20&limit=10
             └──────────── query string ────────┘
                key=value & key=value & key=value

מתי: סינון, מיון, עימוד (Pagination), ואפשרויות. בדרך כלל אופציונליים: GET /students עובד גם בלעדיהם, ופשוט מחזיר הכול.

Body — “הנה הנתונים”

הנתונים עצמם, בגוף הבקשה, כמעט תמיד ב-JSON:

POST /students
Content-Type: application/json

{"name": "Dana", "age": 24, "email": "dana@mail.com"}

מתי: כששולחים נתונים ליצירה או לעדכון (POST, PUT). אפשר לשלוח מבנים מורכבים (רשימות, אובייקטים מקוננים) וכמויות גדולות. ל-GET ול-DELETE אין Body.

איך מחליטים?

שאלהדרך
מזהה איזה פריט?Path — /students/7
מסנן, ממיין, מגביל כמות, אפשרות תצוגה?Query — ?city=Haifa&sort=age
הנתונים של משאב שיוצרים או מעדכנים?Body — JSON
מידע רגיש (סיסמה, טוקן)?לעולם לא ב-URL (נשמר בלוגים ובהיסטוריית הדפדפן). Body או Headers
אנלוגיה: הזמנה בפיצרייה בטלפון

“אני מתקשר לסניף חיפה” (Path: לאיזה מקום בדיוק). “תגידו לי את המבצעים, רק טבעוניים, הכי זולים קודם” (Query: סינון ומיון של מה שאני מבקש). “אני רוצה להזמין: פיצה משפחתית, זיתים, פטריות, לכתובת הרצל 10” (Body: הפרטים המלאים של מה שיוצרים).

קידוד URL (URL Encoding)

ב-URL אסור רווחים ותווים מיוחדים “כמו שהם”. רווח הופך ל-%20 (או +), & בתוך ערך הופך ל-%26, ועברית מקודדת לבתים (%D7%93...). הדפדפן והספריות עושים את הקידוד בשבילנו — אבל חשוב להבין למה הוא קיים.

לפרק כתובת

/students/7/grades?semester=2&limit=5

path   ->  students / 7 / grades   (the grades of student 7)
query  ->  semester = 2            (a filter)
           limit    = 5            (how many)
  • ה-Path מזהה איזה משאב: הציונים של סטודנט 7.
  • ה-Query מתחיל אחרי ?, וכל פרמטר מופרד ב-&. הוא אומר איך: איזה סמסטר, וכמה תוצאות.

שלושתם בבקשה אחת

PUT /students/7?notify=true
Content-Type: application/json

{"name": "Dana Cohen", "age": 25}
חלקערךלמה כאן
Path7איזה סטודנט — חלק מהזהות של המשאב
Querynotify=trueאפשרות של הבקשה — לא חלק מהנתונים
Body{"name": ..., "age": ...}הנתונים החדשים עצמם
HeaderContent-Type: application/jsonבאיזה פורמט הגוף

בשיעור הבא נראה איך FastAPI מקבל את שלושתם אוטומטית — ומכניס כל אחד לפרמטר של הפונקציה שלנו.

טעות נפוצה

הטעות 1: מזהה ב-Query במקום ב-Path, או ההפך.

GET /students?id=7          ← works, but not the convention for ONE resource
GET /students/city/Haifa    ← "Haifa" is a filter, not a resource id

מוסכמה: פריט ספציפי ב-Path (/students/7), סינון ב-Query (/students?city=Haifa).

הטעות 2: ערך עם רווחים ו-& “כמו שהוא” בכתובת.

/search?q=rock & roll

הרווחים שוברים את הכתובת, וה-& מתפרש כתחילת פרמטר חדש. הערך צריך להיות מקודד: q=rock+%26+roll.

הטעות 3: לשכוח שכל מה שב-URL הוא מחרוזת. "7" ≠ 7. השוואה if student_id == 7 כש-student_id הגיע מה-URL כ-"7" → False. (FastAPI ימיר בשבילנו, אם נגדיר טיפוס.)

הטעות 4: מידע רגיש ב-URL. GET /login?user=dana&password=1234. ה-URL נשמר בהיסטוריית הדפדפן, בלוגים של שרתים, ובקישורים ששולחים. סיסמאות: רק ב-Body (ותמיד ב-HTTPS).

תרגול

התרגילים מבוססים רק על מה שנלמד בשיעור הזה ובשיעורים שלפניו. נסו לבד, ורק אז פתחו את הפתרון.

תרגיל 1: איפה שמים כל נתון?

לכל בקשה — האם הנתון הוא Path Parameter, Query Parameter או Body?

  1. מזהה הסטודנט שרוצים לקבל.
  2. סינון סטודנטים לפי עיר.
  3. השם והגיל של סטודנט חדש.
  4. כמה תוצאות להחזיר בעמוד.
  5. הנתונים המעודכנים של סטודנט קיים.
הצג פתרון
  1. Path — מזהה איזה משאב: /students/7.
  2. Query — סינון: /students?city=Haifa.
  3. Body — הנתונים של משאב חדש, ב-JSON.
  4. Query — אפשרות: ?limit=10.
  5. Body (והמזהה ב-Path): PUT /students/7 עם גוף.

הכלל: Path — איזה משאב. Query — סינון, מיון ועמודים. Body — הנתונים עצמם.

תרגיל 2: לפרק כתובת

פרקו את הכתובת: מה ה-Path, מה המזהה שבתוכו, ומה ה-Query Parameters?

https://api.kodkod.dev/students/7/grades?semester=2&limit=5
הצג פתרון
חלקערךמשמעות
Path/students/7/gradesהציונים של סטודנט 7
מזהה ב-Path7איזה סטודנט
Querysemester=2סינון — סמסטר 2
Querylimit=5כמה תוצאות — 5

ה-Query מתחיל אחרי ?, וכל פרמטר מופרד ב-&.

תרגיל 3: לבנות כתובת

כתבו את הכתובות לבקשות הבאות, לשרת https://api.x.com:

  1. כל הסטודנטים מחיפה.
  2. סטודנטים מחיפה, עשרה ראשונים.
  3. סטודנט 7.
  4. הציונים של סטודנט 7 בסמסטר 1.
הצג פתרון
1. https://api.x.com/students?city=Haifa
2. https://api.x.com/students?city=Haifa&limit=10
3. https://api.x.com/students/7
4. https://api.x.com/students/7/grades?semester=1

המזהה הולך בנתיב, והסינונים ב-Query — אחרי ?, ומחוברים ב-&.

תרגיל 4: שלושתם בבקשה אחת

PUT /students/7?notify=true
Content-Type: application/json

{"name": "Dana Cohen", "age": 25}

זהו את ה-Path Parameter, את ה-Query Parameter ואת ה-Body, והסבירו למה כל נתון נמצא במקום שלו. מה התפקיד של ה-Header Content-Type?

הצג פתרון
  • Path: 7 — איזה סטודנט מעדכנים. זה חלק מהזהות של המשאב.
  • Query: notify=true — אפשרות של הבקשה: איך לבצע אותה. זה לא חלק מהנתונים של הסטודנט.
  • Body: {"name": "Dana Cohen", "age": 25} — הנתונים החדשים עצמם.
  • Content-Type: application/json — אומר לשרת באיזה פורמט הגוף, כדי שידע איך לקרוא אותו.

תרגיל 5: מה לא שמים בכתובת?

לכל כתובת — מה הבעיה, ואיך עושים את זה נכון?

1. GET /students?id=7
2. GET /students/city/Haifa
3. GET /login?user=dana&password=1234
4. GET /search?q=rock & roll
הצג פתרון
  1. מזהה של פריט אחד שייך לנתיב: GET /students/7. ה-Query מיועד לסינון.
  2. “Haifa” הוא סינון, לא מזהה של משאב: GET /students?city=Haifa.
  3. סיסמה בכתובת נשמרת בהיסטוריית הדפדפן, בלוגים של שרתים ובקישורים ששולחים. סיסמאות — רק ב-Body, ותמיד ב-HTTPS.
  4. רווחים ו-& בתוך ערך שוברים את הכתובת: ה-& מתפרש כתחילת פרמטר חדש. הערך צריך להיות מקודד (URL Encoding): q=rock+%26+roll. בפועל, הדפדפן והספריות עושים את הקידוד בשבילנו.

סיכום

  • Path Parameter (/students/7) — איזה משאב. חלק מהנתיב.
  • Query Parameters (?city=Haifa&limit=10) — סינון, מיון, עימוד, אפשרויות. בדרך כלל אופציונליים.
  • Body (JSON) — הנתונים ליצירה ולעדכון (POST, PUT). ל-GET ול-DELETE אין Body.
  • כל מה שב-URL הוא מחרוזת. בונים Query עם urlencode (קידוד רווחים, & ועברית).
  • סיסמאות ומידע רגיש לא שמים ב-URL.
  • בשיעור 5, FastAPI יפענח את שלושתם אוטומטית, כולל המרת טיפוסים.

דוקומנטציה רשמית