6. RESTful API

6.2. Zasady identyfikowania zasobów

Projektując interfejs API w stylu REST dla aplikacji internetowej należy zadbać o właściwe skonstruowanie adresów identyfikujących poszczególne zasoby (ang. URI – Uniform Resource Identifiers), gdyż wpływa to na jego spójność i łatwość zrozumienia.

Poniżej zestawiono najważniejsze reguły i dobre praktyki, którymi powinien kierować się twórca aplikacji internetowej podczas projektowania adresów URI dla zasobów w RESTful API.

1. Unikalne i opisowe URI dla zasobów
  • Każdy zasób w API powinien mieć jednoznacznie identyfikowalny adres URI.
  • Adresy URI powinny być opisowe, aby użytkownicy API mogli łatwo zrozumieć, co jest reprezentowane przez dany adres.
  • Przykład:
    • Dla kolekcji użytkowników: /users
    • Dla konkretnego użytkownika: /users/{id} np. /users/123
2. Stosowanie rzeczowników zamiast czasowników
  • Poszczególne człony adresów URI powinny być rzeczownikami, które odnoszą się do reprezentowanych zasobów (np. users, products, orders), a nie do akcji (np. getUser, createOrder).
  • Akcje na zasobach (np. tworzenie, odczyt, aktualizacja, usuwanie) są definiowane za pomocą metod protokołu HTTP (np. GET, POST, PUT, DELETE), a nie w samym URI.
  • Przykład:
    • Poprawne: /products
    • Niepoprawne: /getProducts, /deleteUser
3. Hierarchiczna struktura URI
  • Adresy URI powinny być zorganizowane hierarchicznie, od ogółu do szczegółu, aby odzwierciedlały relacje między zasobami.
  • Przykład:
    • Kolekcja użytkowników: /users
    • Szczegóły konkretnego użytkownika: /users/{id} np. /users/123
    • Lista zamówień konkretnego użytkownika: /users/{id}/orders
4. Stosowanie liczby mnogiej dla kolekcji
  • Kolekcje zasobów powinny być nazwane w liczbie mnogiej, aby jasno wskazywać, że reprezentują zbiór elementów.
  • Przykład:
    • Poprawne: /users, /products, /orders
    • Niepoprawne: /user, /product, /order (mogą mylić się z pojedynczym zasobem)
5. Używanie identyfikatorów w URI
  • Dostęp do konkretnego zasobu w kolekcji powinien być możliwy za pośrednictwem unikalnego identyfikatora
  • Identyfikatory powinny być czytelne i proste (np. liczby lub unikalne ciągi alfanumeryczne)
  • Przykład:
    • Konkretne zasoby w kolekcji: /users/123, /products/45
6. Unikanie wielopoziomowej złożoności URI
  • Adresy URI powinny być możliwie krótkie i proste. Głębokie zagnieżdżenie (/users/123/orders/456/items/789) powinno być stosowane z rozwagą i tylko wtedy, gdy jest to uzasadnione logicznie.
  • Przykład:
    • Poprawne: /orders/456 (zakładając, że 456 (identyfikator zamówienia) wystarczająco identyfikuje zamówienie, włącznie z powiązaniem go z konkretnym użytkownikiem).
    • Niepoprawne: /users/123/orders/456 (uznać należy za niepoprawne, jeśli 456 wystarcza do pełnej identyfikacji zamówienia).
7. Wersjonowanie API
  • Projektując API warto przewidzieć jego długoterminowy rozwój. W szczególności może się okazać, że w przyszłości niezbędna będzie przebudowa aplikacji i idąca za tym zmiana formatów reprezentacji zasobów. Nie zawsze istnieje możliwość aktualizacji oprogramowania klienckiego, więc dobrze zaprojektowane API powinno przewidywać mechanizm jego wersjonowania. Jedną z możliwości jest umieszczenie umieszczenie identyfikatora wersji w adresie URI.
  • Wersjonowanie API powinno może być umieszczane w ścieżce URI lub w nagłówkach, ale nie w nazwach zasobów.
  • Przykład wersjonowania w URI:
    • Poprawne: /v1/users, /v2/products
    • Niepoprawne: /users_v1
8. Adresy URI zgodne z zasadami konstruowania adresów URL
  • Adresy URI powinny być zgodne z zasadami URL-friendly, co oznacza:
    • Używanie małych liter (unikaj wielkich liter)
    • Zamiast spacji stosowanie znaku myślnika (-) lub podkreślenia (_)
    • Unikanie znaków specjalnych (np. !@#$%^&*)
  • Przykład:
    • Poprawne: /user-profiles, /order-history
    • Niepoprawne: /UserProfiles, /order history
9. Używanie parametrów zapytania dla filtrów, sortowania i paginacji
  • Jeśli zasób wymaga dodatkowych informacji, takich jak filtrowanie, sortowanie czy paginacja, te operacje powinny być obsługiwane przez parametry zapytania (query parameters), a nie w samej ścieżce URI.
  • Przykład:
    • Paginacja: /users?page=2&limit=20
    • Filtrowanie: /products?category=electronics
    • Sortowanie: /products?sort=price&order=desc
10. Unikanie rozszerzeń plików w URI
  • URI powinny być czyste i nie zawierać rozszerzeń plików (np. .json, .xml), ponieważ format reprezentacji zasobu jest określany przez nagłówki protokołu HTTP (Accept), a nie przez adres URI.
  • Przykład:
    • Poprawne: /users
    • Niepoprawne: /users.json, /users.xml
11. Odpowiednie użycie kodów odpowiedzi protokołu HTTP
  • Adresy URI powinny być zaprojektowane tak, aby pozwalały na wykorzystanie standardowych kodów statusu HTTP (np. 200 OK, 201 Created, 404 Not Found, 500 Internal Server Error).
  • Przykładowe zachowanie:
    • Żądanie GET /users/123 dla istniejącego użytkownika powinno zwrócić 200 OK wraz z danymi użytkownika.
    • Jeśli użytkownik o ID 123 nie istnieje, odpowiedź powinna zostać odesłana z kodem 404 Not Found.
12. Spójność w całym API
  • Adresy URI powinny być spójne i jednolite w całym API, niezależnie od zasobu.
  • Przykład:
    • Jeśli URI dla użytkowników to /users/{id}, to URI dla produktów powinno być w podobnym formacie, np. /products/{id}.
13. Obsługa działań specyficznych dla zasobów
  • Działania specyficzne dla zasobów, które nie pasują do standardowych metod HTTP (np. akceptowanie zamówienia, resetowanie hasła), można obsługiwać za pomocą pod-ścieżek lub specjalnych zasobów.
  • Przykład:
    • Akceptowanie zamówienia: POST /orders/{id}/accept
    • Resetowanie hasła użytkownika: POST /users/{id}/reset-password
14. Dokumentacja URI
  • Wszystkie adresy URI powinny być dokładnie udokumentowane w API, aby użytkownicy wiedzieli, jak z nich korzystać.
  • Dokumentacja powinna zawierać:
    • Opis każdego URI
    • Przykłady żądań i odpowiedzi
    • Informacje o obsługiwanych metodach HTTP

Przykłady dobrze zaprojektowanych identyfikatorów zasobów w RESTful API
Metoda HTTPURIOpis
GET/usersPobierz listę wszystkich użytkowników.
GET/users/123Pobierz dane użytkownika o ID 123.
POST/usersUtwórz nowego użytkownika.
PUT/users/123Zaktualizuj dane użytkownika o ID 123.
DELETE/users/123Usuń użytkownika o ID 123.
GET/users/123/ordersPobierz zamówienia użytkownika o ID 123.
POST/ordersUtwórz nowe zamówienie.
GET/products?category=booksPobierz produkty z kategorii "books".