HTTP
HTTP dla interfejsów API
Szukaj…
Uwagi
Interfejsy API HTTP używają szerokiego spektrum czasowników HTTP i zwykle zwracają odpowiedzi JSON lub XML.
Utwórz zasób
Nie wszyscy zgadzają się co do najbardziej semantycznie poprawnej metody tworzenia zasobów. W związku z tym Twój interfejs API może akceptować POST
lub PUT
, albo jedno i drugie.
Serwer powinien odpowiedzieć za pomocą 201 Created
jeśli zasób został pomyślnie utworzony. Wybierz najbardziej odpowiedni kod błędu, jeśli nie był.
Na przykład, jeśli udostępnisz interfejs API do tworzenia akt pracowników, żądanie / odpowiedź może wyglądać następująco:
POST /employees HTTP/1.1
Host: example.com
Content-Type: application/json
{
"name": "Charlie Smith",
"age": 38,
"job_title": "Software Developer",
"salary": 54895.00
}
HTTP/1.1 201 Created
Location: /employees/1/charlie-smith
Content-Type: application/json
{
"employee": {
"name": "Charlie Smith",
"age": 38,
"job_title": "Software Developer",
"salary": 54895.00
"links": [
{
"uri": "/employees/1/charlie-smith",
"rel": "self",
"method": "GET"
},
{
"uri": "/employees/1/charlie-smith",
"rel": "delete",
"method": "DELETE"
},
{
"uri": "/employees/1/charlie-smith",
"rel": "edit",
"method": "PATCH"
}
]
},
"links": [
{
"uri": "/employees",
"rel": "create",
"method": "POST"
}
]
}
Uwzględnienie links
pól JSON w odpowiedzi umożliwia klientowi dostęp do zasobu związanego z nowym zasobem i aplikacją jako całością, bez konieczności wcześniejszego poznania ich identyfikatorów URI lub metod.
Edytuj zasób
Edycja lub aktualizacja zasobu jest częstym celem interfejsów API. Edycji można dokonać, wysyłając POST
, PUT
lub PATCH
do odpowiedniego zasobu. Chociaż POST
może dołączać dane do istniejącej reprezentacji zasobu, zaleca się użycie PUT
lub PATCH
ponieważ przekazują one bardziej wyraźny semantyczny.
Twój serwer powinien odpowiedzieć 200 OK
jeśli aktualizacja została wykonana, lub 202 Accepted
jeśli nie została jeszcze zastosowana. Wybierz najbardziej odpowiedni kod błędu, jeśli nie można go uzupełnić.
Pełne aktualizacje
PUT
ma semantykę zastępowania bieżącej reprezentacji ładunkiem zawartym w żądaniu. Jeśli ładunek nie jest tego samego typu reprezentacji, co bieżąca reprezentacja zasobu do aktualizacji, serwer może zdecydować, które podejście wybrać. RFC7231 określa, że serwer może albo
- Ponownie skonfiguruj zasób docelowy, aby odzwierciedlić nowy typ nośnika
- Przekształć reprezentację PUT do formatu zgodnego z formatem zasobu przed zapisaniem go jako nowego stanu zasobów
- Odrzuć żądanie z
415 Unsupported Media Type
odpowiedzią415 Unsupported Media Type
wskazującą, że zasób docelowy jest ograniczony do określonego (zestawu) typów nośników.
Zasób podstawowy zawierający reprezentację JSON HAL, taki jak ...
{
"name": "Charlie Smith",
"age": 39,
"job_title": "Software Developer",
"_links": {
"self": { "href": "/users/1234" },
"employee": { "href": "http://www.acmee.com" },
"curies": [{ "name": "ea", "href": "http://www.acmee.com/docs/rels/{rel}", templated": true}],
"ea:admin": [
"href": "/admin/2",
"title": "Admin"
]
}
}
... może otrzymać takie żądanie aktualizacji
PUT /users/1234 HTTP/1.1
Host: http://www.acmee.com
Content-Type: "application/json; charset=utf-8"
Content-Length: 85
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
{
"name": "Charlie Gold-Smith",
"age": 40,
"job_title": "Senior Software Developer"
}
Serwer może teraz zastąpić stan zasobu podaną treścią żądania, a także zmienić typ zawartości z application/hal+json
na application/json
lub przekonwertować ładunek JSON na reprezentację JSON HAL, a następnie zastąpić zawartość zasobu z transformowanym lub odrzuć żądanie aktualizacji z powodu niewłaściwego typu nośnika z odpowiedzią 415 Unsupported Media Type
.
Istnieje różnica między bezpośrednim zastąpieniem treści lub pierwszą transformacją reprezentacji do zdefiniowanego modelu reprezentacji, a następnie zastąpieniem istniejącej treści transformowaną. Kolejne żądanie GET
zwróci następującą odpowiedź w przypadku bezpośredniego zastąpienia:
GET /users/1234 HTTP/1.1
Host: http://www.acmee.com
Accept-Encoding: gzip, deflate
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
ETag: "e0023aa4e"
{
"name": "Charlie Gold-Smith",
"age": 40,
"job_title": "Senior Software Developer"
}
podczas gdy transformacja, a następnie zastąpienie, zwróci następującą reprezentację:
GET /users/1234 HTTP/1.1
Host: http://www.acmee.com
Accept-Encoding: gzip, deflate
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
ETag: e0023aa4e
{
"name": "Charlie Gold-Smith",
"age": 40,
"job_title": "Senior Software Developer",
"_links": {
"self": { "href": "/users/1234" },
"employee": { "href": "http://www.acmee.com" },
"curies": [{ "name": "ea", "href": "http://www.acmee.com/docs/rels/{rel}", templated": true}],
"ea:admin": [
"href": "/admin/2",
"title": "Admin"
]
}
}
Skutki uboczne
Pamiętaj, że PUT
może PUT
skutki uboczne, chociaż jest zdefiniowane jako idempotentna operacja! Jest to udokumentowane w RFC7231 jako
Żądanie PUT zastosowane do zasobu docelowego może mieć skutki uboczne dla innych zasobów . Na przykład artykuł może mieć identyfikator URI służący do identyfikacji „bieżącej wersji” (zasób), który jest niezależny od identyfikatorów URI identyfikujących każdą konkretną wersję (różne zasoby, które w jednym punkcie miały ten sam stan co zasób bieżącej wersji). Pomyślne żądanie PUT dotyczące identyfikatora URI „bieżącej wersji” może zatem oprócz nowego stanu zasobu docelowego utworzyć nowy zasób wersji, a także może spowodować dodanie łączy między powiązanymi zasobami.
Tworzenie dodatkowych wpisów w dzienniku zwykle nie jest uważane za efekt uboczny, ponieważ z pewnością nie jest to ogólnie stan zasobów.
Częściowe aktualizacje
RFC7231 wspomina o częściowych aktualizacjach:
Częściowe aktualizacje treści są możliwe poprzez celowanie w osobno zidentyfikowany zasób ze stanem, który nakłada się na część większego zasobu lub przez zastosowanie innej metody, która została specjalnie zdefiniowana dla częściowych aktualizacji (na przykład metoda PATCH zdefiniowana w RFC5789 ).
Częściowe aktualizacje można zatem wykonać w dwóch wariantach:
- Niech zasób osadzi wiele mniejszych zasobów podrzędnych i zaktualizuj tylko odpowiedni podrzędny zasób zamiast pełnego zasobu za pośrednictwem
PUT
- Za pomocą
PATCH
i poinstruuj serwer, co należy zaktualizować
Częściowa aktualizacja ze nakładającym się stanem
Jeśli reprezentacja użytkownika wymaga częściowej aktualizacji z powodu przeniesienia użytkownika do innej lokalizacji, zamiast bezpośredniej aktualizacji użytkownika, powiązany zasób powinien zostać zaktualizowany bezpośrednio, co odzwierciedla częściową aktualizację reprezentacji użytkownika.
Przed przeniesieniem użytkownik miał następującą reprezentację
GET /users/1234 HTTP/1.1
Host: http://www.acmee.com
Accept: application/hal+json; charset=utf-8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
ETag: "e0023aa4e"
{
"name": "Charlie Gold-Smith",
"age": 40,
"job_title": "Senior Software Developer",
"_links": {
"self": { "href": "/users/1234" },
"employee": { "href": "http://www.acmee.com" },
"curies": [{ "name": "ea", "href": "http://www.acmee.com/docs/rels/{rel}", templated": true}],
"ea:admin": [
"href": "/admin/2",
"title": "Admin"
]
},
"_embedded": {
"ea:address": {
"street": "Terrace Drive, Central Park",
"zip": "NY 10024"
"city": "New York",
"country": "United States of America",
"_links": {
"self": { "href": "/address/abc" },
"google_maps": { "href": "http://maps.google.com/?ll=40.7739166,-73.970176" }
}
}
}
}
Gdy użytkownik przenosi się do nowej lokalizacji, aktualizuje informacje o swojej lokalizacji w następujący sposób:
PUT /address/abc HTTP/1.1
Host: http://www.acmee.com
Content-Type: "application/json; charset=utf-8"
Content-Length: 109
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
{
"street": "Standford Ave",
"zip": "CA 94306",
"city": "Pablo Alto",
"country": "United States of America"
}
Dzięki semantyce transformacji przed zamianą dla niedopasowanego typu nośnika między istniejącym zasobem adresu a zasobem w żądaniu, jak opisano powyżej, zasób adresu jest teraz aktualizowany, co powoduje, że przy kolejnym żądaniu GET
zasobu użytkownika nowy adres dla użytkownika jest zwracany.
GET /users/1234 HTTP/1.1
Host: http://www.acmee.com
Accept: application/hal+json; charset=utf-8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
ETag: "e0023aa4e"
{
"name": "Charlie Gold-Smith",
"age": 40,
"job_title": "Senior Software Developer",
"_links": {
"self": { "href": "/users/1234" },
"employee": { "href": "http://www.acmee.com" },
"curies": [{ "name": "ea", "href": "http://www.acmee.com/docs/rels/{rel}", templated": true}],
"ea:admin": [
"href": "/admin/2",
"title": "Admin"
]
},
"_embedded": {
"ea:address": {
"street": "Standford Ave",
"zip": "CA 94306",
"city": "Pablo Alto",
"country": "United States of America"
"_links": {
"self": { "href": "/address/abc" },
"google_maps": { "href": "http://maps.google.com/?ll=37.4241311,-122.1524475" }
}
}
}
}
Patchowanie częściowych danych
PATCH
jest zdefiniowany w RFC5789 i nie jest bezpośrednio częścią specyfikacji HTTP jako takiej. Powszechnym błędem jest to, że wysyłanie tylko pól, które powinny być częściowo zaktualizowane, wystarczy w żądaniu PATCH
. W związku z tym w specyfikacji podano
Metoda PATCH wymaga zastosowania zestawu zmian opisanych w encji żądania do zasobu określonego przez identyfikator URI żądania. Zestaw zmian jest reprezentowany w formacie zwanym „dokumentem poprawki” identyfikowanym przez typ nośnika.
Oznacza to, że klient powinien obliczyć niezbędne kroki potrzebne do transformacji zasobu ze stanu A do stanu B i wysłać te instrukcje do serwera.
Popularnym typem nośnika opartym na JSON do łatania jest JSON Patch .
Jeśli wiek i stanowisko naszego przykładowego użytkownika zmieni się, a dodatkowe pole reprezentujące dochód użytkownika powinno zostać dodane, częściowa aktualizacja za pomocą PATCH
za pomocą JSON Patch może wyglądać następująco:
PATCH /users/1234 HTTP/1.1
Host: http://www.acmee.com
Content-Type: application/json-patch+json; charset=utf-8
Content-Length: 188
Accept: application/json
If-Match: "e0023aa4e"
[
{ "op": "replace", "path": "/age", "value": 40 },
{ "op": "replace", "path": "/job_title", "value": "Senior Software Developer" },
{ "op": "add", "path": "/salery", "value": 63985.00 }
]
PATCH
może aktualizować wiele zasobów jednocześnie i wymaga atomowego zastosowania zmian, co oznacza, że albo wszystkie zmiany muszą zostać zastosowane, albo wcale, co nakłada transakcyjne obciążenie na implementator API.
Pomyślna aktualizacja może zwrócić coś takiego
HTTP/1.1 200 OK
Location: /users/1234
Content-Type: application/json
ETag: "df00eb258"
{
"name": "Charlie Smith",
"age": 40,
"job_title": "Senior Software Developer",
"salary": 63985.00
}
chociaż nie jest ograniczony tylko do 200 OK
kodów odpowiedzi 200 OK
.
Aby zapobiec aktualizacjom pomiędzy (zmiany dokonane pomiędzy poprzednim ETag
stanu reprezentacji a aktualizacją) należy ETag
, If-Match
lub If-Unmodified-Since
.
Obsługa błędów
Specyfikacja PATCH
zaleca następującą obsługę błędów:
Rodzaj | Kod błędu |
---|---|
Zniekształcony dokument poprawki | 400 Bad Request |
Nieobsługiwany dokument poprawki | 415 Unsupported Media Type |
Żądanie nieprzetworzone, tj. Jeśli udział stałby się nieważny przez zastosowanie łatki | 422 Unprocessable Entity |
Nie znaleziono zasobów | 404 Not Found |
Stan konfliktu, tj. Zmiana nazwy (przeniesienie) pola, które nie istnieje | 409 Conflict |
Sprzeczna modyfikacja, tj. Jeśli klient używa nagłówka If-Match lub If-Unmodified-Since którego sprawdzanie nie powiodło się. Jeśli warunek wstępny nie był dostępny, należy zwrócić ten drugi kod błędu | 412 Precondition Failed lub 409 Conflict |
Jednoczesna modyfikacja, tzn. Czy żądanie musi zostać zastosowane przed akceptacją kolejnych żądań PATCH | 409 Conflict |
Usuń zasób
Innym powszechnym zastosowaniem interfejsów API HTTP jest usunięcie istniejącego zasobu. Zwykle należy tego dokonać przy użyciu żądań DELETE
.
Jeśli usunięcie się powiodło, serwer powinien zwrócić 200 OK
; odpowiedni kod błędu, jeśli nie był.
Jeśli nasz pracownik Charlie Smith opuścił firmę, a my chcemy teraz usunąć jego dane, może to wyglądać tak:
DELETE /employees/1/charlie-smith HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-Type: application/json
{
'links': [
{
'uri': '/employees',
'rel': 'create',
'method': 'POST'
}
]
}
Lista zasobów
Ostatnim powszechnym zastosowaniem interfejsów API HTTP jest uzyskanie listy istniejących zasobów na serwerze. Takie listy należy uzyskać za pomocą żądań GET
, ponieważ pobierają one tylko dane.
Serwer powinien zwrócić wartość 200 OK
jeśli może dostarczyć listę, lub odpowiedni kod błędu, jeśli nie.
Lista naszych pracowników może więc wyglądać następująco:
GET /employees HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-Type: application/json
{
'employees': [
{
'name': 'Charlie Smith',
'age': 39,
'job_title': 'Software Developer',
'salary': 63985.00
'links': [
{
'uri': '/employees/1/charlie-smith',
'rel': 'self',
'method': 'GET'
},
{
'uri': '/employees/1/charlie-smith',
'rel': 'delete',
'method': 'DELETE'
},
{
'uri': '/employees/1/charlie-smith',
'rel': 'edit',
'method': 'PATCH'
}
]
},
{
'name': 'Donna Prima',
'age': 30,
'job_title': 'QA Tester',
'salary': 77095.00
'links': [
{
'uri': '/employees/2/donna-prima',
'rel': 'self',
'method': 'GET'
},
{
'uri': '/employees/2/donna-prima',
'rel': 'delete',
'method': 'DELETE'
},
{
'uri': '/employees/2/donna-prima',
'rel': 'edit',
'method': 'PATCH'
}
]
}
],
'links': [
{
'uri': '/employees/new',
'rel': 'create',
'method': 'PUT'
}
]
}