POST HTTP z parametrami zapytań URL-dobry pomysł czy nie?

Projektuję API, aby przejść przez HTTP i zastanawiam się, czy użycie polecenia HTTP POST, ale tylko z parametrami zapytania URL i bez ciała żądania, jest dobrym sposobem.

Rozważania:

  • "dobre projektowanie stron internetowych" wymaga nie idempotentnych działań, które należy wysyłać pocztą. Jest to działanie bez idempotentne.
  • łatwiej jest opracować i debugować tę aplikację, gdy parametry żądania są obecne w adresie URL.
  • API nie jest przeznaczone do powszechnego użytku.
  • It wygląda na to, że wykonanie żądania POST bez body ' ego zajmie trochę więcej pracy, np. nagłówek Content-Length: 0 musi być wyraźnie dodany.
  • wydaje mi się również, że POST bez ciała jest nieco sprzeczny z oczekiwaniami większości programistów i frameworków HTTP.

Czy są jeszcze jakieś pułapki lub korzyści w wysyłaniu parametrów na żądanie POST za pośrednictwem zapytania URL zamiast treści żądania?

Edit: powodem tego jest to, że operacje nie są idempotentne i mieć skutki uboczne inne niż pobieranie. Zobacz spec HTTP :

W szczególności Konwencja została ustalono, że GET i głowy metody nie powinny mieć znaczenie podjęcia działania Inne niż odzyskiwanie. Metody te powinny być uważane za "bezpieczne". Pozwala to użytkownikowi środki do reprezentowania innych metod, takich jak POST, PUT i DELETE, w specjalny sposób, tak aby użytkownik został wykonany świadomi faktu, że możliwe niebezpieczne działanie jest / align = "left" /

...

Metody mogą mieć również właściwość "idempotencja" w tym (oprócz błąd lub problemy z wygaśnięciem) skutki uboczne N > 0 wnioski są takie same jak dla pojedynczego Prośba. Metody GET, HEAD, PUT i usuń Udostępnij tę właściwość. Również, opcje metod i TRACE powinny Nie mają skutków ubocznych, a więc są z natury idempotentna.

Author: Steven Huwig, 2009-03-04

7 answers

Jeśli twoja akcja nie jest idempotentna, to musisz użyć POST. Jeśli nie, prosisz o kłopoty. GET, PUT i DELETE metody są wymagane , aby były idempotentne. Wyobraź sobie, co by się stało w Twojej aplikacji, gdyby klient pobierał wszystkie możliwe GET prośby o Twoją usługę - jeśli spowodowałoby to efekty uboczne widoczne dla Klienta, to coś jest nie tak.

Zgadzam się, że wysyłanie {[0] } z ciągiem zapytania, ale bez ciało wydaje się dziwne, ale myślę, że może być odpowiednie w niektórych sytuacjach.

Pomyśl o części zapytania adresu URL jako o poleceniu do zasobu, aby ograniczyć zakres bieżącego żądania. Zazwyczaj ciągi zapytań są używane do sortowania lub filtrowania żądania GET (Jak ?page=1&sort=title), ale przypuszczam, że na POST ma sens również ograniczanie zakresu (być może jak ?action=delete&id=5).

 199
Author: Don McCaughey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-04 19:20:39

Każdy ma rację: trzymaj się postu dla nie idempotentnych żądań.

A co z używaniem zarówno ciągu zapytania URI, jak i treści żądania? Dobrze jest to poprawne HTTP( patrz uwaga 1), więc dlaczego nie!

Jest to również całkowicie logiczne: adresy URL, w tym ich część łańcucha zapytań, są przeznaczone do lokalizowania zasobów. Natomiast metoda HTTP (POST - i jej opcjonalna treść żądania) służy do określania akcji, czyli co zrobić z zasobami. To powinny być problemy ortogonalne. (Ale oni nie są pięknie ortogonalnymi problemami dla specjalnego przypadku ContentType=application / x-www-form-urlencoded, patrz uwaga 2 poniżej.)

Uwaga 1: specyfikacja HTTP (1.1) nie stwierdza, że parametry zapytania i zawartość wzajemnie się wykluczają dla serwera HTTP, który akceptuje żądania POST lub PUT. Więc każdy serwer może zaakceptować oba. Tzn. jeśli piszesz serwer to nic nie stoi na przeszkodzie, żebyś zaakceptował oba (może poza nieelastycznym frameworkiem). Ogólnie serwer może interpretować zapytania ciągów zgodnie z dowolnymi regułami, jakie chce. Może nawet interpretować je za pomocą logiki warunkowej, która odnosi się 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ą, to powinieneś przestrzegać zasad dla tego typu treści. A zasady aplikacji / x-www-form-urlencoded to znacznie bardziej szczegółowe( i szczerze mówiąc, niezwykłe): w tym przypadku musisz zinterpretować URI jako zestaw parametrów, a nie lokalizację zasobów. [Jest to ten sam punkt użyteczności Powerlord podniesiony; że może być trudno używać formularzy internetowych do publikowania treści na serwerze. Wyjaśniłem to trochę inaczej.]

Uwaga 3: do czego pierwotnie służą łańcuchy zapytań? RFC 3986 definiuje ciągi zapytań HTTP jako część URI, która działa jako niehierarchiczny sposób lokalizowania zasobu.

W przypadku czytelników zadając to pytanie pragniemy zapytać, co to jest dobra architektura RESTful: wzór 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 buforowalność zasobów, projektowanie samych zasobów (ich zachowanie, możliwości i reprezentacje) oraz czy idempotencja jest spełniona. Innymi słowy, osiągnięcie projektu, który jest wysoce kompatybilny z protokołem HTTP i jego zestawem HTTP czasowniki metodyczne. :- ) (Innymi słowy, Architektura RESTful nie jest zbyt intuicyjna z tym, jak znajdują się zasoby .)

Ostatnia uwaga: czasami parametry zapytań są używane do jeszcze innych rzeczy, które nie są ani lokalizowaniem zasobów, ani kodowaniem treści. Czy kiedykolwiek widziałeś parametr zapytania, taki jak "PUT = true" lub "POST = true"? Są to obejścia dla przeglądarek, które nie pozwalają na używanie metod PUT I POST. Chociaż takie parametry są postrzegane jako część ciągu zapytania URL( na drucie), argumentuję że nie są one częścią zapytania URL w duchu .

 103
Author: Tim Lovell-Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-09 17:14:59

Chcesz powodów? Oto jeden:

Formularz internetowy nie może być używany do wysyłania żądania do strony, która używa mieszanki GET I POST. Jeśli ustawisz metodę formularza NA GET, wszystkie parametry znajdują się w łańcuchu zapytania. Jeśli ustawisz metodę formularza NA POST, wszystkie parametry znajdują się w treści żądania.

Source: HTML 4.01 standard, section 17.13 Form Submission

 58
Author: Powerlord,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-04 19:16:26

Z punktu widzenia programistycznego, dla klienta jest to pakowanie parametrów i dołączanie ich do adresu url i prowadzenie POST vs. GET. Po stronie serwera, ocenia parametry przychodzące z querystring zamiast wysyłanych bajtów. W zasadzie to pranie.

Zalety / wady mogą wynikać z tego, jak konkretne platformy klienckie współpracują z funkcjami POST I GET w stosie sieciowym, a także jak serwer WWW radzi sobie z tymi żądaniami. W zależności od wdrożenia, jedno podejście może być bardziej efektywne niż drugie. Wiedząc, że to pokieruje twoją decyzją.

Niemniej jednak, z punktu widzenia programisty, wolę pozwolić albo POST ze wszystkimi parametrami w ciele, lub GET ze wszystkimi paramami w adresie url, i jawnie ignorując parametry url z dowolnym żądaniem POST. Pozwala uniknąć nieporozumień.

 8
Author: jro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-04 18:56:28

Myślę, że nadal może być dość spokojny, aby mieć argumenty zapytań, które identyfikują zasób na adresie URL, utrzymując ładunek treści ograniczony do ciała posta. Wydaje się to oddzielać rozważania "co wysyłam?"versus" do kogo to wysyłam?".

 4
Author: swizzcheez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-10 19:04:11

Obóz REST ma pewne zasady przewodnie, których możemy użyć do standaryzacji sposobu, w jaki używamy czasowników HTTP. Jest to pomocne podczas budowania RESTful API tak, jak to robisz.

W skrócie: GET powinien być tylko odczytywany tzn. nie ma wpływu na stan serwera. POST służy do tworzenia zasobów na serwerze. PUT służy do aktualizacji lub tworzenia zasobu. DELETE służy do usuwania zasobu.

Innymi słowy, jeśli twoje działanie API zmieni stan serwera, REST zaleca nam użycie POST/PUT / DELETE, ale nie GET.

Agenci użytkowników zazwyczaj rozumieją, że robienie wielu postów jest złe i ostrzegają przed tym, ponieważ intencją postu jest zmiana stanu serwera (np. zapłać za towar przy kasie), a prawdopodobnie nie chcesz tego robić dwa razy!

Porównaj z GETEM, który możesz zrobić często, jak chcesz(idempotent).

 2
Author: saille,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-30 23:12:51

Zgadzam się - prawdopodobnie bezpieczniej jest użyć żądania GET, jeśli po prostu przekazujesz dane w adresie URL, a nie w ciele. Zobacz to podobne pytanie , aby uzyskać dodatkowe widoki na całą koncepcję POST+GET.

 -9
Author: Marc Novakowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:24