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}| חלק | ערך | למה כאן |
|---|---|---|
| Path | 7 | איזה סטודנט — חלק מהזהות של המשאב |
| Query | notify=true | אפשרות של הבקשה — לא חלק מהנתונים |
| Body | {"name": ..., "age": ...} | הנתונים החדשים עצמם |
| Header | Content-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?
- מזהה הסטודנט שרוצים לקבל.
- סינון סטודנטים לפי עיר.
- השם והגיל של סטודנט חדש.
- כמה תוצאות להחזיר בעמוד.
- הנתונים המעודכנים של סטודנט קיים.
הצג פתרון
- Path — מזהה איזה משאב:
/students/7. - Query — סינון:
/students?city=Haifa. - Body — הנתונים של משאב חדש, ב-JSON.
- Query — אפשרות:
?limit=10. - 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 |
| מזהה ב-Path | 7 | איזה סטודנט |
| Query | semester=2 | סינון — סמסטר 2 |
| Query | limit=5 | כמה תוצאות — 5 |
ה-Query מתחיל אחרי ?, וכל פרמטר מופרד ב-&.
תרגיל 3: לבנות כתובת
כתבו את הכתובות לבקשות הבאות, לשרת https://api.x.com:
- כל הסטודנטים מחיפה.
- סטודנטים מחיפה, עשרה ראשונים.
- סטודנט 7.
- הציונים של סטודנט 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הצג פתרון
- מזהה של פריט אחד שייך לנתיב:
GET /students/7. ה-Query מיועד לסינון. - “Haifa” הוא סינון, לא מזהה של משאב:
GET /students?city=Haifa. - סיסמה בכתובת נשמרת בהיסטוריית הדפדפן, בלוגים של שרתים ובקישורים ששולחים. סיסמאות — רק ב-Body, ותמיד ב-HTTPS.
- רווחים ו-
&בתוך ערך שוברים את הכתובת: ה-&מתפרש כתחילת פרמטר חדש. הערך צריך להיות מקודד (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 יפענח את שלושתם אוטומטית, כולל המרת טיפוסים.
דוקומנטציה רשמית
- MDN — What is a URL? — Path ו-Query בכתובת
- MDN — HTTP messages: Body — ה-Body של בקשה