Albireo zei:
In bovenstaande twee voorbeelden heb je redundant info, want het werkwoord (GET/POST) drukt eigenlijk al die view en insert uit. Eigenlijk is de resource "people" in combinatie met het werkwoord GET of POST designtechnisch gezien een stuk properder.
Albireo zei:
En hier komt dus het verschil met een REST service pas echt naar boven. Dit is dus de "old-school" manier van werken. Elke URL vertegenwoordigt een "action" en een "target". Is dit fout? Nee. Laat dat duidelijk zijn. Mijn ervaring met derde partijen die SOAP of HTTP based target-action of een variant gebruiken voor webservices al heel snel vervallen in request creep.
Bv.
http://mijnapp.be/update-companies-for-person?id=123
http://mijnapp.be/make-person-inactive?id=123
…
Ze gaan m.a.w. acties op een record als aparte url gaan exposen omdat dat binnen die action-based mindset perfect logisch klinkt.
In een REST setup zijn de twee URLs gewoon weeral een PUT op
http://mijnapp.be/people/123 (of
http://mijnapp.be/people?id=123, hoewel ik niet echt voor query parameters in die context ben), waarbij je in je POST params respectievelijk een array van companies doorgeeft of inactive=true.
T is maar een voorbeeld, maar ik zie echt wel dikwijls een wildgroei van calls waarbij verschillende mensen dan ook nog eens verschillende implementaties of meningen over hoe het juist moet gebeuren erop nahouden. Met REST kan dat ook gebeuren, maar de kans is een pak kleiner omdat je met een duidelijke conventie zit (die dikwijls dan nog door generische code zal geïmplementeerd worden en gewoon werken zonder dat er voor elke resource iets moet geschreven worden).
Trouwens, je moet voor REST zelfs absoluut niet die PUT/DELETE gebruiken. Je kan nog altijd die werkwoorden in de URL voorzien (je zal wel nog altijd GET en POST gebruiken, maar dat heeft dan meer met de potentie van die werkwoorden te maken). Om te zien hoe je nog altijd RESTful kan werken zonder die HTTP verbs verwijs ik naar de aanvulling onderaan deze post. Je zal misschien denken: dit is toch identiek aan wat ik doe, maar dat is niet zo. Het werkwoord is een aparte entiteit binnen de URL:
- Jij: view-people.aspx, create-people.aspx, update-people.aspx
- Zij: people/ , people/create, people/update
T is moeilijk om echt 100% duidelijk uit te leggen, ofwel klikt het ofwel klikt het niet
Albireo zei:
Zo hebben ze het mij aangeleerd en zo ziet elke tutorial op het web er ook uit. Maar ik kan de elegantie van de REST-methode zien. Ik kan ook een paar praktische moeilijkheden zien.
Zoals?
Albireo zei:
Ik heb PUT en DELETE nog NOOIT gebruikt. Ik zou eigenlijk niet eens weten hoe je die gebruikt in PHP of ASP.NET. Je hebt daar respectievelijk $_POST en $_GET versus Request.Form en Request.QueryString, maar niets om PUT of DELETE te verwerken (ik vermoed dat je dan low level methods moet bovenhalen, zoals HttpWebRequest).
rest - PHP detecting request type (GET, POST, PUT or DELETE) - Stack Overflow
Er zal voor ASP ook wel genoeg te vinden zijn daarover. Alle webservers de dag van vandaag kennen PUT/PATCH en DELETE (en voor de oude kan het via een automatische parameter injectie gesimuleerd worden, Rails zal bv een POST doen met _method=PUT in de parameters).
Albireo zei:
De vraag is, is het sop de kool waard?
Dat is aan jou om te beslissen. Voor ons biedt REST in elk geval een meerwaarde omdat we er minder code voor moeten schrijven in de backend (generische code doet gans de REST routing en setup) en dat de frontend (Backbone of Ember based meestal) al voorzien zijn op de REST conventies.
In de populaire MVC omgevingen mapt het gewoon perfect op de model-view-controller conventie. Elk model is perfect als een resource te zien, de controllers kunnen perfect op een model mappen en de views kunnen perfect afgeleid worden uit extensie of Accept headers. Je kan natuurlijk ook wel nog altijd resources hebben die niet op een model mappen, zoals bv. cookie-based sessions.
Albireo zei:
De reden dat ik over sessies begon, is omdat die als ik het allemaal goed begrepen heb, het REST-principe schenden. REST is stateless en sessies introduceren net state.
Wel… ja en nee. Als je state wil hebben in REST moet je dat gewoon bij elke request via die unique resource identifiers kunnen doorgeven en dat kunnen perfect via cookies ofzo. Het is een misvatting dat je aan de serverzijde geen state management mag doen.
Laat ons bv. een shopping cart nemen. Het is dus niet zo dat je via REST geen items kan toevoegen/verwijderen aan die persoonlijke shopping cart.
In dat geval moet je shopping cart als een resource zien en heb je een URL zoals
http://mijnapp.be/shopping_cart
Ook daarop kan je weer die GET/POST/DELETE/PATCH/PUT methodiek toepassen voor create/update/delete. Maar een shopping cart is nog altijd persoonlijk, dus zal je via de request headers nog altijd een session maintainen en bij elke request die doorgeven. Dat kan zelfs een cookie value zijn, maar ook perfect iets anders. Zolang de combinatie van alles maar een unieke endpoint heeft en consistent voor alles werkt.
Als we dan toch over sessies bezig zijn, hoe implementeer je sessies dan in een RESTful omgeving? Een sessie is een resource, inloggen is een sessie aanmaken, uitloggen is je sessie afsluiten. Je kan in dit geval dus perfect een url
http://mijnapp.be/sessions hebben waar je een POST naar doet om de sessie te maken (met login en paswoord als params) en een DELETE gebruiken naar die URL om uit te loggen. Net zoals al de rest is dat dus een Representational State Transfer. Het is gewoon consistent.
REST statelessness gaat dus niet over state management aan de serverzijde maar wel over het uniek en dus stateless identificeren van een entiteit/resource.
Aanvulling: bekijk de screencast op
http://sailsjs.org eens om een praktijkvoorbeeld te zien over hoe REST conventies de hoeveelheid code kunnen reduceren.