ugrás a tartalomhoz

REST edit és new hova kerüljön

inf3rno · 2012. Okt. 29. (H), 05.12
Szép napot!

Van néhány kérdésem REST-el kapcsolatban. Vannak alap koncepciók REST-ben, pl hogy accept header-el küldjük, hogy milyen formát akarunk viszont látni, nem pedig .json vagy .html végződéseket teszünk az erőforrás url-jébe. A másik ilyen, hogy amikor lekérdezünk egy erőforrást, és szűrjük, akkor a szűrés adatait a queryString-be tesszük, és nem az url-be.

Amit engem érdekelne, hogy mi a helyzet a new és az edit szavakkal. Az express-resource ezeket automatikusan az url-hez csapja hozzá, viszont az edit szinte biztos, hogy nem oda való, mert az egy módosított formája az erőforrás megjelenítésének. A new már érdekesebb kérdés, mert ott magát a gyűjteményt nem jelenítjük meg, csak egy hozzáadás űrlapot. Bármit ötlet, cikk, leírás, szabvány?
 
4

Már láttam ezt a videot, de

inf3rno · 2012. Okt. 29. (H), 12.35
Már láttam ezt a videot, de emlékeim szerint nincs olyan rész benne, ami ezzel foglalkozna. Ami elég biztos, hogy a http://my.example.com/users/1/birthDate és a http://my.example.com/users/1/edit koncepciók nem férnek össze. A /edit helyett inkább http://my.example.com/users/1?edit kellene.
6

Félreértettelek, akkor nem

pp · 2012. Okt. 29. (H), 14.11
Félreértettelek, akkor nem értem a kérdést. :D
1

Representational state

Poetro · 2012. Okt. 29. (H), 06.56
Representational state transfer
A Beginner’s Introduction to HTTP and REST
Amit engem érdekelne, hogy mi a helyzet a new és az edit szavakkal.

Az űrlapok maguk nem részei a REST-nek. A lényeg, hogy POST-tal küldesz egy űzenetet a resource URL-jére, ekkor jön létre egy új, és egy a resource URL-jére küldött PUT-tal frissíted.

A HTTP 1.1 RFC-je is tartalmaz részleteket a témában.
3

Tudom, hogy nem részei, arra

inf3rno · 2012. Okt. 29. (H), 12.33
Tudom, hogy nem részei, arra vonatkozott a kérdés, hogy a REST elvek szerint az url-ben vagy queryString-ben, esetleg header-ben van e a megfelelő helyük, mert nekem az url-ben nem tetszenek... Az edit vagy a new nem erőforrást reprezentálnak, nincs mögöttük tényleges adat, csak módosító oldalak, ezért nem kerülhetnének az url-be, egész pontosan az url.path-be. A queryString-be kerülhetnek.
7

Szerintem teljesen mindegy

MadBence · 2012. Okt. 29. (H), 17.56
Szerintem teljesen mindegy hova rakod, nekem egy űrlap eleve nem igazán tud beférni a REST filozófiájába.
Ha meg teljesen mindegy, hogy hova kerül, akkor inkább választanám az editable resource opciót, az még kinéz valahogy.
8

Hát ja a klasszikus html

inf3rno · 2012. Okt. 29. (H), 23.55
Hát ja a klasszikus html oldalak nem alkalmasak ilyen nyalánkságokra. Ez a probléma is csak azért jött elő, mert úgy látszik, hogy még azok sincsenek tisztában a REST-el, akik sűrűn használják. Értsd: express-resource fejlesztői.

Ha klasszikus űrlapokat használnék, akkor nekem is teljesen megfelelne a path-be gányolás, mert tökmindegy lenne, hogy hogyan rontom le a felületet, viszont single page appot csinálok, és nem tetszik, hogy afelé terelgetnek, hogy ne REST elveket kövessek. Így nehéz megtanulni egy módszert, ha senki sem tudja igazán, hogy mit jelent...

Btw csinálok egy kisebb projektet marionette-el, aztán írok erről az egész REST, meg single page application témáról egy blog bejegyzést. Talán hosszabb is lesz, bár a többség nem szereti a hosszú cikkeket...
9

REST vagy nem REST

MadBence · 2012. Okt. 30. (K), 00.54
Szerintem ha szigorúan vesszük a REST-et, akkor az azt jelenti, hogy van egy (JSON, vagy XML, lényegtelen) API-d, az egyes resource-ok egyszerű (JSON/XML) objektumok, mindenféle megjelenítésre vonatkozó sallang nélkül.
Nekem logikusnak tűnik akkor inkább egy másik service-t írni, ami ezt az API-t használja, tehát űrlapokat gyárt, megjelenít, stb, és ennek nem is kell REST szerint működnie, lehet bátran gányolni.

Vagy a másik lehetőség, hogy úgy fogjuk föl, hogy a resource/edit maga is egy erőforrás, ami a resource-hoz tartozó űrlapot reprezentál.

Fölösleges ezeken a dolgokon rugózni, mert pl ha JSON-t használsz, az nem lehet REST. Pedig elég népszerű buzzword mostanában a RESTful JSON API és társai.

A REST nem is igazán szabvány (ha mégis az lenne, akkor kérek egy linket rá), hanem egy filozófia, hogy használjuk a HTTP protokoll lehetőségeit (verbs, headers, stb), és ne mindent egy kilométeres XML-ben próbáljunk leírni.
10

A REST szempontjából teljesen

inf3rno · 2012. Okt. 30. (K), 01.01
A REST szempontjából teljesen lényegtelen, hogy mi az adattovábbítási forma, szóval a JSON minden további nélkül lehet REST.
11

Nézd meg a videot, amit pp

inf3rno · 2012. Okt. 30. (K), 01.04
Nézd meg a videot, amit pp linkelt be legelső hozzászólásként. Ott elég világosan elmondják, hogy mi REST és mi nem. Nem standard, amit mondanak, de lehetne az is, mert hibátlan a logikája.
12

Meg fogom nézni a videót, de

MadBence · 2012. Okt. 30. (K), 01.23
Meg fogom nézni a videót, de leszögezem, hogy ami nem szabvány, az nem szabvány, tehát akkor hívom én a szolgáltatásomat RESTfulnak, amikor csak akarom. Bele lehet kötni, de értelmetlen :).

Így többszöri átgondolás után én arra jutottam, hogy az express-resource editable resource elgondolása nem ütközik nálam semmilyen ellentmondásba a REST elvekkel.
13

Hát amíg nincs szabvány

inf3rno · 2012. Okt. 30. (K), 01.34
Hát amíg nincs szabvány arról, hogy mi az, hogy REST, addig nincs értelme erről vitatkozni. Egyébként akkor a videoban egy lehetséges szabvány vázlatot adnak elő, ami egy nagyon logikusan felépített dolog, és mindennek megvan a maga helye benne. Én ezt követem. Amúgy találtam áthidaló megoldást idő közben. Az alap GET-es megjelenítési formával együtt lerántom a létrehozó és módosító űrlapokat is. Ehhez a megoldáshoz még javascriptre sincs szükség, elég a css is az elrejtésükhöz.

Azt hiszem ezt is fogom követni, és nem szórakozok a layout header-ekkel csak akkor, ha nagyon rögös ez az út.
5

A logika a következőt

inf3rno · 2012. Okt. 29. (H), 13.35
A logika a következőt diktálja:

A PUT, POST, DELETE teljesen ugyanazt csinálja a /users/1/edit-nél mint a /users/1-nél. Az elsőt "editable resource"-nak nevezik egyébként. Na mármost mivel ezek ugyanazt csinálják mindkettőnél, csak a GET tér el, ezért nyilvánvaló, hogy ez az "editable resource" nem erőforrás, hanem megjelenítési mód.

Mivel a megjelenítési mód tér el, ezért header-be kell kerülnie. Abban tévedtem, hogy accept header-be, mert egy űrlapot ugyanúgy le lehet írni html-ben, json-ban, xml-ben, stb... Ha az accept header-be kerülne, akkor mindegyiknél létrejönne egy-egy új mime típus, ami marhaság lenne. Helyette kell neki csinálni egy layout headert:

accept: text/html
accept-layout: editable
Ez persze csak arra az esetre igaz, ha single-page javascript alkalmazást csinál az ember. Ha szükség van arra, hogy rendesen kövesse a linkeket, ahol ugye nem lehet plusz header-t küldeni, akkor muszáj valahova az url-be szemetelni. Akkor meg vagy beteszi a path-be az ember, mint egyesek, vagy a queryString-be. Ha már a queryString-be kerül, akkor lehet egy headers tömböt hozzácsapni a queryString-hez, hogy az ilyen megjelenítési információk egy helyen legyenek.

/users/1?headers[accept-layout]=editable
Persze szebb, ha a path-ben van. Igazából tökmindegy, mert már egyik sem REST innentől.
14

Kliens és szerver szétválasztása

pp · 2012. Okt. 30. (K), 05.49
Most már kezdem érteni, hogy mit szeretnél, de egyre jobban azt látom, hogy olyan dolgokat akarsz összekeverni, amit nem kéne.

Hogyan döntöd el a szerver oldalon, hogy a kliens milyen felületi elemet szeretne használni egy elem beviteléhez? Már egy sima varchar-nál(255-nél rövidebb szöveg) is meg fogsz bukni,(lásd twitter pl.), hisz az most textfield lesz vagy textarea?
Egy egész szám az választó lista lesz, radio, vagy textfield? Egy tag-eket tartalmazó tömb az most checkbox lesz, multiple select, vagy autocomplet-es textfield. Ha ez utóbbi akkor honnan fog autocomplettálni. Vagy hogyan, mert ilyen HTML elem nincsen (valamilyen van, de ha nem pont olyan kell?).

Az egésznek pont az lenne a lényeg, hogy szeparáld a kliens és szerver oldalt úgy, hogy egymástól függetlenül tudd fejleszteni.

pp
16

Nem vágom, hogy ez most hogy

inf3rno · 2012. Okt. 30. (K), 17.54
Nem vágom, hogy ez most hogy jött ide, egyáltalán nem erről volt szó.

Annyi volt a probléma, hogy ugyanazt az erőforrást akartam megjeleníti ugyanolyan mime típussal, de eltérő layout-tal. Erre két megoldás van. Az egyikben tudja a REST API, hogy eltérő layout-tal fogom megjeleníteni az adatokat, a másikban nem. Mindkettő megoldható. Az elsőben az API-nak egy extra header-ben küldöd meg, hogy milyen layout-ot szeretnél, a másodiknál meg vagy olyan html-t küld ki az API, amiben az összes szükséges layout eleve jelen van és kliens oldalon választasz css-el, vagy nyers adatot küld ki az API, és a kliens oldali javascript dönti el, hogy milyen layout-ot szór hozzá. A három megoldás közül egyik sem ütközik REST elvekkel.
18

Nem arról beszélek, hogy

pp · 2012. Okt. 30. (K), 21.17
Nem arról beszélek, hogy megoldható-e avagy sem amit akarsz. Nem is arról írtam, hogy egyik vagy másik megoldás a jó avagy sem. Azt írom, hogy amit akarsz szerintem nem üdvözítő. Ha nem választod szét a megjelenítést és az adatok előállítását akkor mindig bele fogsz ütközni falakba, amikor aztán gányolnod kell.

Mert mi van, hogy ha nem lehet valamelyik layout-ot css-el kiválasztani? Mert mondjuk egy olyat szeretnél amit nem szolgált ki a szerver, vagy olyan megoldás kell, amihez más elrendezés kell?

Egyáltalán miért kéne eldöntened az API megtervezésekor, implementálásakor, hogy milyen megjelenésre lesz szükséged? Miért jó az, hogy ha akarsz egy másik megjelenítést akkor a szerverbe, rosszabb esetben az API-ba kell ezt belehárdkódolnod.

Mi van, ha valamelyik kliensnek nem tetszik a már meglévő layout és módosítasz rajta egy kicsit, de másik kliens meg pont azért borul meg/esik szét? Egyáltalán miért kéne ilyenre felkészülni??

Persze, az is lehet, hogy nagyon nem értem, hogy mit akarsz.

Írsz rá egy életszerű példát, amikor az API-t és a szerver oldalt egy cég működteti, és van három kliens amit három másik, egymástól különböző cég üzemeltet egymástól függetlenül, csak az API dokumentációjára támaszkodva?

pp
19

Nekifutok huszadszor is :DA

inf3rno · 2012. Okt. 30. (K), 21.54
Nekifutok huszadszor is :D

A megjelenítés szétválasztásának csak annyi köze van a REST-hez, hogy úgy is megoldható, hogy van egy REST service-ed, ami csak adatot szolgáltat, és van valamilyen kliensed, ami fogadja ezt az adatot. De egyáltalán nem kötelező így megoldani.

Az adatszolgáltatás is egy megjelenítési formája az adatnak. Küldhetetd JSON-ban, XML-ben, vagy amiben csak akarod. Ha eltekintünk a HTML-től, mert látom egyeseknek nagyon bekavart, akkor pusztán JSON-ban is létre lehet hozni ugyanezt a problémát. Ott nincs olyan gát, hogy a böngésző képtelen normálisan kezelni a REST-nek megfelelő kéréseket és válaszokat.

Mondjuk van egy REST service-ed, amiben azt tárolod, hogy mennyi pénzed van, és szeretnéd lekérni valamilyen valutában. A mime típus ugyanúgy JSON minden valuta esetében.

GET /user/me/money
accept: application/json
accept-currency: HUF
Egy hagyományos webalkalmazásnál a currency az kapásból a queryString-be menne, de REST esetében oda csak adat manipuláció mehet. Legalábbis az előadás alapján, amit belinkeltél. Egyébként szerintem nagyon logikus, hogy így választják szét REST-nél a dolgokat:
  • akció -> METHOD-ba
  • api -> url: domain/basePath
  • erőforrás -> url: path
  • adat szűrés -> url: queryString
  • megjelenítés -> header

Szét lehetne máshogy is választani őket, de mivel ők ezt hívják REST-nek, és ők jobban értenek hozzá, mint én, ezért elfogadom.


Egyébként van másik példa is. Mondjuk van egy API-d, amin verzióváltást akarsz eszközölni, és a v2-es API csak részben kompatibilis az előzővel. Van egy mime típusod: application/my-api. Csinálhatod azt, hogy létrehozol minden ilyen verzióváltásnál egy új mime típust: application/my-api2, vagy csinálhatod azt, hogy küldesz egy client-version request header-t, ami alapján eldönti az API, hogy ő ki tudja e szolgálni a kérést, vagy sem. Ha az API-nak éppen olyan részét használja az 1-es verziós kliens, ami ugyanaz a 2-es verzióban is, akkor kiszolgálja, ha meg nem, akkor meg visszaírja, hogy nem támogatott az a kérés a 2-es verzióban, frissítsen klienst.
22

"Egy hagyományos

pp · 2012. Okt. 31. (Sze), 06.35
"Egy hagyományos webalkalmazásnál a currency az kapásból a queryString-be menne, de REST esetében oda csak adat manipuláció mehet."

Az átváltás tipikusan adat manipuláció sztm, nem megjelenítés. De nézzük mondjuk úgy, hogy idő formátumról van szó, és akkor nem lehet így belekötni a felvetésedbe, de az tipikusan belemehet a header-be. (már ha egyáltalán szükség van ilyenre, hisz ez is inkább kliens oldalon implementálandó dolog, nem szerver oldalon... vagy fogalmazzunk úgy, hogy más-más felelősségi kör.)

De visszatérve az eredeti felvetésedre bizton állíthatom, hogy egy user interface az nem csak megjelenítési, hanem igen komoly működési logika is. Tehát nem fogod megúszni, hogy a kliens oldalon ezt implementáld. Ezt kár várni a szervertől.

pp
23

Hát én sem várom tőle.

inf3rno · 2012. Okt. 31. (Sze), 09.33
Hát én sem várom tőle. Elméletileg lehetséges lenne pusztán szerverrel megoldani, ha a böngészőket felkészítenék rá. Jelen esetben viszont muszáj js-t írni, ha REST-es service-el akarunk kommunikálni. Egyébként ez nem is baj, vannak nagyon jó rendszerek js-ben. Én most backbone.marionette-el rakok össze alkalmazást, meg használok kb 10 ksiebb-nagyobb libet meg plugint hozzá... Elég vicces, hogy szinte mindent össze lehet halászni netről. Egyedül a validálással vagyok gondban, mert abból nem találtam olyat, ami i18n-t támogatja, szóval kénytelen leszek sajátot írni.
15

adatok kezelése

T.G · 2012. Okt. 30. (K), 12.36
Nekem nem világos, hogy a megjelenítést/szerkesztést miért kevered ennyire bele az adatok kezelésébe. Ahogy én értem, amikor adatokat kérünk le, akkor GET, amikor újat hozunk létre akkor POST, módosítás esetén PUT és törlés esetén DELETE kérést ad a kliens a szerver felé, ugyanarra az url-re. Nincs szó sem megjelenítésről, sem szerkesztőfelületről. Ez nem is része ennek az egésznek.

Mivel nem böngészőben vagyunk, a szép url-ek előnyei nem érvényesülnek, így az users?id=1 és az users/1 között csupán annyi a különbség, hogy az első rugalmasabb felületet biztosít, ha nem csak azonosítóra szűrhetünk: users?first_name=Bela

Én kifejezetten szeretem a JSON-t, így erősnek érzem, hogy a JSON nem REST, a hypermedia kifejezést meg most hallottam először, és sajnálom, hogy a JSON nem az. :) A queryString-ben adom át, hogy milyen formában kérem az adatokat, illetve milyen formában adom az adatokat.

Zárójelben, ha bele akarjuk keverni a megjelenést, szerkesztést, akkor miért nem egy másik url-en kérjük le a template-et, amire majd ráhúzzuk az adatokat? (azaz a template is egy adat, csak nem felhasználó adat)
17

Mivel nem böngészőben

inf3rno · 2012. Okt. 30. (K), 18.17
Nekem nem világos, hogy a megjelenítést/szerkesztést miért kevered ennyire bele az adatok kezelésébe. Ahogy én értem, amikor adatokat kérünk le, akkor GET, amikor újat hozunk létre akkor POST, módosítás esetén PUT és törlés esetén DELETE kérést ad a kliens a szerver felé, ugyanarra az url-re. Nincs szó sem megjelenítésről, sem szerkesztőfelületről. Ez nem is része ennek az egésznek.

De része.

Mivel nem böngészőben vagyunk, a szép url-ek előnyei nem érvényesülnek, így az users?id=1 és az users/1 között csupán annyi a különbség, hogy az első rugalmasabb felületet biztosít, ha nem csak azonosítóra szűrhetünk: users?first_name=Bela


Ha van még al-erőforrás a user alatt, akkor jobb slash-el elválasztani. Mondjuk ha külön akarod változtatni a jelszót, akkor

PUT /users/1/password | "..."
Sokkal logikusabb, mint a

PUT /users?id=1 | {password: "..."}
Az utóbbiról inkább azt gondolná az ember, hogy az összes felhasználói adatot átküldöd, nem csak a jelszót.

Ha ennél mélyebben van az adat, amihez hozzá akarsz nyúlni, akkor meg már nagy a gond:

PUT /users/1/cars/2/color | "red"
Ezt hogy csinálod meg a te queryString-es módszereddel? (sehogy, mert a queryString csak adat szűrésre való, egyedül úgy menne, ha a teljes kocsi listád lekéred, módosítod, és visszatöltöd)

Zárójelben, ha bele akarjuk keverni a megjelenést, szerkesztést, akkor miért nem egy másik url-en kérjük le a template-et, amire majd ráhúzzuk az adatokat? (azaz a template is egy adat, csak nem felhasználó adat)


Az, hogy milyen formában kapod az adatot attól függ, hogy mit küldesz accept header-nek. Ha te application/json-t küldesz, akkor json-ban kapod, ha text/html-t, akkor meg html-ben. Nálam az úgy fog menni, hogy az api csak adatot szolgáltat, mellette meg lesz egy gui, ami meg egy kezdő html-t, meg egy csomó js fájl szolgáltat sablonokkal. Szóval jogos a felvetésed, tényleg így érdemes csinálni.

A megjelenítést egyáltalán nem "belekevertem", egyszerűen arról van szó, hogy azonos mime típushoz több megjelenítési forma is tartozhat, és hogy ez az információ hol utazzon. Ez olyan dolog, amit nem lehet sablon fájlokkal megoldani. Pl van egy REST alkalmazásom, ami csakis képeket szolgál ki image/jpeg-ben. Kérek tőle egy képet, de azt mondom neki, hogy legyen a képen 10px-es keret, és a színe legyen piros. Ezt te hogy oldanád meg?

GET /images/12345
accept: image/jpeg
accept-layout: {border: {color: "red", size: 10}}
Én így.


Az a gond, hogy félreérted ezt az egész REST-et. Ez nem csak arra jó, hogy mondjuk csakis JSON-ban nyers adatot szolgáltass, hanem bármilyen formában lehet vele adatot szolgáltatni és nem csak nyers formában, hanem formázott módon is. A lényeg, hogy request header-ben jelezni kell, hogy milyen formában kéred az adatot, response header-ben meg visszajelezni, hogy ebben és ebben a formában kapod.

Azért lehet szükség plusz header-ekre, mert előfordulhat, hogy ugyanolyan mime típusban akarsz megjeleníteni egy erőforrást, de eltérő layout-al.

Azért ezt hozzáteszem, hogy pp videojában van ez a fajta meghatározás a REST-re. Amíg nincs szabványosítva, addig mindenki azt nevez REST-nek, amit akar.
20

Mi a baj a put/post kérésekkel?

T.G · 2012. Okt. 30. (K), 22.18
Egyik oldalról jogos, újragondolom a REST-ben rejlő lehetőségeket, én mindennek egy szűk metszetét használtam csak, de...
...pontosan miért kérdés, hogy mi a new és mi az edit? Ha sok minden nincs is szabályozva, de ezek igen. Post kérés és put kérés. Miért az url-ben akarod ezeket megadni? Mi előnyöd származik ebből?
21

Félreértetted az egészet.Az

inf3rno · 2012. Okt. 30. (K), 22.39
Félreértetted az egészet.

Az edit és a new azok az űrlapokat jelölik az url-ben, amiknek nyilván get-tel kell lejönniük, nem pedig a create és update kéréseket, amik meg nyilván post-al és put-tal mennek.

Egyébként ebben a félreértésben én vagyok a hibás. Be kellett volna tennem ezt:

var orderedActions = [
   'index' // GET /
  , 'new' // GET /new
  , 'create' // POST /
  , 'show' // GET /:id
  , 'edit' // GET /edit/:id
  , 'update' // PUT /:id
  , 'destroy' // DEL /:id
];
a kérdés mellé. A különböző action-öket erre fordítja le default az express-resource. Itt a GET /new és a GET /edit/:id, ami nem felel meg a REST-nek az említett video alapján. Helyettük GET /:id | layout: editable kellene, vagy a GET /:id-vel és a GET /-el le kéne jönniük azoknak az űrlapoknak is, ha az accept header-ben text/html van. Helyette ők elnevezték ezeket editable resource-nak, ami egy nagyon hibás lépés volt. Ennek a lépésnek meg az volt az oka, hogy a böngészők nem kompatibilisek REST-el. Egy sima html webalkalmazást nem tudsz kiszolgálni REST kompatibilisen, csak egy statikus html oldalt, vagy egy olyat, ami javascriptben küldi és fogadja az adatot.