Próbuję ustalić, jak zaprojektować spokojne adresy URL. Jestem zwolennikiem spokojnego podejścia do używania adresów URL z rzeczownikami, a nie czasownikami, nie rozumiem, jak to zrobić.
Tworzymy usługę wdrożenia kalkulatora finansowego. Kalkulator pobiera kilka parametrów, które prześlemy za pomocą pliku CSV. Przypadki użycia obejmowałyby:
- Prześlij nowe parametry
- Uzyskaj najnowsze parametry
- Uzyskaj parametry dla danej daty biznesowej
- Uaktywnij zestaw parametrów
- Sprawdź poprawność zestawu parametrów
Rozumiem, że spokojnym podejściem byłoby mieć następujące adresy URL:
/parameters
/parameters/12-23-2009
Pierwsze trzy przypadki użycia można osiągnąć za pomocą:
- POST, w którym dołączasz plik parametrów do żądania postu
- POBIERZ pierwszy adres URL
- Uzyskaj drugi adres URL
Ale w jaki sposób robisz czwarty i piąty przypadek użycia bez czasownika? Czy nie potrzebujesz adresów URL takich jak:
/parameters/ID/activate
/parameters/ID/validate
??
rest
restful-url
Marcus Leon
źródło
źródło
Odpowiedzi:
Być może coś takiego:
źródło
POST
jest OK, jeśli musisz wykonać „procedurę”, taką jak weryfikacja parametrów za każdym razem, gdy wysyłasz żądanie. Ale modyfikując stan (aplikacji) zasobu, faktycznie aktualizujesz istniejący zasób, nie tworzysz nowego zasobu ani nie wysyłasz żądania przetwarzania.POST
vsPUT
nie jest dokładnie tak, jakinsert
vsupdate
.PUT
aktualizuje zasób odpowiadający danej ścieżce lub tworzy nowy zasób odpowiadający danej ścieżce.POST
tworzy gdzieś nowy zasób. Na przykładPUT /blog/posts/3/comments/5
zaktualizuje odpowiedni komentarz, a jednocześniePOST /blog/posts/3/comments
utworzy nowycomment
zasób (i powinien zwrócić ścieżkę do nowego zasobu w odpowiedzi).PUT
jest idempotentna, podczas gdyPOST
nie jest. Zwykle powinieneś nakładać jak najwięcej ograniczeń na to, co zapewniasz w wyniku, jak to możliwe. Trzymanie sięPUT
daje więcej informacji klientowi usługi.Ogólne zasady dobrego projektowania URI:
/resource
czy/resource/
; utwórz 301 przekierowań z tego, którego nie używasz(Uwaga: nie powiedziałem „projekt RESTful URI”; URI są zasadniczo nieprzejrzyste w REST.)
Ogólne zasady wyboru metody HTTP:
Ogólne zasady projektowania usług internetowych za pomocą HTTP:
201 Created
po utworzeniu zasobu; zasób musi istnieć w momencie wysłania odpowiedzi202 Accepted
po pomyślnym wykonaniu operacji lub asynchronicznym utworzeniu zasobu400 Bad Request
gdy ktoś wykonuje operację na danych, która jest wyraźnie nieprawdziwa; dla twojej aplikacji może to być błąd sprawdzania poprawności; zazwyczaj rezerwują 500 na niewyłapane wyjątki401 Unauthorized
gdy ktoś uzyskuje dostęp do interfejsu API albo nie dostarcza niezbędnegoAuthorization
nagłówka, albo gdy poświadczenia w nimAuthorization
są nieprawidłowe; nie używaj tego kodu odpowiedzi, jeśli nie oczekujesz poświadczeń za pomocąAuthorization
nagłówka.403 Forbidden
gdy ktoś uzyskuje dostęp do Twojego interfejsu API w sposób, który może być złośliwy lub jeśli nie ma autoryzacji405 Method Not Allowed
kiedy ktoś używa POST, kiedy powinien był użyć PUT itp413 Request Entity Too Large
gdy ktoś próbuje wysłać ci niedopuszczalnie duży plik418 I'm a teapot
podczas próby parzenia kawy za pomocą czajnikaETag
nagłówki są dobre, gdy można łatwo zredukować zasób do wartości skrótuLast-Modified
powinien zasygnalizować, że sprawdzanie czasu aktualizacji zasobów jest dobrym pomysłemCache-Control
iExpires
powinny mieć sensowne wartościIf-None-Modified
,If-Modified-Since
)W odniesieniu do twojego konkretnego pytania, należy użyć POST dla # 4 i # 5. Operacje te podlegają powyższej wytycznej „podobnej do RPC”. W przypadku nr 5 pamiętaj, że POST nie musi koniecznie używać
Content-Type: application/x-www-form-urlencoded
. Może to być równie łatwo ładunek JSON lub CSV.źródło
Ilekroć wygląda na to, że potrzebujesz nowego czasownika, pomyśl o zamianie go w rzeczownik. Na przykład zmień „aktywuj” na „aktywacja”, a „sprawdź” na „weryfikacja”.
Ale na podstawie tego, co napisałeś, powiedziałbym, że Twoja aplikacja ma znacznie większe problemy.
Za każdym razem, gdy proponowany jest zasób zwany „parametrem”, powinien wysyłać czerwone flagi w umyśle każdego członka zespołu projektowego. „parametr” może dosłownie dotyczyć dowolnego zasobu; to nie jest wystarczająco szczegółowe.
Co dokładnie oznacza „parametr”? Prawdopodobnie wiele różnych rzeczy, z których każda powinna mieć osobny zasób dedykowany.
Kolejny sposób na osiągnięcie tego - kiedy omawiasz swoją aplikację z użytkownikami końcowymi (tymi, którzy prawdopodobnie niewiele wiedzą o programowaniu), jakich słów używają wielokrotnie?
To są słowa, które powinieneś projektować.
Jeśli nie masz jeszcze tej konwersji z potencjalnymi użytkownikami - zatrzymaj wszystko teraz i nie pisz kolejnej linii kodu, dopóki tego nie zrobisz! Tylko wtedy twój zespół będzie wiedział, co należy zbudować.
Nie wiem nic o oprogramowaniu finansowym, ale gdybym musiał zgadywać, powiedziałbym, że niektóre zasoby mogą mieć nazwy takie jak „Raport”, „Płatność”, „Przelew” i „Waluta”.
Jest wiele dobrych książek na temat tej części procesu projektowania oprogramowania. Dwa, które mogę polecić, to wzorce projektowania i analizy oparte na domenie .
źródło
Projekt twoich adresów URL nie ma nic wspólnego z tym, czy twoja aplikacja jest RESTful czy nie. Wyrażenie „RESTful URL” jest więc nonsensowne.
Myślę, że powinieneś przeczytać coś więcej na temat tego, czym tak naprawdę jest REST. REST traktuje adresy URL jako nieprzejrzyste i jako takie nie wie, co się w nich znajduje, bez względu na to, czy istnieją czasowniki, rzeczowniki czy cokolwiek innego. Nadal możesz chcieć zaprojektować swoje adresy URL, ale to dotyczy interfejsu użytkownika, a nie REST.
To powiedziawszy, przejdźmy do twojego pytania: dwa ostatnie przypadki nie są ODPOCZYNEKAMI i nie pasują do żadnego rodzaju schematu odpoczynku. Oto, co możesz nazwać RPC. Jeśli poważnie myślisz o REST, musisz od nowa przemyśleć sposób działania aplikacji. Albo to, albo zrezygnuj z REST i po prostu zrób swoją aplikację jako aplikację RPC.
Hmmm może nie.
Chodzi o to, że musisz traktować wszystko jako zasób, więc gdy zestaw parametrów ma adres URL, z którego można się do niego odwoływać, dodajesz:
Ale znowu, rzeczą aktywującą jest RPC, a nie REST.
źródło
Wymagania dotyczące aktywacji i sprawdzania poprawności to sytuacje, w których próbujesz zmienić stan zasobu. Nie inaczej jest składanie zamówienia „zrealizowane” lub inne „złożone” żądanie. Istnieje wiele sposobów modelowania tego rodzaju zmian stanu, ale moim zdaniem, który często działa, jest tworzenie zasobów kolekcji dla zasobów tego samego stanu, a następnie przenoszenie zasobów między kolekcjami w celu wpłynięcia na stan.
np. Utwórz niektóre zasoby, takie jak
Jeśli chcesz, aby zestaw parametrów był aktywny, dodaj go do kolekcji ActiveParameters. Możesz przekazać zestaw parametrów jako treść encji lub przekazać URL jako parametr zapytania w następujący sposób:
To samo można zrobić z / ValidatedParameters. Jeśli parametry nie są prawidłowe, serwer może zwrócić „niepoprawne żądanie” do żądania dodania parametrów do kolekcji zweryfikowanych parametrów.
źródło
Proponuję następujące zasoby i metody Meta.
Uaktywnij parametry i / lub sprawdź je:
Sprawdź, czy parametry są aktywne i prawidłowe:
źródło
Jest mi trochę przykro, widząc, że po ponad 10 latach nie ma tak naprawdę odpowiedzi, która mówi, w jaki sposób można zażądać OP w architekturze REST, dlatego teraz muszę to zrobić.
Po pierwsze, czym jest REST ?! Skrót REST lub ReST oznacza „Reprezentatywny transfer stanu” i określa wymianę stanu zasobu w określonym formacie reprezentacji. Format reprezentacji jest zgodny z typem wynegocjowanego nośnika. W przypadku
application/html
formatu reprezentacji może to być strumień treści tekstowej w formacie HTML, który jest renderowany w przeglądarce, prawdopodobnie po zastosowaniu formatowania arkusza stylów w celu umiejscowienia niektórych elementów w określonych lokalizacjach.REST jest w zasadzie uogólnieniem przeglądalnej sieci, którą wszyscy znamy, choć atakuje ona wszystkie rodzaje aplikacji, a nie tylko przeglądarki. Dlatego z założenia te same pojęcia, które dotyczą sieci, dotyczą również architektury REST. Pytanie, jak osiągnąć coś w sposób „RESTful”, rozwiązuje problem odpowiadania na pytanie, jak osiągnąć coś na stronie internetowej, a następnie zastosować te same koncepcje do warstwy aplikacji.
Internetowy kalkulator zwykle zaczyna się od „strony”, która pozwala wprowadzić pewne wartości do obliczenia przed wysłaniem wprowadzonych danych na serwer. W HTML jest to zwykle osiągane za pomocą
<form>
elementów HTML , które uczą klienta o dostępnych parametrach do ustawienia, docelowej lokalizacji do wysłania żądania, a także formacie reprezentacji, który należy zastosować przy wysyłaniu danych wejściowych. Może to wyglądać tak:Powyższy przykład, tj. Stwierdza, że istnieją dwa pola wejściowe, które może wypełnić użytkownik lub niektóre inne automaty oraz że po wywołaniu elementu wejściowego prześlij przeglądarkę formatuje dane wejściowe do
application/x-www-form-urlencoded
formatu reprezentacji, który jest wysyłany do wspomnianej docelowej lokalizacji za pomocą określonej metody żądania HTTP,POST
w tym przypadku. Jeśli wchodzimy1
wfirstNumber
polu wprowadzania i2
dosecondNumber
pola wprowadzania, przeglądarka wygeneruje reprezentacjęfirstNumber=1&secondNumber=2
i wysłać go jako ładunek ciała rzeczywistego żądanie zasobu docelowego.Surowe żądanie HTTP wysłane do serwera może więc wyglądać następująco:
Serwer może wykonać obliczenia i odpowiedzieć kolejną stroną HTML, która zawiera wynik obliczeń, ponieważ żądanie wskazało, że klient rozumie ten format.
Jak już zauważył Breton, nie ma czegoś takiego jak „RESTful” URL lub URI. Identyfikator URI / URL jest swoistą rzeczą i nie powinien przekazywać żadnego znaczenia klientowi / użytkownikowi. W powyższym przykładzie kalkulatora użytkownik po prostu nie jest zainteresowany, gdzie wysłać dane, interesuje go tylko to, że po uruchomieniu pola wejściowego przesłania żądanie jest wysyłane. Serwer powinien podać wszystkie wymagane informacje potrzebne do wykonania zadania.
Przeglądarka może również nie zdawać sobie sprawy z tego, że żądanie faktycznie zasila kalkulator z niektórymi parametrami wejściowymi, może to być również rodzaj formularza zamówienia, który zwraca tylko kolejną reprezentację formularza w celu kontynuowania procesu zamawiania lub zupełnie innego rodzaju ratunek. Po prostu wykonuje to, czego wymaga specyfikacja HTML w takim przypadku i nie obchodzi go, co tak naprawdę robi serwer. Ta koncepcja umożliwia przeglądarce korzystanie z tego samego formatu reprezentacji do robienia wszelkiego rodzaju rzeczy, takich jak zamawianie niektórych rzeczy w preferowanym sklepie internetowym, rozmowy z najlepszymi przyjaciółmi, logowanie się do konta online i tak dalej.
Affordance niektórych elementów, np w przypadku przedstawienia wejściowe pole, które jest zwykle renderowany jako przycisk definiuje co należy się z nim. W przypadku przycisku lub łącza w zasadzie każe ci je kliknąć. Inne elementy mogą przenosić różne afordancje. Tę afordancję można również wyrazić za pomocą relacji między
preload
linkami, np. Za pomocą linków z adnotacjami, które w zasadzie mówią klientowi, że może on już załadować zawartość połączonego zasobu w tle, ponieważ użytkownik najprawdopodobniej następnie przejmie tę zawartość. Takie relacje linków powinny być oczywiście znormalizowane lub zgodne z mechanizmem rozszerzenia dla typów relacji określonych przez linkowanie w sieci .Są to podstawowe koncepcje stosowane w sieci, które powinny być również stosowane w architekturze REST. Według „wujka Boba” Roberta C. Martina architektura dotyczy zamiarów, a intencją architektury REST jest oddzielenie klientów od serwerów, aby umożliwić serwerom swobodną ewolucję w przyszłości bez obawy, że złamią klientów. To niestety wymaga dużej dyscypliny, ponieważ tak łatwo jest wprowadzić sprzęganie lub dodać rozwiązania szybkiej naprawy, aby wykonać zadanie i przejść dalej. Jak zauważył Jim Webber w architekturze REST, jako dostawca usług powinieneś spróbować zaprojektować protokół aplikacji domeny podobny do tekstowej gry komputerowej z lat 70., którą klienci będą realizować aż do końca procesu.
Niestety tak naprawdę wiele tzw. Interfejsów API „REST” w rzeczywistości to wszystko. Widoczna jest wymiana danych opartych głównie na JSON, które są określone w dokumentacji zewnętrznej specyficznej dla API, którą zwykle trudno dynamicznie zintegrować w locie. Format, w jaki musi wyglądać żądanie, jest również zapisany na stałe w dokumentacji zewnętrznej, co prowadzi do dużej liczby interpretacji identyfikatorów URI w celu zwrócenia predefiniowanych typówzamiast używać jakiegoś wspólnego formatu reprezentacji, który jest negocjowany z góry. Zapobiega to zmianie serwerów, ponieważ klienci oczekują teraz otrzymania określonego formatu danych (należy pamiętać, że nie jest to format reprezentacji!) Dla wstępnie zdefiniowanych identyfikatorów URI. Ta niestandardowa wymiana formatu danych dodatkowo uniemożliwia klientom interakcję z innymi interfejsami API, ponieważ „format danych” jest zwykle przypływem do określonego interfejsu API. Znamy tę koncepcję z przeszłości z technologii RPC, takich jak Corba, RMI lub SOAP, które potępiamy jako w jakiś sposób złe, mimo że Peppol przeszedł na nią ponownie, zastępując AS2 domyślnym protokołem przesyłania ostatnio.
Jeśli chodzi o zadane pytanie, wysyłanie danych w postaci pliku csv nie różni się niczym od używania
application/x-www-form-urlencoded
reprezentacji lub podobnych rzeczy. Jim Webber wyjaśnił, że w końcu HTTP jest tylko protokołem transportowym, którego domeną aplikacji jest przesyłanie dokumentów przez Internet . Klient i serwer powinny co najmniej obsługiwaćtext/csv
zgodnie z definicją w RFC 7111 . Ten plik CSV może zostać wygenerowany w wyniku przetworzenia typu nośnika, który definiuje elementy formularza, element docelowy lub atrybut, do którego należy wysłać żądanie, a także metodę HTTP w celu przesłania konfiguracji.Istnieje kilka rodzajów nośników obsługujących formularze, takie jak HTML , formularze HAL , halform , ion lub Hydra . Obecnie jednak nie znam typu nośnika, który może automatycznie kodować dane wejściowe
text/csv
bezpośrednio, dlatego może być konieczne zdefiniowanie i zarejestrowanie w rejestrze typów nośników IANA .Przesyłanie i pobieranie pełnego zestawu parametrów nie powinno być problemem. Jak wspomniano wcześniej, docelowy identyfikator URI nie ma znaczenia, ponieważ klient użyje identyfikatora URI do pobrania nowej treści do przetworzenia. Filtrowanie według daty biznesowej również nie powinno być trudne. Tutaj serwer powinien jednak mieć wszystkie możliwości, z których klient może po prostu wybrać. W ostatnich latach opracowano GraphQL i RestQL, które wprowadzają język podobny do SQL, który może być ukierunkowany na określony punkt końcowy w celu uzyskania odfiltrowanej odpowiedzi. Jednak w prawdziwym sensie REST narusza to ideę REST jako a) GraphQL, tj. Używa tylko jednego punktu końcowego, który w jakiś sposób uniemożliwia optymalne użycie buforowania ib) wymaga znajomości dostępnych pól w górę, co może prowadzić do wprowadzenia łączenia klientów do podstawowego modelu danych zasobu.
Aktywacja lub dezaktywacja niektórych parametrów konfiguracyjnych jest po prostu kwestią uruchomienia kontroli hipermedialnych, które zapewniają taką afordancję. W formularzach HTML może to być proste pole wyboru lub zaznaczenie wielu wierszy na liście lub tego rodzaju. W zależności od formy i metody, którą definiuje, może potencjalnie wysłać całą konfigurację za pośrednictwem
PUT
lub być sprytnym w kwestii dokonanych zmian i wykonać tylko częściową aktualizację za pośrednictwemPATCH
. Ten ostatni wymaga w zasadzie obliczenia reprezentacji zmiany na zaktualizowaną i podaje serwerowi wymagane kroki, aby przekształcić bieżącą reprezentację w pożądaną. Zgodnie ze specyfikacją PATH należy to zrobić w ramach transakcji, aby zastosować wszystkie lub żaden z kroków.HTTP pozwala i zachęca serwer do zweryfikowania otrzymanego żądania z góry przed zastosowaniem zmian. Dla PUT specyfikacja określa:
Podsumowując ten post, powinieneś albo użyć istniejącego typu nośnika, który pozwala nauczyć klienta o wymaganych lub obsługiwanych parametrach wejściowych, docelowej lokalizacji, do której należy wysłać żądanie, operacji, a także typu mediów prośba musi zostać sformatowana lub zdefiniować własną, którą zarejestrujesz w IANA. To ostatnie może być konieczne, jeśli chcesz przekonwertować dane wejściowe
text/csv
a następnie prześlij reprezentację CSV na serwer. Sprawdzanie poprawności powinno nastąpić przed zastosowaniem zmian do zasobu. Rzeczywisty identyfikator URI nie powinien mieć znaczenia dla klientów poza ustaleniem, gdzie wysłać zapytanie i jako taki może być swobodnie wybrany przez Ciebie, realizatora usługi. Postępując zgodnie z tymi krokami, zyskujesz swobodę zmiany strony serwera w dowolnym momencie, a klienci nie ulegną awarii, jeśli obsługują używane typy mediów.źródło
Edycja: Rzeczywiście, identyfikator URI uniemożliwiłby
GET
żądanie pozostanie idempotentem.Jednak w przypadku sprawdzania poprawności użycie kodów stanu HTTP do powiadomienia o ważności żądania (w celu utworzenia nowego lub zmodyfikowania istniejącego „parametru”) pasowałoby do modelu Restful.
Zgłoś z
400 Bad Request
kodem stanu, jeśli przesłane dane są / są nieprawidłowe i żądanie musi zostać zmienione przed ponownym przesłaniem ( kody stanu HTTP / 1.1 ).Polega to jednak na sprawdzeniu poprawności podczas przesyłania, a nie na odroczeniu jej, tak jak w przypadku użycia. Inne odpowiedzi mają odpowiednie rozwiązania tego scenariusza.
źródło
W środowisku REST każdy adres URL jest unikalnym zasobem. Jakie są twoje zasoby Kalkulator finansowy naprawdę nie ma żadnych oczywistych zasobów. Musisz zagłębić się w parametry, które nazywasz, i wyciągnąć zasoby. Na przykład kalendarz amortyzacji pożyczki może być zasobem. Adres URL kalendarza może obejmować datę początkową, termin (w miesiącach lub latach), okres (po złożeniu odsetek), stopę procentową i zasadę początkową. Przy wszystkich tych wartościach masz określony kalendarz płatności:
Teraz nie wiem, co obliczasz, ale twoja koncepcja listy parametrów nie brzmi RESTful. Jak ktoś inny powiedział, powyższe wymagania brzmią bardziej XMLRPC. Jeśli próbujesz uzyskać REST, potrzebujesz rzeczowników. Obliczenia nie są rzeczownikami, są czasownikami działającymi na rzeczowniki. Musisz go odwrócić, aby wyciągnąć rzeczowniki z cieląt.
źródło