Що таке REST
REST не є протоколом, бібліотекою чи стандартом. Це набір архітектурних принципів та обмежень (constraints), слідування яким робить вебсервіси масштабованими, надійними, гнучким...
🟢 Junior Level
REST (Representational State Transfer — «передача стану представлення») — це архітектурний стиль взаємодії компонентів розподіленого вебдодатка, сформульований Роєм Філдінгом у 2000 році в його докторській дисертації.
REST не є протоколом, бібліотекою чи стандартом. Це набір архітектурних принципів та обмежень (constraints), слідування яким робить вебсервіси масштабованими, надійними, гнучкими та продуктивними.
Ключові поняття REST
- Ресурс (Resource): Будь-яка сутність у системі, до якої можна звернутися (користувач, замовлення, товар). Ресурс завжди має унікальний ідентифікатор — URI (наприклад,
/api/v1/orders/42). - Представлення (Representation): Поточний стан ресурсу, переданий у певному форматі даних (зазвичай JSON, рідше XML).
- Стандартні методи HTTP: Операції над ресурсами виражаються через дієслова протоколу HTTP:
GET— читання ресурсу (безпечний та ідемпотентний).POST— створення нового ресурсу (неідемпотентний).PUT— повна заміна ресурсу (ідемпотентний).PATCH— часткове оновлення ресурсу (як правило, неідемпотентний).DELETE— видалення ресурсу (ідемпотентний).
- Статус-коди HTTP: Сервер повідомляє про результат операції стандартними тризначними кодами (
200 OK,201 Created,400 Bad Request,404 Not Found,500 Internal Server Error).
Базовий приклад REST-контролера на Spring Boot 3
package com.example.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
// GET /api/v1/users — отримати список ресурсів
@GetMapping
public List<UserResponseDto> getAllUsers() {
return userService.findAll();
}
// GET /api/v1/users/{id} — отримати конкретний ресурс
@GetMapping("/{id}")
public ResponseEntity<UserResponseDto> getUserById(@PathVariable Long id) {
return ResponseEntity.ok(userService.findById(id));
}
// POST /api/v1/users — створити ресурс
@PostMapping
public ResponseEntity<UserResponseDto> createUser(@RequestBody CreateUserRequest request) {
UserResponseDto created = userService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(created); // 201 Created
}
// DELETE /api/v1/users/{id} — видалити ресурс
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT) // 204 No Content
public void deleteUser(@PathVariable Long id) {
userService.deleteById(id);
}
}
🟡 Middle Level
6 архітектурних обмежень REST (Constraints)
Щоб API вважався істинно RESTful, він зобов’язаний задовольняти 6 суворим правилам:
1. Client-Server (Розподіл відповідальності інтерфейсу та сховища)
2. Stateless (Відсутність стану сесії клієнта на сервері)
3. Cacheable (Явний контроль кешування відповідей клієнтом і проксі)
4. Layered System (Багаторівнева система: балансувальники, CDN, шлюзи прозорі)
5. Uniform Interface (Одноманітний інтерфейс — фундамент REST)
6. Code on Demand (Опціонально: передача виконуваного коду, наприклад JS)
- Client-Server (Клієнт-Сервер): Повне розділення інтерфейсу користувача (Frontend, Mobile) та бізнес-логіки/сховища (Backend). Вони можуть еволюціонувати та масштабуватися незалежно.
- Stateless (Без збереження стану): Сервер не зберігає контекст сесії клієнта між запитами. Кожен запит зобов’язаний містити абсолютно всю інформацію для його авторизації та обробки (наприклад, JWT-токен у заголовку
Authorization). - Cacheable (Кешованість): Кожна відповідь зобов’язана явно оголошувати, чи можна її кешувати і на який термін (заголовки
Cache-Control,ETag,Last-Modified), виключаючи повторні важкі запити. - Layered System (Багаторівнева архітектура): Клієнт не знає, чи спілкується він безпосередньо з сервером додатків, чи з проміжною ланкою (Reverse Proxy, Load Balancer, API Gateway, CDN). Проміжні шари можуть забезпечувати безпеку та кешування без зміни контракту.
- Uniform Interface (Одноманітний інтерфейс): Найсуворіше та найголовніше обмеження REST, що складається з 4 постулатів:
- Ідентифікація ресурсів: Ресурси відокремлені від їхніх представлень і мають стабільні URI (
/products/123). - Маніпуляція через представлення: Клієнт передає представлення (
JSON) та бажану дію через HTTP-метод. - Самодостатні повідомлення (Self-descriptive messages): Кожен запит/відповідь містить метадані про формат (
Content-Type: application/json), кодування та кешування. - HATEOAS (Hypermedia As The Engine Of Application State): Відповідь сервера містить гіперпосилання на доступні подальші дії клієнта.
- Ідентифікація ресурсів: Ресурси відокремлені від їхніх представлень і мають стабільні URI (
- Code on Demand (Код на вимогу, опціональне): Сервер може передавати клієнту виконуваний код для тимчасового розширення функціональності (наприклад, JavaScript-сценарії або WebAssembly).
Модель зрілості Річардсона (Richardson Maturity Model)
Леонард Річардсон запропонував класифікацію вебсервісів за ступенем їхньої відповідності принципам REST:
Level 3: HATEOAS (Істинний RESTful API)
▲
Level 2: HTTP Verbs & Status Codes (Золотий стандарт індустрії / Pragmatic REST)
▲
Level 1: Ресурси (Кожен ресурс має свій URI: /orders, /users)
▲
Level 0: The Swamp of POX (Один URI, один HTTP-метод, RPC over HTTP, наприклад SOAP або XML-RPC)
- Level 0: Використання HTTP як простого транспорту. Усі запити йдуть методом
POSTна один ендпоінт/api/service, а дія зашита в тіло повідомлення. - Level 1 (Resources): Поява унікальних URI для сутностей (
/users/1,/orders), але операції все ще можуть виконуватися одним методомPOST. - Level 2 (HTTP Verbs & Codes): Коректне використання семантики HTTP: методи
GET,POST,PUT,DELETEта статус-коди200,201,404,500. Це рівень 99% комерційних «REST API». - Level 3 (HATEOAS): Сервер разом із даними повертає посилання на пов’язані дії (
_links). Повна відповідність баченню Роя Філдінга.
🔴 Senior Level
REST vs Альтернативи: Коли REST є поганим вибором
У сучасній enterprise-архітектурі REST не є срібною кулею:
| Технологія | Де перевершує REST | Коли обирати замість REST |
|---|---|---|
| gRPC (Protocol Buffers) | Міжсервісна взаємодія (East-West traffic). Бінарна серіалізація в 5–10 разів швидша за JSON, мультиплексування HTTP/2, сувора кодогенерація. | Високонавантажена мікросервісна мережа із жорсткими вимогами до затримок (SLA < 10ms). |
| GraphQL | Вирішує проблеми Over-fetching (зайві поля) та Under-fetching (N+1 HTTP-запитів до різних ресурсів). Клієнт сам запитує схему. | Складні клієнтські додатки (BFF, Web/Mobile), що вимагають агрегації сотень різнорідних сутностей. |
| WebSockets / RSocket | Двонапрямлений постійний повнодуплексний обмін повідомленнями з мінімальним оверхедом заголовків. | Real-time чати, котирування бірж, дашборди з живими графіками, IoT телеметрія. |
Сучасний стандарт обробки помилок: RFC 9457 (Problem Details)
У Spring Boot 3+ стандартизовано універсальний формат повідомлень про помилки REST API:
package com.example.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.net.URI;
import java.time.Instant;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ProblemDetail handleUserNotFound(UserNotFoundException ex) {
// Формування стандартного Problem Details (RFC 9457)
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(
HttpStatus.NOT_FOUND, ex.getMessage()
);
problemDetail.setTitle("User Not Found");
problemDetail.setType(URI.create("https://api.example.com/errors/not-found"));
problemDetail.setProperty("timestamp", Instant.now());
problemDetail.setProperty("errorCode", "USR-404");
return problemDetail;
}
}
Клієнт отримує стандартизований JSON:
{
"type": "https://api.example.com/errors/not-found",
"title": "User Not Found",
"status": 404,
"detail": "User with id 42 does not exist",
"instance": "/api/v1/users/42",
"timestamp": "2026-09-26T12:00:00Z",
"errorCode": "USR-404"
}
Highload-оптимізації REST на Java 21+
- Virtual Threads (Project Loom у Java 21):
- Увімкнення
spring.threads.virtual.enabled=trueпереводить вбудований Tomcat на віртуальні потоки. - Зникає потреба переписувати сервіси на реактивний стек (Spring WebFlux) лише заради утримання 50 000 паралельних I/O з’єднань.
- Увімкнення
- HTTP Caching з
ETag(ShallowEtagHeaderFilter):- Сервер розраховує MD5-хеш тіла відповіді та віддає заголовок
ETag: "686897696a7c76". - Клієнт при повторному запиті відправляє
If-None-Match: "686897696a7c76". - Сервер миттєво повертає
304 Not Modifiedз порожнім тілом, заощаджуючи вихідний трафік та час рендерингу.
- Сервер розраховує MD5-хеш тіла відповіді та віддає заголовок
🎯 Шпаргалка для інтерв’ю
30-секундна відповідь
REST — це архітектурний стиль побудови вебсервісів поверх протоколу HTTP, сформульований Роєм Філдінгом у 2000 році.
- Базується на 6 обмеженнях: Client-Server, Stateless, Cacheable, Layered System, Uniform Interface та Code on Demand.
- У центрі концепції знаходиться Ресурс, ідентифікований URI. Операції над ресурсами задаються дієсловами HTTP (
GET,POST,PUT,PATCH,DELETE), а стан передається через формати представлень (JSON/XML).- За моделлю зрілості Річардсона більшість production API знаходяться на Level 2 (використання ресурсів, HTTP-дієслів та статус-кодів). Справжній Level 3 вимагає підтримки HATEOAS.
4 каверзних питання з відповідями
-
Чи є REST протоколом або специфікацією? Відповідь: Ні, REST — це архітектурний стиль (набір принципів та обмежень). Протоколом є HTTP, поверх якого зазвичай реалізується REST. Стандартом чи специфікацією REST не є, тому розробники можуть адаптувати його під власні потреби (Pragmatic REST).
- Що таке Uniform Interface (Одноманітний інтерфейс) і з яких 4 частин він складається?
Відповідь: Це центральне обмеження REST, що відділяє архітектуру від інших стилів (RPC). Воно включає:
- Ідентифікацію ресурсів через URI.
- Маніпуляцію ресурсами через представлення (клієнт змінює ресурс, відправляючи JSON).
- Самоописувані повідомлення (наявність метаданих:
Content-Type, заголовки кешування). - HATEOAS (сервер передає гіперпосилання на доступні подальші переходи стану).
-
У чому різниця між RESTful API та звичайним HTTP API? Відповідь: HTTP API просто використовує протокол HTTP як транспорт для передачі даних (часто як RPC, Level 0–1 за Річардсоном). RESTful API суворо дотримується всіх 6 обмежень стилю REST, включно зі statelessness, семантикою HTTP-дієслів, кешуванням та гіпермедіа (HATEOAS).
- Коли REST архітектурно програє іншим підходам?
Відповідь:
- У міжсервісній взаємодії мікросервісів з високими навантаженнями — gRPC значно швидший через бінарний формат Protobuf та мультиплексування HTTP/2.
- При складній вибірці пов’язаних сутностей для мобільних клієнтів — GraphQL вирішує проблеми Over-fetching та множинних запитів.
- Для real-time даних — WebSockets та RSocket перевершують REST, усуваючи оверхед на постійне відкриття HTTP-з’єднань.
Червоні прапорці (чого категорично не можна говорити)
- ❌ «REST — це офіційний протокол передачі даних W3C» — це архітектурний стиль дисертації, а не протокол.
- ❌ «Метод GET можна використовувати для видалення запису з бази» — грубе порушення REST: метод
GETзобов’язаний бути безпечним (Safe) і не мати побічних ефектів. - ❌ «REST вимагає обов’язкового використання формату JSON» — REST не прив’язаний до JSON, він працює з будь-якими представленнями (XML, HTML, Protocol Buffers, MessagePack).
- ❌ «Сервер REST зберігає стан сесії користувача в оперативній пам’яті» — обмеження Stateless суворо забороняє зберігання клієнтської сесії на сервері.