Параметры пути, параметры запроса и тело
- Различать параметр пути (Path Parameter), параметр запроса (Query Parameter) и тело (Body)
- Выбирать правильный способ передачи каждого вида информации
- Строить URL с правильной строкой запроса и понимать, почему специальные символы кодируются
- Распознавать в настоящем запросе, что находится в пути, что в строке запроса, а что в теле
Что мы изучим?
Клиенту нужно сказать серверу, что именно он хочет. Для этого есть три способа:
| Способ | Где | Пример |
|---|---|---|
| Параметр пути (Path Parameter) | Часть самого пути | /students/7 |
| Параметры запроса (Query Parameters) | После ? в URL | /students?city=Haifa&limit=10 |
| Тело (Body) | В теле запроса (JSON) | {"name": "Dana", "age": 24} |
Зачем это нужно?
В следующем уроке мы напишем первый сервер, и в FastAPI каждый из трёх способов определяется по-своему. Если не понимать разницу, информация попадает не туда: идентификатор — в тело, а пароль — в URL. А каждый настоящий API, которым вы будете пользоваться (GitHub, погода, платежи), использует все три.
Объяснение с основ
Параметр пути — «какой именно?»
Переменная часть внутри пути, которая идентифицирует конкретный ресурс:
GET /students/7
└─ path parameter: which student
GET /users/octocat/repos
└─ path parameter: which userКогда: когда вы идентифицируете один элемент (обычно по id). Без параметра путь неполный.
Параметры запроса — «как? сколько? отфильтровать по чему?»
Пары key=value после ?, разделённые &:
GET /students?city=Haifa&min_age=20&limit=10
└──────────── query string ────────┘
key=value & key=value & key=valueКогда: фильтрация, сортировка, постраничный вывод (Pagination) и опции. Обычно необязательны: GET /students работает и без них и просто возвращает всё.
Тело — «вот данные»
Сами данные, в теле запроса, почти всегда в JSON:
POST /students
Content-Type: application/json
{"name": "Dana", "age": 24, "email": "dana@mail.com"}Когда: когда вы отправляете данные для создания или обновления (POST, PUT). Можно отправлять сложные структуры (списки, вложенные объекты) и большие объёмы. У GET и DELETE тела нет.
Как решить?
| Вопрос | Способ |
|---|---|
| Идентифицирует, какой элемент? | Путь — /students/7 |
| Фильтрует, сортирует, ограничивает количество, опция отображения? | Строка запроса — ?city=Haifa&sort=age |
| Данные ресурса, который вы создаёте или обновляете? | Тело — JSON |
| Чувствительная информация (пароль, токен)? | Никогда в URL (он сохраняется в логах и в истории браузера). Тело или заголовки (Headers) |
«Я звоню в хайфский филиал» (путь: какое именно место). «Расскажите об акциях, только веганские, сначала самые дешёвые» (строка запроса: фильтрация и сортировка того, что я спрашиваю). «Хочу заказать: семейную пиццу, маслины, грибы, на улицу Герцля, 10» (тело: полные данные того, что создаётся).
Кодирование 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)- Путь идентифицирует, какой ресурс: оценки студента 7.
- Строка запроса начинается после
?, и параметры разделяются&. Она говорит, как: какой семестр и сколько результатов.
Все три в одном запросе
PUT /students/7?notify=true
Content-Type: application/json
{"name": "Dana Cohen", "age": 25}| Часть | Значение | Почему здесь |
|---|---|---|
| Путь | 7 | Какой студент — часть идентичности ресурса |
| Строка запроса | notify=true | Опция запроса — не часть данных |
| Тело | {"name": ..., "age": ...} | Сами новые данные |
| Заголовок | Content-Type: application/json | В каком формате тело |
В следующем уроке мы увидим, как FastAPI автоматически принимает все три — и кладёт каждый в параметр нашей функции.
Типичная ошибка
Ошибка 1: идентификатор в строке запроса вместо пути — или наоборот.
GET /students?id=7 ← works, but not the convention for ONE resource
GET /students/city/Haifa ← "Haifa" is a filter, not a resource idСоглашение: конкретный элемент — в пути (/students/7), фильтрация — в строке запроса (/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 сохраняется в истории браузера, в логах сервера и в ссылках, которые вы отправляете. Пароли — только в теле (и всегда через HTTPS).
Практика
Упражнения опираются только на то, что пройдено в этом уроке и в предыдущих. Сначала попробуйте сами, и только потом открывайте решение.
Упражнение 1: Куда идёт каждый кусок данных?
Для каждого запроса — являются ли данные параметром пути, параметром запроса или телом?
- Идентификатор студента, которого вы хотите получить.
- Фильтрация студентов по городу.
- Имя и возраст нового студента.
- Сколько результатов возвращать на страницу.
- Обновлённые данные существующего студента.
Показать решение
- Путь (Path) — идентифицирует, какой ресурс:
/students/7. - Строка запроса (Query) — фильтрация:
/students?city=Haifa. - Тело (Body) — данные нового ресурса в JSON.
- Строка запроса — опция:
?limit=10. - Тело (а идентификатор — в пути):
PUT /students/7с телом.
Правило: путь — какой ресурс. Строка запроса — фильтрация, сортировка и страницы. Тело — сами данные.
Упражнение 2: Разбор адреса
Разберите адрес: что является путём, какой в нём идентификатор и каковы параметры запроса?
https://api.kodkod.dev/students/7/grades?semester=2&limit=5Показать решение
| Часть | Значение | Смысл |
|---|---|---|
| Путь | /students/7/grades | Оценки студента 7 |
| Идентификатор в пути | 7 | Какой студент |
| Строка запроса | semester=2 | Фильтр — семестр 2 |
| Строка запроса | limit=5 | Сколько результатов — 5 |
Строка запроса начинается после ?, а параметры разделяются &.
Упражнение 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Идентификатор идёт в путь, а фильтры — в строку запроса, после ? и через &.
Упражнение 4: Все три в одном запросе
PUT /students/7?notify=true
Content-Type: application/json
{"name": "Dana Cohen", "age": 25}Определите параметр пути, параметр запроса и тело и объясните, почему каждый кусок данных находится на своём месте. Какова роль заголовка Content-Type?
Показать решение
- Путь:
7— какой студент обновляется. Это часть идентичности ресурса. - Строка запроса:
notify=true— опция запроса: как его выполнить. Это не часть данных студента. - Тело:
{"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. Строка запроса предназначена для фильтрации. - «Haifa» — фильтр, а не идентификатор ресурса:
GET /students?city=Haifa. - Пароль в адресе сохраняется в истории браузера, в логах сервера и в ссылках, которые вы отправляете. Пароли — только в теле, и всегда через HTTPS.
- Пробелы и
&внутри значения ломают адрес:&воспринимается как начало нового параметра. Значение нужно закодировать (URL Encoding):q=rock+%26+roll. На практике кодирование за нас делают браузер и библиотеки.
Итоги
- Параметр пути (
/students/7) — какой ресурс. Часть пути. - Параметры запроса (
?city=Haifa&limit=10) — фильтрация, сортировка, постраничный вывод, опции. Обычно необязательны. - Тело (JSON) — данные для создания и обновления (POST, PUT). У GET и DELETE тела нет.
- Всё в URL — строка. Строку запроса нужно правильно кодировать (пробелы,
&и неанглийские буквы). - Не кладите пароли и чувствительную информацию в URL.
- В следующих уроках FastAPI будет автоматически разбирать все три, включая преобразование типов.