URL структура REST API: Правильное построение URL
Введение: адрес дома 🏠
URL в API — это адрес, по которому «живёт» ресурс.
Если адреса хаотичные, клиент теряется так же, как в городе без улиц и домов.
Если адреса хаотичные, клиент теряется так же, как в городе без улиц и домов.
💡 Совет: хороший URL читается как предложение: «получи список курсов».
✅ Вывод: URL должен быть понятным, как обычный адрес.
✅ Вывод: URL должен быть понятным, как обычный адрес.
Проблема → решение
Проблема: когда URL содержит глаголы, технические детали или странные вложенности, API становится непредсказуемым.
Решение: строить URL по правилам: ресурсы, иерархия, единые соглашения.
Решение: строить URL по правилам: ресурсы, иерархия, единые соглашения.
✅ Вывод: единая структура URL экономит время всей команды.
Чем помогает и как работает
Правильная структура URL делает API читаемым и единообразным.
Это снижает путаницу и упрощает поддержку документации.
Как это работает:
- URL описывает ресурс существительным (
/courses). - Конкретный объект задаём через id (
/courses/10). - Условия выдачи (фильтры, сортировка) помещаем в query.
✅ Вывод: ресурсные URL делают API понятным и стабильным.
Ключевые термины (простыми словами)
- Resource (ресурс) — объект API (курс, студент).
- Collection (коллекция) — список ресурсов (courses).
- Path parameter — переменная в пути (
/courses/{id}). - Query parameter — параметры после
?(фильтры, сортировка). - Nested resource — вложенный ресурс (
/courses/{id}/lessons). - HATEOAS — ответы содержат ссылки на следующие действия/ресурсы, чтобы клиент мог «следовать» по API.
✅ Вывод: термины помогают строить URL «по полочкам».
Самое важное (must‑know)
- URL = ресурс, не действие (без глаголов).
- Коллекции — во множественном числе (
/courses). - ID в пути, фильтры — в query.
- Глубокая вложенность — максимум 1–2 уровня.
- Один стиль для всех URL.
✅ Вывод: эти правила делают API читаемым и масштабируемым.
1. Ресурсные URL (существительные)
Назначение: описывать, что это за объект.
Простыми словами: URL говорит «что это», а не «что сделать».
Аналогия: на двери пишут «кабинет 204», а не «работать».
Простыми словами: URL говорит «что это», а не «что сделать».
Аналогия: на двери пишут «кабинет 204», а не «работать».
Пример:
/courses/students🔎 Как это происходит на практике:
- Клиент запрашивает список по
GET /courses. - URL описывает ресурс, а не действие.
- Сервер возвращает коллекцию курсов.
Характеристики:
- ✅ существительные;
- ✅ читается как объект;
- ✅ без глаголов.
Когда использовать: всегда для ресурсов.
✅ Вывод: URL = имя ресурса.
✅ Вывод: URL = имя ресурса.
2. Коллекция и конкретный объект
Назначение: различать список и один элемент.
Простыми словами: один URL — список, другой — конкретный объект.
Аналогия: «улица» vs «дом №10».
Простыми словами: один URL — список, другой — конкретный объект.
Аналогия: «улица» vs «дом №10».
Пример:
/courses/courses/10🔎 Как это происходит на практике:
- Клиент открывает
/coursesи получает список. - Затем запрашивает
/courses/10для деталей. - Один шаблон работает для всех ресурсов.
Характеристики:
- ✅ коллекция — без id;
- ✅ объект — с id;
- ✅ единый паттерн.
Когда использовать: когда есть список и детали.
✅ Вывод: коллекция и объект — два разных адреса.
✅ Вывод: коллекция и объект — два разных адреса.
3. Вложенность и иерархия
Назначение: показать связь между ресурсами.
Простыми словами: вложенный URL = «часть целого».
Аналогия: комната внутри здания.
Простыми словами: вложенный URL = «часть целого».
Аналогия: комната внутри здания.
Пример:
/courses/10/lessons🔎 Как это происходит на практике:
- Клиенту нужны уроки курса 10.
- Он использует
/courses/10/lessons. - Сервер возвращает дочерние ресурсы.
Характеристики:
- ✅ подходит для «дочерних» сущностей;
- ✅ не углубляемся больше 2 уровней.
Когда использовать: когда ресурс принадлежит другому.
✅ Вывод: вложенность = связь.
✅ Вывод: вложенность = связь.
4. Query‑параметры — для фильтров
Назначение: задавать условия и сортировку.
Простыми словами: путь говорит «где», query — «какие».
Аналогия: адрес дома + «этаж, подъезд».
Простыми словами: путь говорит «где», query — «какие».
Аналогия: адрес дома + «этаж, подъезд».
Пример:
/courses?level=beginner&sort=rating🔎 Как это происходит на практике:
- Клиент передаёт
/courses?level=beginner&sort=rating. - Сервер применяет фильтр и сортировку.
- Ответ содержит отфильтрованный список.
Характеристики:
- ✅ фильтры и сортировка;
- ✅ опционально;
- ✅ не для обязательных параметров.
Когда использовать: фильтры, пагинация.
✅ Вывод: условия — в query, не в пути.
✅ Вывод: условия — в query, не в пути.
5. Действия как под‑ресурсы
Назначение: описывать операции, которые не являются ресурсом.
Простыми словами: если это действие, добавляем под‑путь.
Аналогия: «запустить курс» как отдельный процесс.
Простыми словами: если это действие, добавляем под‑путь.
Аналогия: «запустить курс» как отдельный процесс.
Пример:
POST /courses/10/publish🔎 Как это происходит на практике:
- Клиент отправляет
POST /courses/10/publish. - Сервер выполняет действие публикации.
- Возвращает результат операции и статус.
Характеристики:
- ✅ действие — отдельный URL;
- ✅ метод определяет тип операции.
Когда использовать: публикация, активация, отмена.
✅ Вывод: действия = под‑ресурсы.
✅ Вывод: действия = под‑ресурсы.
6. Единый стиль и читаемость
Назначение: сделать URL визуально одинаковыми.
Простыми словами: все адреса выглядят как из одного шаблона.
Аналогия: единые дорожные знаки в городе.
Простыми словами: все адреса выглядят как из одного шаблона.
Аналогия: единые дорожные знаки в городе.
Пример:
/kebab-case🔎 Как это происходит на практике:
- Команда выбирает kebab‑case для всех URL.
- Все эндпоинты выглядят единообразно.
- Документация и клиенты не путаются.
Характеристики:
- ✅ единый стиль (kebab‑case);
- ✅ без расширений (.php);
- ✅ без лишних слов.
Когда использовать: всегда.
✅ Вывод: единый стиль = меньше ошибок.
✅ Вывод: единый стиль = меньше ошибок.
Сравнение: хороший vs плохой URL
| Плохо | Хорошо | Почему |
|---|---|---|
| /getCourses | /courses | глагол → ресурс |
| /course/10 | /courses/10 | коллекция во мн. числе |
| /courses/delete/10 | DELETE /courses/10 | действие = метод |
| /courses?filter= | /courses?level= | понятный фильтр |
✅ Вывод: URL должен быть «читаемым адресом».
Часто спрашивают на собеседованиях
- Почему нельзя глаголы в URL? действие — это метод.
- Коллекция или объект? коллекция без id, объект с id.
- Query или path? query для фильтров и сортировки.
- Насколько глубоко вкладывать? 1–2 уровня максимум.
- Нужно ли расширение (.php)? нет, API не про файлы.
✅ Вывод: эти вопросы — классика интервью.
Типичные ошибки
Ошибка 1: глаголы в URL
❌
✅
Почему: действие — это метод.
Практический пример:
/getCourses✅
/coursesПочему: действие — это метод.
Практический пример:
GET /courses.Ошибка 2: глубокая вложенность
❌
✅
Почему: длинные URL сложно поддерживать.
/users/1/orders/3/items/5/products✅
/orders/3/itemsПочему: длинные URL сложно поддерживать.
Ошибка 3: фильтр в пути
❌
✅
Почему: фильтры — это query.
/courses/level/beginner✅
/courses?level=beginnerПочему: фильтры — это query.
Ошибка 4: смешанный стиль
❌
✅ единый kebab‑case
Почему: единый стиль проще читать.
/course_list и /courses-list✅ единый kebab‑case
Почему: единый стиль проще читать.
Ошибка 5: действия в path без метода
❌
✅
Почему: метод описывает действие.
/courses/delete/10✅
DELETE /courses/10Почему: метод описывает действие.
Best Practices
- Используйте существительные в URL.
- Коллекции — во множественном числе.
- ID только в path, фильтры — в query.
- Действия оформляйте как под‑ресурс + POST.
- Держите вложенность максимум 2 уровня.
- Следуйте одному стилю (kebab‑case).
Заключение
🧭 URL — это карта вашего API.
🏠 Чем понятнее адреса, тем быстрее клиент ориентируется.
✅ Хорошая структура = меньше ошибок и вопросов.
🏠 Чем понятнее адреса, тем быстрее клиент ориентируется.
✅ Хорошая структура = меньше ошибок и вопросов.
Теперь вы умеете строить URL так, чтобы ими было удобно пользоваться каждый день.