Szukaj…


Uwagi

W tej sekcji omówiono, czym jest reszta i dlaczego deweloper może chcieć z niej skorzystać.

Powinien również wymieniać wszelkie duże tematy w spoczynku i link do powiązanych tematów. Ponieważ Dokumentacja do odpoczynku jest nowa, konieczne może być utworzenie początkowych wersji tych powiązanych tematów.

Przegląd REST

REST oznacza RE prezentacyjny S tate T ransfer i został wymyślony przez Roy Fielding w jego pracy doktorskiej stylów architektury i projektowania sieci opartych na architekturze Software . W nim identyfikuje określone zasady architektury, takie jak:

  • Zasoby adresowalne: kluczowa abstrakcja informacji i danych w REST jest zasobem i każdy zasób musi być adresowalny przez URI.

  • Jednolity, ograniczony interfejs: użycie małego zestawu dobrze zdefiniowanych metod do manipulowania naszymi zasobami.

  • Zorientowane na reprezentację: zasób, do którego odnosi się jeden identyfikator URI, może mieć różne formaty, a różne platformy potrzebują różnych formatów, na przykład przeglądarki potrzebują HTML, JavaScript wymaga JSON, a aplikacje Java mogą wymagać XML, JSON, CSV, tekstu itp. Więc współpracujemy z usługami przy użyciu reprezentacji tej usługi.

  • Komunikuj się bezstanowo: aplikacje bezstanowe są łatwiejsze do skalowania.

  • Hypermedia jako silnik stanu aplikacji: pozwól, aby nasze formaty danych sterowały zmianami stanu w naszych aplikacjach.

Zestaw tych zasad architektonicznych nazywa się REST. Koncepcje REST są inspirowane koncepcją HTTP. Roy Fielding, który dał nam REST, jest również jednym z autorów specyfikacji HTTP.

Usługi sieciowe i usługi RESTful Web Services to usługi, które są narażone na dostęp do Internetu w celu zautomatyzowanego dostępu. Są to API online, które możemy wywołać z naszego kodu. Istnieją dwa rodzaje „dużych” usług sieciowych SOAP i REST.

Usługi sieci Web RESTful : usługi sieci Web napisane przy użyciu koncepcji architektonicznych REST nazywane są usługami sieci RESTful, które koncentrują się na zasobach systemowych i sposobie przesyłania stanu zasobów przez protokół HTTP do różnych klientów.

Ten dokument dotyczy wyłącznie usług sieciowych RESTful, więc nie będziemy wchodzić w szczegóły SOAP WS.

Podczas projektowania usług internetowych typu RESTful nie ma żadnych ścisłych zasad

  • Brak standardu protokołu
  • Brak standardowego kanału komunikacji
  • Brak standardu definicji usługi

Ale SOAP ma rygorystyczne zasady dla nich wszystkich. Wszystkie usługi sieciowe SOAP są zgodne ze specyfikacją SOAP, która określa, jaka powinna być każda usługa internetowa SOAP. Niniejsza specyfikacja jest opracowywana i zarządzana przez komitet, a jeśli SOAP WS nie przestrzega nawet jednej reguły, to z definicji nie jest SOAP.

Koncepcje RESTful Web Services

Istnieje kilka wskazówek, które należy wziąć pod uwagę przy projektowaniu / rozwijaniu interfejsu API RESTful:

  1. Lokalizacje oparte na zasobach / URI
  2. Właściwe stosowanie metod HTTP
  3. HATEOAS (Hypermedia jako silnik stanu aplikacji)

Głównym podejściem podczas opracowywania interfejsów API RESTful powinno być uczynienie interfejsu API „możliwie jak najbardziej RESTful”.

REST przez HTTP

REST to architektura niezależna od protokołu, zaproponowana przez Roy Fieldinga w jego rozprawie (rozdział 5 jest prezentacją REST), która uogólnia sprawdzoną koncepcję przeglądarek internetowych jako klientów w celu oddzielenia klientów w systemie rozproszonym od serwerów.

Aby usługa lub interfejs API był RESTful, musi spełniać określone ograniczenia, takie jak:

  • Klient-serwer
  • Bezpaństwowiec
  • Pamięć podręczna
  • System warstwowy
  • Jednolity interfejs
    • Identyfikacja zasobów
    • Reprezentacja zasobów
    • Wiadomości opisowe
    • Hipermedia

Poza ograniczeniami wymienionymi w rozprawie Fielding, w swoim blogu interfejsy API REST muszą być oparte na hipertekstie , Fielding wyjaśnił, że samo wywołanie usługi przez HTTP nie powoduje, że RESTful . Usługa powinna zatem również przestrzegać innych zasad, które streszczono w następujący sposób:

  • Interfejs API powinien być zgodny z podstawowym protokołem i nie może go naruszać. Chociaż REST jest używany przez HTTP przez większość czasu, nie jest on ograniczony do tego protokołu.

  • Silny nacisk na zasoby i ich prezentację za pośrednictwem mediów.

  • Klienci nie powinni mieć wstępnej wiedzy ani założeń na temat dostępnych zasobów lub ich zwróconego stanu ( „typowanego” zasobu ) w interfejsie API, ale powinni uczyć się ich w locie za pośrednictwem wydanych żądań i analizowanych odpowiedzi. Daje to serwerowi możliwość łatwego przenoszenia lub zmiany nazw zasobów bez przerywania implementacji klienta.

Model dojrzałości Richardsona

Model dojrzałości Richardsona jest sposobem na zastosowanie ograniczeń REST przez HTTP w celu uzyskania usług sieciowych RESTful.

Leonard Richardson podzielił aplikacje na te 4 warstwy:

  • Poziom 0: użycie HTTP do transportu
  • Poziom 1: użycie adresu URL do identyfikacji zasobów
  • Poziom 2: użycie czasowników i statusów HTTP do interakcji
  • Poziom 3: korzystanie z HATEOAS

Ponieważ nacisk kładziony jest na reprezentację stanu zasobu, zaleca się obsługę wielu reprezentacji tego samego zasobu. Reprezentacja może zatem przedstawiać przegląd stanu zasobu, podczas gdy inna zwraca pełne szczegóły tego samego zasobu.

Należy również zauważyć, że biorąc pod uwagę ograniczenia Fielding, interfejs API jest skutecznie RESTful dopiero po zaimplementowaniu 3. poziomu RMM .


Żądania i odpowiedzi HTTP

Żądanie HTTP to:

  • Czasownik (inaczej metoda), w większości przypadków GET , POST , PUT , DELETE lub PATCH
  • URL
  • Nagłówki (pary klucz-wartość)
  • Opcjonalnie ciało (inaczej ładunek, dane)

Odpowiedź HTTP to:

Charakterystyka czasowników HTTP:

  • Czasowniki, które mają ciało: POST , PUT , PATCH
  • Czasowniki, które muszą być bezpieczne (tzn. Nie mogą modyfikować zasobów): GET
  • Czasowniki, które muszą być idempotentne (tj. Nie mogą ponownie wpływać na zasoby, gdy są uruchamiane wiele razy): GET (nullipotent), PUT , DELETE
        body  safe  idempotent
GET      ✗     ✔     ✔
POST     ✔     ✗     ✗
PUT      ✔     ✗     ✔
DELETE   ✗     ✗     ✔
PATCH    ✔     ✗     ✗

W związku z tym czasowniki HTTP można porównać do funkcji CRUD :

Zauważ, że żądanie PUT prosi klientów o przesłanie całego zasobu ze zaktualizowanymi wartościami. Aby częściowo zaktualizować zasób, można użyć czasownika PATCH (zobacz Jak częściowo zaktualizować zasób? ).

Zwykłe stany odpowiedzi HTTP

Sukces

Przekierowanie

Błędy klienta

Błędy serwera

Notatki

Nic nie stoi na przeszkodzie, aby dodać ciało do błędnych odpowiedzi, aby wyjaśnienie klientów było wyraźniejsze. Na przykład 422 (NIEPRZETWARZANA PODMIOT) jest nieco niejasny: organ odpowiedzi powinien podać powód, dla którego podmiot nie mógł zostać przetworzony.


HATEOAS

Każdy zasób musi zapewniać hipermedialne zasoby, z którymi jest powiązany. Link składa się co najmniej z:

  • rel (na rel acji vel nazwa) opisuje zależność pomiędzy głównym źródłem i połączonej jednym (S)
  • href : adres URL kierowany do połączonych zasobów

Można również użyć dodatkowych atrybutów, aby pomóc w wycofaniu, negocjowaniu treści itp.

Cormac Mulhall wyjaśnia, że klient powinien zdecydować, którego czasownika HTTP użyć, na podstawie tego, co próbuje zrobić . W razie wątpliwości dokumentacja API powinna i tak pomóc w zrozumieniu dostępnych interakcji ze wszystkimi hipermediami.


Rodzaje mediów

Typy mediów pomagają w tworzeniu samoopisujących wiadomości. Odgrywają rolę umowy między klientami a serwerami, aby mogli wymieniać zasoby i hipermedie.

Chociaż application/json i application/xml są dość popularnymi typami mediów, nie zawierają dużej semantyki. Po prostu opisują ogólną składnię zastosowaną w dokumencie. Należy stosować bardziej wyspecjalizowane typy nośników, które obsługują wymagania HATEOAS (lub rozszerzyć je na typy nośników dostawców ), takie jak:

Klient informuje serwer, jakie typy mediów rozumie, dodając do swojego żądania nagłówek Accept , na przykład:

Accept: application/hal+json

Jeśli serwer nie jest w stanie wygenerować żądanego zasobu w takiej reprezentacji, zwraca wartość 406 (NIEDOPUSZCZALNA) . W przeciwnym razie dodaje typ nośnika w nagłówku Content-Type odpowiedzi zawierającej reprezentowany zasób, na przykład:

Content-Type: application/hal+json

Bezpaństwowy> stanowy

Dlaczego?

Serwer stanowy oznacza, że sesje klientów są przechowywane w lokalnej pamięci instancji serwera (prawie zawsze w sesjach serwera WWW). To zaczyna być problemem podczas próby skalowania w poziomie : jeśli ukryjesz kilka instancji serwera za modułem równoważenia obciążenia, jeśli jeden klient zostanie najpierw wysłany do instancji nr 1 podczas logowania, a następnie do instancji nr 2 podczas pobierania chronionego zasobu, na przykład , wówczas druga instancja obsłuży żądanie jako anonimowe, ponieważ sesja klienta została zapisana lokalnie w instancji nr 1 .

Znaleziono rozwiązania pozwalające rozwiązać ten problem (np. Poprzez konfigurację replikacji sesji i / lub sesji trwałej ), ale architektura REST proponuje inne podejście: po prostu nie wprowadzaj stanu serwera, uczyń go bezstanowym . Według Fieldinga :

Każde żądanie od klienta do serwera musi zawierać wszystkie informacje niezbędne do zrozumienia żądania i nie może korzystać z żadnego kontekstu przechowywanego na serwerze. Stan sesji jest zatem w całości przechowywany na kliencie.

Innymi słowy, żądanie musi być obsługiwane dokładnie w ten sam sposób, niezależnie od tego, czy jest wysyłane do instancji nr 1 czy instancji nr 2 . Dlatego aplikacje bezstanowe są uważane za łatwiejsze do skalowania .

W jaki sposób?

Powszechnym podejściem jest uwierzytelnianie oparte na tokenach , szczególnie w przypadku modnych tokenów internetowych JSON . Zauważ, że JWT wciąż ma pewne problemy, szczególnie dotyczące unieważnienia i automatycznego przedłużania ważności (tj. Funkcja zapamiętaj mnie ).

Notatki dodatkowe

Używanie plików cookie lub nagłówków (lub czegokolwiek innego) nie ma nic wspólnego z tym, czy serwer jest stanowy czy bezstanowy: są to tylko media, które są tutaj używane do transportu tokenów (identyfikator sesji dla serwerów stanowych, JWT itp.), Nic więcej.

Podczas relaksującego API jest używany tylko przez przeglądarki ( HttpOnly i bezpieczna ) Ciasteczka mogą być bardzo wygodne, ponieważ przeglądarki będą automatycznie dołącza je do żądań wychodzących. Warto wspomnieć, że jeśli zdecydujesz się na pliki cookie, pamiętaj o CSRF (dobrym sposobem na zapobieganie temu jest generowanie i wysyłanie przez klientów tej samej unikalnej tajnej wartości zarówno w pliku cookie, jak i niestandardowym nagłówku HTTP ).


Buforowalny interfejs API z żądaniami warunkowymi

Z nagłówkiem Last-Modified

Serwer może dostarczyć nagłówek daty Last-Modified odpowiedzi zawierającej zasoby, które można buforować. Klienci powinni następnie przechowywać tę datę razem z zasobem.

Teraz za każdym razem, gdy klienci proszą API o odczytanie zasobu, mogą dodać do swoich żądań nagłówek If-Modified-Since zawierający najnowszą datę ostatniej Last-Modified którą otrzymali i zapisali. Serwer musi następnie porównać nagłówek żądania i faktyczną datę ostatniej modyfikacji zasobu. Jeśli są one równe, serwer zwraca 304 (NIE ZMODYFIKOWANY) z pustą treścią: klient żądający powinien użyć aktualnie buforowanego zasobu, który ma.

Ponadto, gdy klienci proszą API o aktualizację zasobu (tj. Czasownikiem niebezpiecznym), mogą dodać nagłówek If-Unmodified-Since . Pomaga to w radzeniu sobie z warunkami wyścigu: jeśli nagłówek i data ostatniej modyfikacji są różne, serwer zwraca 412 (AWARIA WSTĘPNA) . Klient powinien następnie odczytać nowy stan zasobu przed ponowną próbą zmodyfikowania zasobu.

Z nagłówkiem ETag

ETag (znacznik encji) to identyfikator określonego stanu zasobu. Może to być skrót MD5 zasobu dla silnego sprawdzania poprawności lub specyficzny dla domeny identyfikator słabego sprawdzania poprawności .

Zasadniczo proces jest taki sam, jak w przypadku nagłówka Last-Modified : serwer dostarcza nagłówek ETag do odpowiedzi zawierających zasoby, które można buforować, a klienci powinni następnie przechowywać ten identyfikator razem z zasobem.

Następnie klienci dostarczają nagłówek If-None-Match gdy chcą odczytać zasób, zawierający najnowszy znacznik ETag, który otrzymali i zapisali. Serwer może teraz zwrócić 304 (NIEZMODYFIKOWANY), jeśli nagłówek odpowiada faktycznemu znacznikowi ET zasobu.

Ponownie, klienci mogą dostarczyć nagłówek If-Match gdy chcą zmodyfikować zasób, a serwer musi zwrócić 412 (WSTĘP NIEUDANY), jeśli podany ETag nie pasuje do rzeczywistego.

Dodatkowe uwagi

ETag> data

Jeśli klienci podają w swoich żądaniach zarówno datę, jak i znacznik ETag, datę należy zignorować. Z RFC 7232 ( tu i tutaj ):

Odbiorca MUSI zignorować If-Modified-Since / If-Unmodified-Since jeśli żądanie zawiera pole nagłówka If-None-Match / If-Match ; warunek w If-None-Match / w If-Match jest uważany za bardziej dokładny zamiennik warunku w If-Modified-Since / If-Unmodified-Since If-Modified-Since If-Unmodified-Since oraz oba są łączone wyłącznie w celu współpracy ze starszymi pośrednikami które mogą nie implementować If-None-Match / If-Match .

Płytkie ETagi

Ponadto, chociaż jest całkiem oczywiste, że ostatnie modyfikowane daty są zachowywane wraz z zasobami po stronie serwera, w ETag dostępnych jest kilka podejść .

Typowym podejściem jest wdrażanie płytkich znaczników ET: serwer przetwarza żądanie tak, jakby nie podano nagłówków warunkowych, ale tylko na samym końcu generuje znacznik ETag odpowiedzi, którą ma zamiar zwrócić (np. Mieszając go), i porównuje z dostarczonym. Jest to stosunkowo łatwe do wdrożenia, ponieważ potrzebny jest tylko przechwytywacz HTTP (a wiele implementacji już istnieje w zależności od serwera). To powiedziawszy, warto wspomnieć, że takie podejście pozwoli zaoszczędzić przepustowość, ale nie wydajność serwera :

Głębsza implementacja mechanizmu ETag może potencjalnie przynieść znacznie większe korzyści - takie jak obsługa niektórych żądań z pamięci podręcznej i wcale nie konieczność wykonywania obliczeń - ale implementacja z pewnością nie byłaby tak prosta, ani tak łatwa w podłączeniu, jak płytkie podejście opisane tutaj.


Częste pułapki

Dlaczego nie powinienem umieszczać czasowników w adresach URL?

HTTP nie jest RPC : tym, co znacznie różni HTTP od RPC, jest to, że żądania są kierowane do zasobów . W końcu URL oznacza Uniform Resource Locator, a URL to URI : Uniden Resource Idenfitier. Adres URL jest skierowany na zasób, z którym chcesz się uporać , metoda HTTP wskazuje, co chcesz z nim zrobić . Metody HTTP są również znane jako czasowniki : czasowniki w adresach URL nie mają wtedy sensu. Pamiętaj, że relacje HATEOAS nie powinny również zawierać czasowników, ponieważ linki również kierują zasoby.

Jak częściowo zaktualizować zasób?

Ponieważ żądania PUT proszą klientów o przesłanie całego zasobu ze zaktualizowanymi wartościami, PUT /users/123 nie może być użyty na przykład do aktualizacji e-maila użytkownika. Jak wyjaśnił William Durand w Please. Nie łataj jak idiota. , dostępnych jest kilka rozwiązań zgodnych z REST:

  • Ujawnij właściwości zasobu i użyj metody PUT , aby wysłać zaktualizowaną wartość, ponieważ specyfikacja PUT stwierdza, że częściowe aktualizacje treści są możliwe poprzez celowanie w osobno zidentyfikowany zasób ze stanem pokrywającym się z częścią większego zasobu :
PUT https://example.com/api/v1.2/users/123/email
body:
  new.email@example.com
  • Użyj żądania PATCH które zawiera zestaw instrukcji opisujących, w jaki sposób należy zmodyfikować zasób (np. Następujące poprawki JSON ):
PATCH https://example.com/api/v1.2/users/123
body:
  [
    { "op": "replace", "path": "/email", "value": "new.email@example.com" }
  ]
PATCH https://example.com/api/v1.2/users/123
body:
  {
    "email": "new.email@example.com"
  }

Co z działaniami, które nie pasują do świata operacji CRUD?

Cytując Vinay Sahni w najlepszych praktykach dotyczących projektowania pragmatycznego interfejsu API RESTful :

To tutaj rzeczy mogą się rozmazać. Istnieje wiele podejść:

  1. Zmień strukturę akcji, aby wyglądała jak pole zasobu. Działa to, jeśli akcja nie przyjmuje parametrów. Na przykład akcja aktywacji może być odwzorowana na pole activated logicznie i zaktualizowana za pomocą PATCHA do zasobu.

  2. Traktuj to jak pod-zasób z zasadami RESTful. Na przykład interfejs API GitHub pozwala oznaczyć gwiazdkę za pomocą PUT /gists/:id/star i unstar za pomocą DELETE /gists/:id/star .

  3. Czasami naprawdę nie ma sposobu, aby odwzorować akcję na rozsądną strukturę RESTful. Na przykład wyszukiwanie wielu zasobów nie ma sensu, aby stosować je do punktu końcowego określonego zasobu. W takim przypadku /search ma sens, nawet jeśli nie jest zasobem. To jest OK - po prostu rób to, co jest właściwe z punktu widzenia konsumenta interfejsu API i upewnij się, że jest to dobrze udokumentowane, aby uniknąć nieporozumień.


Wspólne praktyki

  • API jest udokumentowane. Dostępne są narzędzia pomocne w budowaniu dokumentacji, np. Swagger lub Spring REST Docs .

  • Interfejs API jest wersjonowany za pomocą nagłówków lub adresu URL:

https://example.com/api/v1.2/blogs/123/articles
                        ^^^^
https://example.com/api/v1.2/blogs/123/articles
                             ^^^^^     ^^^^^^^^
  • Adresy URL używają wielkości kebab (słowa są pisane małymi literami i rozdzielane myślnikiem):
https://example.com/api/v1.2/quotation-requests
                             ^^^^^^^^^^^^^^^^^^
{
  ...,
  _links: {
    ...,
    self: { href: "https://example.com/api/v1.2/blogs/123/articles/789" }
    ^^^^
  }
}
  • Relacje HATEOAS używają lowerCamelCase (słowa są pisane małymi literami, a następnie pisane wielkimi literami, z wyjątkiem pierwszej, a spacje są pomijane), aby umożliwić klientom JavaScript stosowanie notacji kropkowej przy jednoczesnym przestrzeganiu konwencji nazewnictwa JavaScript podczas uzyskiwania dostępu do linków:
{
  ...,
  _links: {
    ...,
    firstPage: { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=1&pageSize=25" }
    ^^^^^^^^^
  }
}

Zarządzanie blogami za pomocą interfejsu API RESTful HTTP

Poniższe przykłady używają HAL do wyrażenia HATEOAS i wykorzystują:

  • CURIE (kompaktowy URI): służy do udostępniania linków do dokumentacji API
  • Szablony URI : URI, który zawiera parametry, które muszą zostać podstawione przed rozwiązaniem URI

Uzyskaj blog 123

Żądanie

GET https://example.com/api/v1.2/blogs/123
headers:
  Accept: application/hal+json

Odpowiedź

status: 200 (OK)
headers:
  Content-Type: application/hal+json
body:
  {
    "id": 123,
    "title": "The blog title",
    "description": "The blog description",
    "_links": {
      "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
      "self": { "href": "https://example.com/api/v1.2/blogs/123" },
      "doc:articles": { "href": "https://example.com/api/v1.2/blogs/123/articles{?pageIndex,pageSize}", "templated": true }
    }
  }

Utwórz nowy artykuł na blogu 123

Żądanie

POST https://example.com/api/v1.2/blogs/123/articles
headers:
  Content-Type: application/json
  Accept: application/hal+json
  X-Access-Token: XYZ
body:
  {
    "title": "The title 2",
    "content": "The content 2"
  }

Odpowiedź

status: 201 (CREATED)
headers:
  Content-Type: application/hal+json
body:
  {
    "id": 789,
    "title": "The title 2",
    "content": "The content 2",
    "_links": {
      "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
      "self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
      "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
      "doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
    }
  }

Uzyskaj artykuł 789 bloga 123

Żądanie

GET https://example.com/api/v1.2/blogs/123/articles/789
headers:
  Accept: application/hal+json

Odpowiedź

status: 200 (OK)
headers:
  Content-Type: application/hal+json
body:
  {
    "id": 789,
    "title": "The title 2",
    "content": "The content 2",
    "_links": {
      "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
      "self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
      "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
      "doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
    }
  }

Uzyskaj czwartą stronę z 25 artykułów na blogu 123

Żądanie

GET https://example.com/api/v1.2/blogs/123/articles?pageIndex=4&pageSize=25
headers:
  Accept: application/hal+json

Odpowiedź

status: 200 (OK)
headers:
  Content-Type: application/hal+json
body:
  {
    "pageIndex": 4,
    "pageSize": 25,
    "totalPages": 26,
    "totalArticles": 648,
    "_link": {
      "firstPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=1&pageSize=25" },
      "previousPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=3&pageSize=25" },
      "self": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=4&pageSize=25" },
      "nextPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=5&pageSize=25" },
      "lastPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=26&pageSize=25" }
    },
    "_embedded": [
      {
        ...
      }, {
        "id": 456,
        "title": "The title 1",
        "content": "The content 1",
        "_links": {
          "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
          "self": { "href": "https://example.com/api/v1.2/blogs/123/articles/456" },
          "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
          "doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/456/comments{?pageIndex,pageSize}", "templated": true }
        }
      }, {
        "id": 789,
        "title": "The title 2",
        "content": "The content 2",
        "_links": {
          "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
          "self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
          "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
          "doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
        }
      }, {
        ...
      }
    ]
  }

Zaktualizuj artykuł 789 blogu 123

Żądanie

PUT https://example.com/api/v1.2/blogs/123/articles/789
headers:
  Content-Type: application/json
  Accept: application/hal+json
  X-Access-Token: XYZ
body:
  {
    "id": 789,
    "title": "The title 2 updated",
    "content": "The content 2 updated"
  }

Odpowiedź

status: 200 (OK)
headers:
  Content-Type: application/hal+json
body:
  {
    "id": 789,
    "title": "The title 2 updated",
    "content": "The content 2 updated",
    "_links": {
      "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
      "self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
      "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
      "doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
    }
  }

Notatki

  • Identyfikator używany do identyfikacji zasobu do aktualizacji to ten znajdujący się w adresie URL : ten w treści (jeśli istnieje) musi zostać cicho zignorowany.
  • Gdy żądanie PUT aktualizuje cały zasób, jeśli żadna content nie zostałaby wysłana, należy ją usunąć z utrwalonego zasobu.

Usuń artykuł 789 z blogu 123

Żądanie

DELETE https://example.com/api/v1.2/blogs/123/articles/789
headers:
  Accept: application/hal+json
  X-Access-Token: XYZ

Odpowiedź

status: 204 (NO CONTENT)
headers:
  Content-Type: application/hal+json
body:
  {
    "_links": {
      "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
      "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" }
    }
  }

Naruszenie REST

<stock>
    <add>
        <item>
            <name>Milk</name>
            <quantity>2</quantity>
        </item>
    </add>
</stock>

Umieszczenie tego ciała w zasobach takich jak /stocks/123 narusza ideę REST. Chociaż to ciało jest put i zawiera wszystkie niezbędne informacje, zawiera również wywołanie metody, które można add gdzieś, gdy ciało jest przetwarzane. Po REST należy opublikować item w /stocks/123/items/ .



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow