# Path Params, Query Parameters ו-Body<no value>

## מה נלמד?

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 — "איזה?"

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

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

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

### Query Parameters — "איך? כמה? לפי מה לסנן?"

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

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

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

### Body — "הנה הנתונים"

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

```text
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 |

{{< box "analogy" "אנלוגיה: הזמנה בפיצרייה בטלפון" >}}
"אני מתקשר **לסניף חיפה**" (**Path**: לאיזה מקום בדיוק). "תגידו לי את המבצעים, **רק טבעוניים**, **הכי זולים קודם**" (**Query**: סינון ומיון של מה שאני מבקש). "אני רוצה להזמין: **פיצה משפחתית, זיתים, פטריות, לכתובת הרצל 10**" (**Body**: הפרטים המלאים של מה שיוצרים).
{{< /box >}}

### קידוד URL (URL Encoding)

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

## לפרק כתובת

```text
/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** מתחיל אחרי `?`, וכל פרמטר מופרד ב-`&`. הוא אומר **איך**: איזה סמסטר, וכמה תוצאות.

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

```text
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, או ההפך.**

```text
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: ערך עם רווחים ו-`&` "כמו שהוא" בכתובת.**

```text
/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).

<!-- exercises:start — generated by scripts/intro6/sync_site_exercises.py; edit scripts/intro6/exercises/ -->
## תרגול

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

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

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

1. מזהה הסטודנט שרוצים לקבל.
2. סינון סטודנטים לפי עיר.
3. השם והגיל של סטודנט חדש.
4. כמה תוצאות להחזיר בעמוד.
5. הנתונים המעודכנים של סטודנט קיים.

{{< solution >}}
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** — הנתונים עצמם.
{{< /solution >}}

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

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

```text
https://api.kodkod.dev/students/7/grades?semester=2&limit=5
```

{{< solution >}}
| חלק | ערך | משמעות |
|---|---|---|
| Path | `/students/7/grades` | הציונים של סטודנט 7 |
| מזהה ב-Path | `7` | **איזה** סטודנט |
| Query | `semester=2` | סינון — סמסטר 2 |
| Query | `limit=5` | כמה תוצאות — 5 |

ה-Query מתחיל אחרי `?`, וכל פרמטר מופרד ב-`&`.
{{< /solution >}}

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

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

1. כל הסטודנטים מחיפה.
2. סטודנטים מחיפה, עשרה ראשונים.
3. סטודנט 7.
4. הציונים של סטודנט 7 בסמסטר 1.

{{< solution >}}
```text
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** — אחרי `?`, ומחוברים ב-`&`.
{{< /solution >}}

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

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

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

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

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

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

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

```text
1. GET /students?id=7
2. GET /students/city/Haifa
3. GET /login?user=dana&password=1234
4. GET /search?q=rock & roll
```

{{< solution >}}
1. **מזהה של פריט אחד שייך לנתיב**: `GET /students/7`. ה-Query מיועד לסינון.
2. **"Haifa" הוא סינון, לא מזהה של משאב**: `GET /students?city=Haifa`.
3. **סיסמה בכתובת** נשמרת בהיסטוריית הדפדפן, בלוגים של שרתים ובקישורים ששולחים. סיסמאות — **רק ב-Body**, ותמיד ב-HTTPS.
4. **רווחים ו-`&` בתוך ערך** שוברים את הכתובת: ה-`&` מתפרש כתחילת פרמטר חדש. הערך צריך להיות **מקודד** (URL Encoding): `q=rock+%26+roll`. בפועל, הדפדפן והספריות עושים את הקידוד בשבילנו.
{{< /solution >}}

<!-- exercises:end -->

## סיכום

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

<!-- docs:start — generated by scripts/intro6/site_docs.py; edit the links there -->

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

- [MDN — What is a URL?](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Web_mechanics/What_is_a_URL) — Path ו-Query בכתובת
- [MDN — HTTP messages: Body](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Messages#request_body) — ה-Body של בקשה

<!-- docs:end -->
