Projektuję interfejs API do obsługi protokołu HTTP i zastanawiam się, czy dobrym rozwiązaniem jest użycie polecenia HTTP POST, ale z parametrami zapytań URL i bez treści żądania.
Uwagi:
- „Dobry projekt internetowy” wymaga wysłania za pomocą POST działań nie idempotentnych. To działanie nie idempotentne.
- Łatwiej jest rozwijać i debugować tę aplikację, gdy parametry żądania są obecne w adresie URL.
- Interfejs API nie jest przeznaczony do powszechnego użytku.
- Wygląda na to, że wykonanie żądania POST bez treści zajmie nieco więcej pracy, np.
Content-Length: 0
Nagłówek musi zostać wyraźnie dodany. - Wydaje mi się również, że test POST bez ciała jest nieco sprzeczny z oczekiwaniami większości programistów i środowisk HTTP.
Czy są jakieś pułapki lub zalety wysyłania parametrów na żądanie POST za pośrednictwem zapytania URL, a nie treści żądania?
Edycja: Powodem tego jest to, że operacje nie są idempotentne i mają skutki uboczne inne niż pobieranie. Zobacz specyfikację HTTP :
W szczególności ustanowiono konwencję, że metody GET i HEAD NIE POWINNY mieć znaczenia innego niż odzyskanie. Metody te należy uznać za „bezpieczne”. Pozwala to agentom użytkownika na reprezentowanie innych metod, takich jak POST, PUT i DELETE, w specjalny sposób, dzięki czemu użytkownik jest informowany o tym, że żądane jest potencjalnie niebezpieczne działanie.
...
Metody mogą również mieć właściwość „idempotence”, ponieważ (oprócz błędów związanych z błędem lub wygasaniem) skutki uboczne N> 0 identycznych żądań są takie same jak w przypadku pojedynczego żądania. Metody GET, HEAD, PUT i DELETE współużytkują tę właściwość. Ponadto metody OPCJE i ŚLEDZENIE NIE POWINNY wywoływać skutków ubocznych, a zatem są z natury idempotentne.
Odpowiedzi:
Jeśli twoje działanie nie jest idempotentne, MUSISZ użyć
POST
. Jeśli nie, po prostu prosisz o kłopoty.GET
,PUT
aDELETE
metody są muszą być idempotentne. Wyobraź sobie, co by się stało w Twojej aplikacji, gdyby klient pobierał wszystkie możliweGET
żądania dotyczące Twojej usługi - jeśli spowodowałoby to widoczne skutki uboczne dla klienta, coś jest nie tak.Zgadzam się, że wysyłanie ciągu
POST
zapytania, ale bez treści, wydaje się dziwne, ale myślę, że może być odpowiednie w niektórych sytuacjach.Pomyśl o części zapytania w adresie URL jako o poleceniu do zasobu, aby ograniczyć zakres bieżącego żądania. Zazwyczaj ciągi zapytania są używane do sortowania lub filtrowania
GET
żądania (jak?page=1&sort=title
), ale przypuszczam, że sensowne jestPOST
również ograniczenie zakresu (być może jak?action=delete&id=5
).źródło
/action?response_format=json
)Wszyscy mają rację: trzymaj się POST dla nie idempotentnych żądań.
Co z użyciem zarówno ciągu zapytania URI, jak i treści żądania? To poprawny HTTP (patrz uwaga 1), więc czemu nie ?!
Jest to również całkowicie logiczne: adresy URL, w tym część ciągu zapytania, służą do lokalizowania zasobów. Natomiast czasowniki metody HTTP (POST - i opcjonalna treść żądania) służą do określania działań lub sposobu postępowania z zasobami. Powinny to być obawy ortogonalne. (Ale nie są to pięknie ortogonalne obawy dotyczące specjalnego przypadku ContentType = application / x-www-form-urlencoded, patrz uwaga 2 poniżej.)
Uwaga 1: Specyfikacja HTTP (1.1) nie określa, że parametry i treść zapytania wykluczają się wzajemnie dla serwera HTTP, który przyjmuje żądania POST lub PUT. Tak więc każdy serwer może zaakceptować oba. Tzn. Jeśli napiszesz serwer, nic nie stoi na przeszkodzie, abyś zaakceptował oba (z wyjątkiem może nieelastycznego frameworka). Zasadniczo serwer może interpretować ciągi zapytań zgodnie z dowolnymi regułami. Może nawet interpretować je za pomocą logiki warunkowej, która odnosi się również do innych nagłówków, takich jak Content-Type, co prowadzi do uwagi 2:
Uwaga 2: jeśli przeglądarka internetowa jest podstawowym sposobem, w jaki ludzie uzyskują dostęp do twojej aplikacji internetowej, a application / x-www-form-urlencoded jest typem treści, który publikują, powinieneś postępować zgodnie z zasadami dla tego typu treści. A zasady dla application / x-www-form-urlencoded są znacznie bardziej szczegółowe (i szczerze mówiąc, niezwykłe): w tym przypadku musisz interpretować URI jako zestaw parametrów, a nie lokalizację zasobu. [Jest to ten sam punkt przydatności podniesiony przez Władcę; korzystanie z formularzy internetowych do wysyłania treści na serwer może być trudne. Wyjaśniłem trochę inaczej.]
Uwaga 3: po co są pierwotnie ciągi zapytań? RFC 3986 definiuje ciągi zapytania HTTP jako część URI, która działa jako niehierarchiczny sposób lokalizowania zasobu.
W przypadku, gdy czytelnicy zadający to pytanie chcą zapytać, co jest dobre architektura RESTful: wzorzec architektury RESTful nie wymaga, aby schematy URI działały w określony sposób. Architektura RESTful dotyczy innych właściwości systemu, takich jak buforowanie zasobów, projektowanie samych zasobów (ich zachowanie, możliwości i reprezentacje) oraz to, czy idempotencja jest spełniona. Innymi słowy, osiągnięcie projektu wysoce kompatybilnego z protokołem HTTP i zestawem czasowników metod HTTP. :-) (Innymi słowy, relaksującego architektura nie jest bardzo presciptive z przebiegu zasobów znajduje ).
Uwaga końcowa: czasami parametry zapytania są wykorzystywane do jeszcze innych rzeczy, które nie są ani lokalizowaniem zasobów, ani kodowaniem treści. Widziałeś kiedyś parametr zapytania, taki jak „PUT = true” lub „POST = true”? Są to obejścia dla przeglądarek, które nie pozwalają na stosowanie metod PUT i POST. Chociaż takie parametry są postrzegane jako część ciągu zapytania adresu URL (w sieci), twierdzę, że nie są one częścią zapytania adresu URL w duchu .
źródło
Chcesz powodów? Tutaj jest jeden:
Formularza internetowego nie można użyć do wysłania żądania do strony, która korzysta z kombinacji GET i POST. Jeśli ustawisz metodę formularza na GET, wszystkie parametry znajdują się w ciągu zapytania. Jeśli ustawisz metodę formularza na POST, wszystkie parametry znajdują się w treści żądania.
Źródło: standard HTML 4.01, sekcja 17.13 Przesyłanie formularzy
źródło
method
jest POST, nie ma wzmianki o zmianie identyfikatora URI w formularzuaction
. I oczywiście każdy identyfikator URI może już zawierać część ciągu zapytania./Books?bookCode=1234
. Serwer WWW otrzyma zmienne formularza POST i ciąg zapytania.Z programowego punktu widzenia, dla klienta pakuje parametry i dołącza je do adresu URL i przeprowadza test POST vs. GET. Po stronie serwera ocenia parametry przychodzące z kwerendy zamiast wysyłanych bajtów. Zasadniczo jest to pranie.
Mogą występować zalety / wady w sposobie działania określonych platform klienckich z procedurami POST i GET w stosie sieci, a także w sposobie, w jaki serwer WWW radzi sobie z tymi żądaniami. W zależności od implementacji jedno podejście może być bardziej wydajne niż drugie. Wiedząc, że to pomoże ci podjąć decyzję tutaj.
Niemniej jednak, z perspektywy programisty, wolę zezwolić na POST ze wszystkimi parametrami w ciele lub GET ze wszystkimi parametrami na adresie URL, i jawnie ignoruję parametry adresu URL przy każdym żądaniu POST. Pozwala uniknąć zamieszania.
źródło
Wydaje mi się, że nadal może być dość RESTful mieć argumenty zapytania, które identyfikują zasób w adresie URL, utrzymując ładunek zawartości ograniczony do treści POST. Wydaje się, że to rozdziela rozważania „Co ja wysyłam?” kontra „Do kogo to wysyłam?”.
źródło
REST obóz pewne zasady przewodnie, które możemy wykorzystać w celu ujednolicenia sposobu używamy czasowników HTTP. Jest to pomocne podczas budowania interfejsów API RESTful podczas pracy.
W skrócie: GET powinien być tylko do odczytu, tzn. Nie ma wpływu na stan serwera. POST służy do tworzenia zasobu na serwerze. PUT służy do aktualizacji lub utworzenia zasobu. DELETE służy do usuwania zasobu.
Innymi słowy, jeśli działanie API zmienia stan serwera, REST zaleca nam użycie POST / PUT / DELETE, ale nie GET.
Programy klienckie zwykle rozumieją, że wykonywanie wielu testów POST jest złe i ostrzega przed tym, ponieważ celem testu POST jest zmiana stanu serwera (np. Płacenie za towary przy kasie) i prawdopodobnie nie chcesz tego robić dwa razy!
Porównaj z GET, który możesz robić często, jak chcesz (idempotent).
źródło
Zgadzam się - prawdopodobnie bezpieczniej jest używać żądania GET, jeśli tylko przekazujesz dane w adresie URL, a nie w treści. Zobacz to podobne pytanie, aby uzyskać dodatkowe informacje na temat całej koncepcji POST + GET.
źródło