PUT vs. POST REST

Pagal HTTP / 1.1 Spec specifikaciją:

POST metodas naudojamas norint, kad šaltinio serveris priimtų užklausoje esantį objektą kaip naują pavaldinį šaltinį, kurį Request-Line nurodė Request-URI

Kitaip tariant, POST naudojamas kuriant .

PUT metodas reikalauja, kad privatus objektas būtų saugomas pateiktame Request-URI . Jei Request-URI reiškia jau veikiantį šaltinį, uždaras subjektas TURI būti laikomas modifikuota versija, kuri yra kilmės serveryje. Jei Request-URI nenurodo esamo šaltinio ir URI gali būti apibrėžiamas kaip naujas šaltinis prašančiam naudotojo agentui, kilmės serveris gali sukurti išteklių su tuo URI. "

Tai reiškia, kad PUT naudojamas kuriant ar atnaujinant .

Taigi, kuris iš jų turėtų būti naudojamas kuriant šaltinį? Arba jums reikia remti abu?

4581
10 марта '09 в 17:25 2009-03-10 17:25 alex yra nustatytas kovo 10 d. 09: 17:25 2009-03-10 17:25
@ 33 atsakymai
  • 1
  • 2

Apskritai:

PUT ir POST gali būti naudojami kūrimui.

Jūs turite paklausti: ką tu darai? atskirti tai, ką turėtumėte naudoti. Tarkime, jūs kuriate API klausimus. Jei norite naudoti POST, turėtumėte tai padaryti klausimų sąraše. Jei norite naudoti PUT, galite tai padaryti konkrečiu klausimu.

Galite naudoti abi parinktis, todėl turiu jį naudoti atnaujinamame dizaine:

Jums nereikia palaikyti PUT ir POST.

Naudojamas jums. Bet nepamirškite naudoti teisingą parinktį, priklausomai nuo to, kurį objektą prašote.

Kai kurie svarstymai:

  • Ar pavadinate URL objektus, kuriuos aiškiai sukuriate arba leidžiate serveryje? Jei juos skambinate, naudokite PUT. Jei įgalinate serverį, naudokite POST.
  • PUT yra idempotentas, taigi, jei dukart paliesite objektą, jis neturi jokio poveikio. Tai puiki nuosavybė, todėl galėčiau naudoti PUT, kai tik įmanoma.
  • Galite atnaujinti arba sukurti išteklius naudodami PUT su tuo pačiu objekto URL
  • Naudodami POST galite vienu metu atlikti 2 užklausas, keisti URL, ir jie gali atnaujinti skirtingas objekto dalis.

Pavyzdys:

Atsakydamas į kitą atsakymą į SO, parašiau :

POST

Naudojamas keisti ir atnaujinti šaltinį.

 POST /questions/<existing_question> HTTP/1.1 Host: www.example.com/ 

Atminkite, kad ši klaida:

 POST /questions/<new_question> HTTP/1.1 Host: www.example.com/ 

Jei URL dar nebuvo sukurtas, neturėtumėte naudoti POST, kad jį sukurtumėte, nurodydami pavadinimą. Tai turėtų sukelti išteklių <new_question> klaidą, nes <new_question> dar nėra. Turite spustelėti <new_question> išteklių mygtuką serveryje.

Galite sukurti kažką panašaus, kad sukurtumėte išteklius naudodami POST:

 POST /questions HTTP/1.1 Host: www.example.com/ 

Atkreipkite dėmesį, kad šiuo atveju išteklių pavadinimas nėra nurodytas, jums bus grąžinti nauji URL objektai.

PUT:

Naudojamas ištekliams sukurti arba perrašyti. Tol, kol nurodysite naujojo URL išteklius.

Naujas šaltinis:

 PUT /questions/<new_question> HTTP/1.1 Host: www.example.com/ 

Jei norite perrašyti esamą šaltinį:

 PUT /questions/<existing_question> HTTP/1.1 Host: www.example.com/ 
3603
10 марта '09 в 17:29 2009-03-10 17:29 atsakė Brianui R. Bondiui kovo 10 d., 17:29, 2009-03-10 17:29

Jūs galite rasti teiginius internete, kurie sako

Nieko neįvyksta.


Geriau rinktis tarp PUT ir POST, remiantis idempotencijos veiksmais.

PUT reiškia išteklių pateikimą - visiškai pakeičiant viską, kas yra prieinama tam tikram URL. Pagal apibrėžimą PUT yra idempotentas. Padarykite tai tiek kartų, kiek norite, ir rezultatas bus tas pats. x=5 yra idempotentas. Galite nurodyti šaltinį, kuris egzistavo prieš arba ne (pvz., Kuriant ar atnaujinant)!

POST atnaujina išteklius, prideda pagalbinį šaltinį arba sukelia pakeitimus. POST nėra idempotentas, nes x++ nėra idempotentas.

border=0

Šiuo argumentu PUT skirtas sukurti, kai žinosite sukurto elemento URL. POST gali būti naudojamas kuriant, kai žinote „gamyklos“ ar valdytojo URL kategoriją, kurią norite sukurti.

taip:

 POST /expense-report 

arba

 PUT /expense-report/10929 
1925 m
22 апр. Atsakymą pateikė Cheeso balandžio 22 d 2010-04-22 17:55 '10, 17:55, 2010-04-22 17:55
  • POST į URL sukuria vaiko išteklių serverio URL.
  • PUT į URL sukuria / pakeičia visą resursą kliento nurodytame URL.
  • PATCH į URL atnaujina dalį tam tikro kliento URL adreso.

Atitinkama PUT ir POST RFC 2616 §9.5ff specifikacija.

POST sukuria vaiko išteklius , todėl POST į /items sukuria išteklius, kurie gyvena pagal /items . Pavyzdžiui. /items/1 . Siunčiant tą patį pašto paketą bus sukurti du ištekliai.

PUT skirtas sukurti arba pakeisti išteklius, žinomus klientui .

Todėl: PUT yra tik CREATE kandidatas, kur klientas jau žino URL, prieš kurdamas šaltinį. Pavyzdžiui. /blogs/nigel/entry/when_to_use_post_vs_put , nes pavadinimas naudojamas kaip išteklių raktas

PUT pakeičia išteklius žinomu URL, jei jis jau yra, todėl to paties prašymo siuntimas neturi įtakos dvigubai. Kitaip tariant, PUT skambučiai yra idempotentai .

RFC skaitoma taip:

Pagrindinis skirtumas tarp POST ir PUT užklausų atsispindi kitoje užklausos-URI vertėje. POST užklausoje esantis URI identifikuoja šaltinį, kuris tvarkys uždarą objektą. Šis šaltinis gali būti duomenų priėmimo procesas, vartai į kitą protokolą arba atskiras subjektas, priimantis anotacijas. Priešingai, UUT prašyme PUT nurodo objektą, pridėtą prie užklausos - vartotojo agentas žino, kas yra URI, ir serveris NEGALIMA bandyti taikyti užklausą kitam ištekliui. Jei serveris nori, kad prašymas būtų taikomas kitam URI,

Pastaba: PUT daugiausia buvo naudojamas atnaujinti išteklius (juos visiškai pakeitus), tačiau pastaruoju metu buvo pereita prie PATCH naudojant esamus išteklius, nes PUT rodo, kad jis pakeičia visą šaltinį. RFC 5789.

575
07 апр. Nigelio Thorne atsakymas, balandžio 7 d 2010-04-07 08:52 '10 ne 8:52 2010-04-07 08:52

Santrauka:

Sukurti:

Tai galima atlikti su PUT arba POST:

PUT

Sukuria naują šaltinį su newResourceId kaip išteklių arba rinkinio identifikatorius.

 PUT /resources/<newResourceId> HTTP/1.1 

POST

Kuria naują išteklių A išteklių URI / rinkinyje . Paprastai serveris grąžina ID.

 POST /resources HTTP/1.1 

Atnaujinti:

Galima atlikti tik naudojant PUT:

PUT

Atnaujina išteklį, naudojant esamą „ ResourceId“, kaip šaltinio arba rinkinio identifikatorių / URI.

 PUT /resources/<existingResourceId> HTTP/1.1 

Paaiškinimas:

Dirbant su REST ir URI, kaip įprasta, kairėje yra bendras , o dešinėje - apibrėžtas . generiniai vaistai paprastai vadinami kolekcijomis , o konkretesni elementai gali būti vadinami ištekliais . Atkreipkite dėmesį, kad išteklius gali būti kolekcija .

Pavyzdžiai:

<- bendrinis - specifinis →

 URI: website.com/users/john website.com - whole site users - collection of users john - item of the collection, or a resource URI:website.com/users/john/posts/23 website.com - whole site users - collection of users john - item of the collection, or a resource posts - collection of posts from john 23 - post from john with identifier 23, also a resource 

Kai naudojate POST, visada nurodote kolekciją , todėl, kai sakote:

 POST /users HTTP/1.1 

Jūs siunčiate naują naudotoją naudotojų kolekcijai .

Jei tęsite ir pabandykite kažką panašaus:

 POST /users/john HTTP/1.1 

jis veiks, bet semantiškai sakote, kad norite pridėti šaltinį prie John kolekcijos. po kolekcija .

Kai tik naudosite „PUT“, nurodote šaltinį arba vieną elementą, galbūt per kolekciją . Todėl, kai sakote:

 PUT /users/john HTTP/1.1 

Jūs pranešate apie serverio naujinimą arba kuriate, jei neegzistuoja, john išteklių. pagal vartotojo kolekciją .

Specifikacija:

Leiskite pabrėžti keletą svarbių specifikacijos dalių:

POST

POST metodas naudojamas prašyti, kad šaltinio serveris priimtų užklausoje pateiktą objektą kaip naują pavedimo identifikatoriaus užklausą-URI užklausos eilutėje

Todėl kolekcijoje sukuriamas naujas šaltinis . .

PUT

PUT metodas reikalauja, kad uždaras objektas būtų saugomas pateiktame užklausos-URI. Jei užklausos-URI nurodo išteklį, kuris jau yra , uždarytas subjektas turėtų būti laikomas pakeista versija, esanti šaltinio serveryje. Jei užklausos-URI nėra susijęs su esamu ištekliu , ir prašančioji naudotojo agentūra gali apibrėžti šį URI kaip naują šaltinį, šaltinio serveris gali sukurti išteklių su tuo URI. "

Todėl sukurkite arba atnaujinkite, remiantis išteklių buvimu.

Pagalba:

173
15 авг. atsakymas pateiktas 7hi4g0 15 rug . 2013-08-15 01:47 '13 ne 1:47 2013-08-15 01:47

Norėčiau pridėti „pragmatišką“ patarimą. Naudokite PUT, kai žinote „id“, su kuriuo galite išsaugoti išsaugotą objektą. PUT naudojimas neveiks pernelyg gerai, jei jums reikės, pvz., Identifikatoriaus, sukurto iš duomenų bazės, kuri bus grąžinta jums būsimoms paieškoms ar naujinimams.

Taigi: jei norite išsaugoti esamą vartotoją arba klientas generuoja identifikatorių, ir buvo patikrinta, ar identifikatorius yra unikalus:

 PUT /user/12345 HTTP/1.1 <-- create the user providing the id 12345 Host: mydomain.com GET /user/12345 HTTP/1.1 <-- return that user Host: mydomain.com 

Priešingu atveju naudokite POST, jei norite iš pradžių sukurti objektą ir PUT, kad atnaujintumėte objektą:

 POST /user HTTP/1.1 <--- create the user, server returns 12345 Host: mydomain.com PUT /user/12345 HTTP/1.1 <--- update the user Host: mydomain.com 
158
15 янв. Atsakymą pateikė ThaDon sausio 15 d 2011-01-15 22:59 '11 10:59 val. 2011-01-15 22:59

POST reiškia „sukurti naują“, kaip „Čia yra įrašas, skirtas sukurti vartotoją, sukurkite jį man“.

PUT reiškia "įterpti, pakeisti, jei jau yra", kaip "Čia yra 5 vartotojo duomenys".

Jūs naudojate POST for example.com/users, nes nežinote naudotojo URL, kurį norite sukurti serveryje.

Jūs esate PUT at example.com/users/id, nes norite pakeisti / sukurti konkretų vartotoją.

Du kartus naudojant tuos pačius duomenis, sukuriami du identiški naudotojai su skirtingais identifikatoriais. Vykdant du kartus su tais pačiais duomenimis, vartotojas pirmą kartą sukuriamas ir antrą kartą atnaujinamas į tą pačią būseną (be pakeitimų). Kadangi jūs atsidursite tokioje pačioje būsenoje po PUT, nesvarbu, kiek kartų jį vykdote, tai laikoma „vienodai galinga“ kiekvieną kartą - idempotent. Tai naudinga automatiniams pakartotiniams prašymams. Ne daugiau „ar tikrai norite siųsti“, kai naršyklėje paspausite mygtuką „Atgal“.

Bendras patarimas yra naudoti POST, kai norite, kad serveris valdytų jūsų išteklių URL generavimą. Priešingu atveju naudokite PUT. Pageidaujama PUT per POST.

149
23 окт. Atsakymas Alexander Torstlingui spalio 23 d 2011-10-23 17:27 '11, 17:27, 2011-10-23 17:27

Naudokite POST sukurti ir PUT atnaujinti. Vis dėlto, kaip tai daro Ruby on Rails.

 PUT /items/1 #=> update POST /items #=> create 
110
10 марта '09 в 17:28 2009-03-10 17:28 atsakymas, kurį pateikė Tim Sullivan, kovo 10 d., 09:17, 2009-03-10 17:28

REST yra labai aukšto lygio koncepcija. Tiesą sakant, jis netgi nepaminėja HTTP!

Jei kyla abejonių, kaip įdiegti REST HTTP, visada galite pažvelgti į „ AtomPub“ („AtomPub“) specifikacijos specifikaciją. AtomPub yra standartas, skirtas rašyti RESTful žiniatinklio paslaugas su HTTP, kurį sukūrė daugelis HTTP ir REST šaltinių, kai kurie iš REST ir (co), išradėjo HTTP, iš Roy Fielding duomenys.

Tiesą sakant, galite naudoti „AtomPub“ tiesiogiai. Nors jis išėjo iš dienoraščių bendruomenės, tai jokiu būdu neapsiriboja tik dienoraščiais: tai yra bendras protokolas, skirtas susigrąžinti sąveiką su savavališkais (įdėtomis) savavališkų išteklių rinkiniais per HTTP. Jei galite pateikti savo paraišką kaip įdėtą išteklių rinkinį, galite tiesiog naudoti „AtomPub“ ir nesirūpinti, ar naudoti PUT arba POST, kuriuos HTTP būsenos kodus grąžinti, ir visas šias detales.

Štai ką „AtomPub“ turi pasakyti apie išteklių kūrimą (9.2 skirsnis):

Jei norite įtraukti narius į kolekciją, klientai siunčia POST užklausas į kolekcijos URI.

59
10 марта '09 в 18:27 2009-03-10 18:27 Atsakymą pateikė Jörg W Mittag , kovo 10 d., 08:18, 18:27 2009-03-10 18:27

Sprendimas, ar naudoti PUT arba POST, kad sukurtumėte išteklius serveryje su HTTP + REST API, yra pagrįstas tuo, kam priklauso URL struktūra. Turint klientą arba dalyvaujant apibrėžime, URL struktūra yra nereikalinga nuoroda, panaši į nepageidaujamų nuorodų, kilusių iš SOA. Vengti sukabinimo tipų yra priežastis, kodėl REST yra toks populiarus. Todėl teisingas metodas yra POST. Yra šios taisyklės išimčių ir atsiranda, kai klientas nori išlaikyti valdomų išteklių, kuriuos jis naudoja, vietą. Tai retai ir tikriausiai reiškia kažką kito.

Šiuo metu kai kurie žmonės teigia, kad jei bus naudojamas RESTful URL, klientas žino šaltinio URL, todėl PUT yra priimtinas. Galų gale, todėl svarbūs yra kanoniniai, normalizuoti, Ruby on Rails, Django URL, žiūrėkite „Twitter“ API ... blah blah. Šie žmonės turi suprasti, kad nėra tokio dalyko, kaip „Restful-URL“ , ir kad pats Roy Fielding teigia, kad :

REST API neturėtų apibrėžti fiksuotų išteklių pavadinimų ar hierarchijų (akivaizdus ryšys tarp kliento ir serverio). Serveriai turi turėti laisvę valdyti savo vardų erdvę. Vietoj to, leiskite serveriams nurodyti klientams, kaip sukurti tinkamus URI, pvz., HTML formatuose ir URI modeliuose, apibrėždami šias instrukcijas tipo ir asociacijos aplinkoje. [Nesėkmė čia reiškia, kad klientai prisiima išteklių struktūrą dėl informacijos be juostos, pvz., Domeno specifinio standarto, kuris yra duomenų orientuotas RPC funkcinės nuorodos ekvivalentas].

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

„RESTful“ URL idėja iš tikrųjų yra REST pažeidimas, nes serveris yra atsakingas už URL struktūrą ir turėtų turėti teisę nuspręsti, kaip jį naudoti, kad būtų išvengta ryšio. Jei jūs supainiotumėte, skaitykite apie API aptikimo reikšmę.

Naudojant POST kuriant išteklius, reikia atsižvelgti į projektavimo aplinkybes, nes POST nėra idempotentas. Tai reiškia, kad kartotinis POST kartojimas neužtikrina to paties elgesio kiekvieną kartą. Jis gąsdina žmones naudoti PUT, kad sukurtų išteklius, kai jų nereikia. Jie žino, kad tai neteisinga (POST for CREATE), tačiau jie vis dar daro, nes nežino, kaip išspręsti šią problemą. Ši problema pasireiškia tokioje situacijoje:

  • Klientas siunčia naują serverį į serverį.
  • Serveris apdoroja užklausą ir siunčia atsakymą.
  • Klientas niekada neatsako.
  • Serveris nežino, kad klientas negavo atsakymo.
  • Klientas neturi išteklių URL (todėl PUT nėra parinktis) ir kartoja POST.
  • POST nėra idempotentas, o serveris ...

6 žingsnis yra tas, kur žmonės dažnai painiojami dėl to, ką daryti. Tačiau nėra jokios priežasties sukurti šią problemą išspręsti. Vietoj to, HTTP gali būti naudojamas, kaip nurodyta RFC 2616 , ir serveris atsako:

10.4.10 409 Konfliktas

Prašymas negalėjo būti įvykdytas dėl prieštaravimo dabartinei išteklių būsenai. Šis kodas leidžiamas tik tais atvejais, kai tikimasi, kad vartotojas galės išspręsti konfliktą ir vėl išsiųsti užklausą. Atsakymo įstaiga turi turėti pakankamai

informacija vartotojui, kad išsiaiškintų konflikto šaltinį. Idealu atveju atsakymo objektas turi pakankamai informacijos, kad vartotojas ar vartotojo agentas galėtų išspręsti problemą; tačiau tai gali būti neįmanoma ar reikalinga.

Dažniausiai konfliktai atsiranda atsakant į PUT užklausą. Pvz., Jei buvo naudojamas versijas ir PUT objektas įtraukė išteklius, prieštaraujančius anksčiau (trečiosios šalies) prašymui, serveris gali naudoti 409 atsakymą, nurodydamas, kad jis negali vykdyti užklausos. Tokiu atveju greičiausiai bus pateikiamas dviejų versijų skirtumų sąrašas formatu, kurį nustato turinio tipo atsakymas.

Atsakymas su būsenos kodu 409 Konfliktas yra teisinga regresija, nes :

  • Atliekant POST duomenis, turinčius identifikatorių, atitinkantį sistemoje jau esančius išteklius, yra „prieštarauja esamai išteklių būsenai“.
  • Kadangi svarbi dalis yra ta, kad klientas supranta, kad serveris turi savo išteklių ir imasi atitinkamų veiksmų. Tai „situacija (-os), kai tikimasi, kad vartotojas galės išspręsti konfliktą ir vėl išsiųsti užklausą“.
  • Atsakymas, kuriame yra šaltinio, turinčio prieštaringą identifikatorių, URL ir atitinkamos išankstinės išteklių sąlygos suteiks „pakankamai informacijos naudotojui ar naudotojo agentui problemai išspręsti“, kuris yra idealus atvejis RFC 2616.

Atnaujinimas, pagrįstas RFC 7231 leidimu, pakeičiantis 2616

RFC 7231 yra skirtas pakeisti 2616 ir 4.3.3 skyriuje aprašomas galimas atsakymas į POST

Jei POST apdorojimo rezultatas yra lygiavertis esamų išteklių pateikimui, šaltinio serveris gali peradresuoti naudotojo agentą prie šio šaltinio, siųsdamas atsakymą 303 (žr. Skyrių „Kiti“) su esamu išteklių identifikatoriumi lauke „Vieta“. Tai yra privalumas, kad naudotojo agentui suteikiamas išteklių identifikatorius ir pateikiamas vaizdas per bendresnį talpyklos būdą, bet papildomo prašymo sąskaita, jei naudotojo agentas dar nėra išsaugotas talpykloje.

Dabar gali būti viliojanti tiesiog grąžinti 303, jei POST kartojamas. Tačiau taip pat yra priešingai. Grąžinimas 303 bus prasmingas tik tuo atveju, jei keli prašymai sukurti (kurti skirtingus išteklius) grąžina tą patį turinį. Pavyzdys būtų „ačiū, kad siunčiate užklausos pranešimą“, kad klientui nereikia kiekvieną kartą perkrauti. „RFC 7231“ vis dar išlieka 4.2.2 skirsnyje, kad „POST“ neturėtų būti idempotentas ir toliau remia, kad POST turėtų būti naudojamas kūrimui.

Daugiau informacijos apie tai skaitykite straipsnyje .

54
ответ дан Joshcodes 30 окт. '13 в 2:00 2013-10-30 02:00