REST API HTTP kódok

Üdv,

ma voltam egy konferencián, ahol egy a közeljövőben bevezetésre kerülő publikus API volt a téma.

Az előadók közül az egyik bemutatta az API-t: egy HTTPS-re épülő REST API, amely csak POST metódusokat fogad.

Hangsúlyozta, hogy minden választ státusszal együtt le kell kezelni.

A kérdések szekcióban megkérdeztem, hogy mi a teendő 5XX-es válaszkód esetén, mivel az szerver oldali hibára utal.

Egy érintett fejlesztő vette át a mikrofont, aki közölte, hogy minden hiba 500-as lesz, mivel REST API-ról van szó, nem küldhet 4XX-as kódot. Példának hozta az authentikációt, hogy hibás jelszó esetén nem küldhet vissza 401/403-as választ.

Én nem igazán értem ezt, valaki kegyelmezzen meg, és mondja el, miért nem lehet ilyenkor 4XX-as kódot visszaküldeni. Keresgéltem a neten, de ilyet sehol nem találtam.

Hozzászólások

Kövezzetek meg, de az említett kolléga baromságokat beszélt.
500-as error az internal server error, ergó mindenképpen az api belső hibájára kell utaljon.

Több REST api-t is csináltam már, és mindegyiknél törekedtem arra, hogy a válaszkódok is stimmeljenek.

Nah most a másik téma, hogy REST api ami CSAK POST hívásokat fogad. Nokomment... Azt elfogadom, hogy bizonyos esetben egy GET-es hívás helyett POST-osat követelek meg mert esetleg sok és hosszú adatokat kell küldeni amit nem teszek be a GET-be, de, hogy mindig...

A fenti cég nem állami szférában tevékenykedik? :)

Köszi,

500-as error az internal server error - én nem explicit az 500-as kódról beszéltem, hanem 5XX-ről (4XX helyett).
Erre gondolok: https://restfulapi.net/http-status-codes/ - de ugye ez nem valami referencia, csak egy oldal a sok közül.

REST api ami CSAK POST hívásokat fogad - ez félrement, itt konkrétan ez az API fogad csak POST hívásokat, ezzel amúgy semmi gondom.

A fenti cég nem állami szférában tevékenykedik? :) - meleg, kicsit meleg... :)

Oké, az 500 az internal de a lényeg, hogy 500-al nem user error-t kezelünk le, a lényeget értetted.
A REST api-nál fontos információ az is, hogy mi a method. A csak POST ezt heréli ki.

Szerény véleményem, hogy a fenti api nem REST api, csak egy HTTP hívásokból álló api végpontcsokor :)

a lényeget értetted - persze, hogy ezt értettem - az előadást nem értettem :).

A csak POST ezt heréli ki. - kliens szempontjából szerintem ezzel együtt lehet élni :).

...csak egy HTTP hívásokból álló api végpontcsokor :) - biztos én vagyok már öreg, de nem érdekel, ki minek nevezi. Működjön lehetőleg, és ne kelljen kókányolni :).

Nah most a másik téma, hogy REST api ami CSAK POST hívásokat fogad. Nokomment... Azt elfogadom, hogy bizonyos esetben egy GET-es hívás helyett POST-osat követelek meg mert esetleg sok és hosszú adatokat kell küldeni amit nem teszek be a GET-be, de, hogy mindig...

arrol se feledkezzunk meg, hogy POST-ot alapertelmezetten nem szokrunk logolni ;)

Az van, hogy a REST ebben a formában egy büdös nagy layer violation, by design. A kolléga ezt próbálta feloldani, mondjuk ritka idióta módon.

Mondjuk sajnos nem nagyon van neki (jó) megoldása, hogy keverednek a HTTP saját status üzenetei a tetejére hákolt protokoléval. Lehet rühellni a soapot, de ott legalább ez nem volt. És nem segít, hogy a webes gyerekek baromira nem értik, mit csinálnak. Kedvenc példám a swagger, ami azért eléggé terjed, és a példa doksija lendületből felüldefiniálja helyenként a 400-at, valami invalid status id-ra, ami tök API specifikus. Aztán ha valami alatta vagy közben generál egy 400at, akkor majd lehet pingvinezni kliens oldalon, hogy most akkor mi a baj.

Nem annyira gáz ez azért. A HTTP layerben egy generikus hibakódot lehet dobni, amiből már nagyjából sejthető, mi történt. Ez inkább vonatkozik a HTTP kliensre, mint az alkalmazásra. És ha van bővebb alkalmazás-specifikus infó, azt a saját protokollba lehet beletenni pluszban. Nagyon sokfajta hibalehetőségre létezik jó HTTP kód, amire nem, arra mehet a 400/500. Tehát nem értek avval egyet, hogy keveredés van, csak az alkalmazás rétegből egy részletesebb, kiegészítő infót is ki lehet nyerni. Ha pl. HTTP authentikációt használunk, teljesen jogos, hogy azt a HTTP réteg fogja visszadobni 401/403 kóddal, és nem az alkalmazás. Nézd meg pl. itt, milyen részletek vannak a HTTP hibakódon túl: https://cloud.google.com/storage/docs/json_api/v1/status-codes

> Nem annyira gáz ez azért.

Nem annyira gáz, ha gondolkozik rajta az ember, de attól még gáz marad. Az a baj az ilyen "Ez inkább vonatkozik a HTTP kliensre, mint az alkalmazásra" mondásokkal, hogy teljesen szubjektívek. Nem lehet érdemben egyértelműen megmondani, hogy az a 401, az azért 401, mert az alkalmazás mondta, hogy menj a francba, vagy mondjuk előtte egy tűzfal, ergo ez egy application hiba, vagy egy network / transport hiba. És amikor még jönnek az ilyen hozzáértők, mint a fenti fejlesztő, aki emiatt (gondolom) be akarja pakolni a 4xx (you fucked up) üzeneteket is az 5xx-as zónába, ami ugye az 'I fucked up', az... hát nem segít.

> Tehát nem értek avval egyet, hogy keveredés van,

Ez örömteli, de ettől még amikor a REST azt definiálja, hogy használd a HTTP protokol mezőit az alkalmazás rétegben, akkor definíció szerint az van.
Ilyen alapon egyszerűen lehetne egy RST-t is állítani az alatta menő TCPben, mikor úgy gondolom, hogy hülyeséget csinálsz, ezért nem beszélgetek veled. :)

Sok példa van arra, hogy eltérő rétegek tudnak egymásról. A puritán elmélet és a valóság között van egy kis különbség.

Egy SMTP szerver attól függően utasíthat el egy kérést, hogy éppen milyen porton, és SSL-en vagy nem azon keresztül beszélgetsz hozzá.

Egy webszerver is tud máshogy működni annak fényében, hogy az SSL handshake-ben volt-e SNI vagy sem.

RPC over HTTP esetén ugye a tiszta megoldás az lenne, ha hibás kérés esetén 200-as HTTP hibakód menne vissza, ahol a válaszban van alkalmazás szinten a hiba/siker leírója. De ez a HTTP már csak ilyen, hogy kicsit összeolvad a felette levő réteggel.

Még egy példa. Szinte tök mindegy egy böngészőnek, hogy a "keresett oldal nem található" szöveg 200-as vagy 404-es kóddal megy vissza, ugyanúgy le fogja renderelni neked a kapott oldalt. Pedig ugye a tiszta dolog az lenne, ha 404-es kód mellé nem menne tartalom, hiszen pont arról szól, hogy nem találta a keresett dolgot. Mégis jobb a felhasználónak, ha egy szépen renderelt oldal kap, ahol vannak linkek, stb.

Nem mondom, hogy ez feltétlenül szép, de ezeket néha a szükség szüli, néha bénázás.

Persze, hogy vannak ilyenek. Ettől még ez nem olyan jó. A REST meg kifejezetten propagálja ezt, ráadásul úgy, hogy az alul levő rétegnek kellene felkészülni arra, hogy felette okoskodnak, ami nem jellemző irány.

Értem én, hogy véded ezt, hogy ez így jó, de vedd észre, hogy én alapvetően csak annyit állítottam, hogy ez by definition ilyen.

Egyrészt nem azt mondom, hogy jó, hanem hogy ezt szülte a gyakorlat, és jobb elfogadni, mint az elméletet erőltetni.

Másrészt azt mondom, hogy nem by definition. Eleve van egy félreértés.

Létezik tiszta REST, amikor nincs semmi egyedi logika (és így semmi egyedi hibakód sincs). Hogy nézne ki egy CRUD API, ahol egy adatbázisból entitásokat kérsz le, hozol létre, módosítasz? GET-tel lekéred, ha nincs olyan, 404. PUT-tal hozod létre, stb. Itt a HTTP maga a logika, a HTTP fölött már csak entitások vannak, nem a kérésre szóló egyedileg összerakott üzenetek.

És létezik RPC over HTTP. Mint írtam, itt az lenne a tiszta, ha minden egyes RPC kérésre 200-as kód jönne vissza hiba esetén, és a HTTP válasz tartalmazná XML vagy bármilyen formában, hogy hiba történt-e vagy sem. Ha nem található a HTTP végpont, akihez beszélünk (pl. nincs /GetFooBar mert át lett nevezve /GetFoo-ra), 404 jön vissza, de ha nem található egy erőforrás, amiről az RPC szól (pl. /GetFoo végpont van, de az 5-ös azonosítójú Foo már törölve lett), akkor 200-as kód illik hozzá.

Külön-külön ezeket teljesen tisztán meg lehetne csinálni. Tehát ezért nem fucked by design.

A gyakorlat viszont az, hogy ez a kettő keveredni szokott, mert egyszerű CRUD hívásokra egyszerűbb az előbbi, és az élet sosem egyszerű, mindig kelleni fog valami egyedi RPC hívás (bonyolultabb POST vagy akár több entitást magába foglaló GET), akkor meg jobb az utóbbi.

Végső soron az számít, hogy dokumentálva van-e, kliens oldalról könnyen használható-e, működik-e.

> hanem hogy ezt szülte a gyakorlat, és jobb elfogadni, mint az elméletet erőltetni.

A gyakorlat már rengeteg talicska szart szült ebben a szakmában. Ezt el kell fogadni, de érdemes tisztában lenni az elmélettel, úgy egy kicsit könnyebb szart lapátolni.

>Létezik tiszta REST, amikor nincs semmi egyedi logika (és így semmi egyedi hibakód sincs). Hogy nézne ki egy CRUD API, ahol egy adatbázisból entitásokat kérsz le, hozol létre, módosítasz? GET-tel lekéred, ha nincs olyan, 404. PUT-tal hozod létre, stb. Itt a HTTP maga a logika, a HTTP fölött már csak entitások vannak, nem a kérésre szóló egyedileg összerakott üzenetek.

Ja. És ennek a neve HTTP :)

> És létezik RPC over HTTP. Mint írtam, itt az lenne a tiszta, ha minden egyes RPC kérésre 200-as kód jönne vissza hiba esetén, és a HTTP válasz tartalmazná XML vagy bármilyen formában, hogy hiba történt-e vagy sem. Ha nem található a HTTP végpont, akihez beszélünk (pl. nincs /GetFooBar mert át lett nevezve /GetFoo-ra), 404 jön vissza, de ha nem található egy erőforrás, amiről az RPC szól (pl. /GetFoo végpont van, de az 5-ös azonosítójú Foo már törölve lett), akkor 200-as kód illik hozzá.

Még pár kör, és eljutunk odáig, hogy feltalálod a SOAPot :) Egyelőre még kevered a HTTP hibaüzeneteit a protokol hibaüzeneteivel :)

> Külön-külön ezeket teljesen tisztán meg lehetne csinálni. Tehát ezért nem fucked by design.

Én nem azt mondtam, hogy fucked by design, hanem azt, hogy layer violation by design.

> Végső soron az számít, hogy dokumentálva van-e, kliens oldalról könnyen használható-e, működik-e.

Igen, teljesen jellemző hozzáállás, hogy a fejlesztők elfelejtik a köztes infrastruktúrát :)

A layer violation attól még layer violation marad, hogy vannak olyan "eszközök" (olykor protokollok is), amelyek az implementációjukkal by design elkövetik.

És lehet mondani, hogy hát így a gyakorlat meg úgy.

Aztán meg mikor nyílnak rá sorban a CVE-k, meg egy eszköz/ protokoll x-edik verziója jelenik meg, mert még mindig csak tákolt használhatalan fostenger, akkor rá lehet jönni, hogy azért mégiscsak volt egy két jó elgondolás abban az osi-ban.

A HTTP nem egy köztes réteg a modellben, hanem AZ alkalmazás réteg. HTTP keretbe te a fejlécben (Content-Type) meghatározott módon kódolva a konkrét üzenetet teszed. Lehet persze köztes rétegként használni (pl. SOAP), de pont, hogy úgy lesz gány, mivel oda kb. felesleges a HTTP tudása.

A REST nem HTTP feletti layer akarna lenni, aki belegányolja a HTTP fejléceibe, hibakódjaiba a saját működési részleteit, hanem inkább egy irányelv ahhoz, hogyan használd a HTTP-t.

Attól, hogy REST címszó alatt általában mezei JSON RPC alá dugnak HTTP-t, mert ehhez vannak kulcsrakész, bevált megoldások és mert ehhez értenek, attól nem lesz "layer violation, by design".

Először is szeretném felhívni rá a szíves figyelmedet, hogy az "ebben a formában" pontosan ezt értettem: "Attól, hogy REST címszó alatt általában mezei JSON RPC alá dugnak HTTP-t". Szóval mikor már ott tartunk, hogy "mert ehhez [ a nem resthez] vannak kulcsrakész, bevált megoldások [amiket valamiért restnek neveznek]", akkor az számomra by design.

Másodszor:
> A HTTP nem egy köztes réteg a modellben, hanem AZ alkalmazás réteg.

A HTTP nem tud alaklmazás réteg lenni, csak akkor ha nincsen egyébként alkalmazásod. Értem én, hogy lent erről szól a durván elméleti vita, hogy semmi, ami statet hordoz, az nem REST, és hogy mi számít statenek :)

> hanem inkább egy irányelv ahhoz, hogyan használd a HTTP-t.

Jó, én meggyőzhető vagyok arról, hogy a REST igazából csak egy felesleges buzzword a HTTP felett :) Ami ugyanis semmi mást nem csinál, csak HTTPt, az HTTP.

"Mondjuk sajnos nem nagyon van neki (jó) megoldása, hogy keverednek a HTTP saját status üzenetei a tetejére hákolt protokoléval. "

Na igen... Amikor vadászni kell a HTTP státusz kódot a domain specifikus válaszra, az mindig öröm.

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

A timestamp a kérés beküldésének időpontja a kliens órája szerint. A timestamp-nak a
kérésben UTC formátum szerint kell érkeznie. Ez magyarországi időzóna esetén:
DT (téli időszámítás) idején GMT+1 órát
DST (nyári időszámítás) esetén GMT+2 órát jelent. A tag értéke beleszámít a requestSignature
értékébe.
A dátumokkal kapcsolatosan a Helyi idő konvertálása UTC időre fejezet ad felvilágosítást. 

Csak belelapoztam. timestamp UTC ->formátumban<- (!!!?!??) Szóval helyi idő utc formátumban? De hát az utc az PONT nem helyi idő, az utc az nem formátum... WTF?

"A fenti cég nem állami szférában tevékenykedik? :) - meleg, kicsit meleg... :)" ha ez az a fejlesztés amire gondolunk, ott sok fura dolog van.

Nem ismerem ezt az API-t, de az alapján amit írtál: feltételezem a belső hibára ad 500-at, a többi üzemszerű hibakódot/választ pedig a response body-ban adja vissza (gondolom). A GET és POST is rendben lehet szerintem, itt pl a message-ben, vagy url-ben mondod meg mit szeretnél, nem a method-ban. (de van ahol nem is a fejlesztőn múlik, hogy csak GET és POST van, ha az a szabály, hogy max ezeket használhatja, mert ebből hátha nem lesz biztonsági probléma...)

Azert vannak a rohad kodok, hogy hasznaljuk oket. Es ha nem "szabvanyos" a hibakod, akkor nem lesz "szabvanyos" a hiba kezeles. Azt eredmenyezi, hogy kliens oldalon kell kokany logikat epiteni, vagy minden "unknown error" lesz. Az mas kerdes, hogy a 401/403 security okokbol elrejtheto, de azert had tudja mar a user, hogy o rontott el valamit, vagy a szerver doglott meg. Nem beszelve arrol, hogy manapsag mar a kutya sem kezzel irja a klienseket, hanem vagy felhasznal egy restful klienst vagy general egyet az adott apihoz.

Nem akarom a kollegat bantani vagy megitelni, foleg nem egy mas altal idezett szoveg alapjan, de nagy butasagokat mondott.

-
Fájl feltöltése Github tárolóba

Az mas kerdes, hogy a 401/403 security okokbol elrejtheto
Erdekes, ez szoget utott a fejembe, es most utanaolvastam:
1) RFC-szerint (https://tools.ietf.org/html/rfc7231#section-6.5.3) tenyleg valid, hogy mokolnak a 403 vs 404-ekkel.
2) Ugyanakkor az RFC szerint pont forditva valid, mint ahogy sokan csinaljak: gyakori, hogy 403-at (rosszabb esetben 401-et) adnak vissza arra is, ami amugy 404 lenne. Ugyanakkor az RFC eppen azt mondja, hogy 404-nek lehet hazudni azt, ami letezik, de autentikaciot/autorizaciot igenyelne.
---
Régóta vágyok én, az androidok mezonkincsére már!

Aha, szóval te voltál az! Ott ültem előtted egy sorral :)

Ilyenkor mindig felmerül bennem a kérdés, hogy miért mindig a hülyék magabiztosak magukban?

A REST alapvetően arról szól, hogy van valahol egy csomó stateless resource és azokat HTTP metódusokkal, HTTP protokoll használatával elérem. Néha módosítom, de a módosítás nem komplex és csak az adott erőforrást érinti.

Az RPC pedig alapvetően arról szól, hogy meghívok egy komplex függvényt valahol a távolban, aminek adok paramétereket és várok tőle valamilyen eredményt.

És általában - szerintem - annyi a baj, hogy keverjük az RPC hívásokat és a HTTP hívásokat és ezt egységesen REST-nek nevezzük.

Hatalmas +1!

A legtobb fejleszto nem tudja a kulonbseget es ugyanugy mint ahogyan az elcseszett Scrum-nal szokas mondani, azt mondjak hogy hat ez nem TELJESEN REST, de azert hivjuk REST-nek.

Mondjuk azon en is sokat gondolkodtam mar, hogy hogyan lehet pure REST API-t csinalni, mert azert a legtobb alkalmazas, nem csak CRUD methodusok osszessege es amint valamilyen action-t (peldaul az app-nak van egy bonyolultabb workflow-ja) akarsz backend oldalon triggerelni, akkor borul az egesz REST design.

Én úgy gondolom, hogy nem attól REST API a REST API, hogy HTTP protokolon keresztül megy, METHOD-okat, és HTTP hibakódokat használ. Akár HTTP-re épülő saját protokollon keresztül is mehet, vagy füstjelekkel. Ami lényeges (pongyolán fogalmazva): resource-okat érsz el vele, módosítasz, egységes interfésze van, állapotmentes, kliens szerver architectura, cache-elhetőség, stb... A SOAP vagy RPC nem ugyanez. Nem akarom védeni az API készítőt (mert nem ismerem az API-t, és nem voltam az előadáson, lehet hogy hülyeségeket beszélt), de akár REST API is lehet még, ami teljesen rendben van..

És most komolyan senki nem volt olyan tökös az előadáson, hogy megmondja neki, hogy irtó nagy hülyeségeket beszél? Csendben elfogadtátok, hogy oké, akkor ez így lesz? Hát akkor szívjatok is csak vele...

Az igazsághoz tartozik, hogy (így utólag végiggondolva - ott ez nem derült ki) ő nem a HTTP AUTH-ra gondolt, hanem az XML-ben levő user/pass párosra.

A példában konkrétan az volt (amiért én vitába szálltam vele), hogy az authentikáció pont 4XX-es hibakód, erre jött az, hogy de ez itt REST API, és minden ilyen hiba 5XX-re van map-elve.

Ettől függetlenül valószínűleg még nincs igaza. Nagyon leegyszerűsítve a hibakódokat:

- 4xx: A kliensnél történt a hiba (rosszul formázott kérés, hibás felhasználó vagy jelszó, érvénytelen adat, stb).
- 5xx: A kiszolgálónál történt a hiba (nem kezeltek le egy exception-t, leállt a szerver, stb).

Ennyit kell csak megjegyezni és ez alapján dönteni.

Nem ennél a kormányzati API-nál (ott nem volt konferencia), de volt már rá példa, hogy egy konferencián a kérdéseknél elmondtam az előadónak, hogy szinte semmi sem úgy van ahogy ő azt állította. Érdekes módon, két hét múlva a konferencia szervezői ugyabban a témában egy újabb előadást szerveztek egy másik előadóval, csak akkor már helyes információk hangzottak el. Nem kell birkának lenni.

Csak a referencia vegett:

Ajanlott eloadas: Hadi Hariri — Embracing HTTP in the era of REST API's

Gyakran hasznalatos HTTP metodusok:

- OPTIONS: Rendelkezesre allo metodusok, illetve tovabbi vegpontok lekerdezese az adott vegpontra. (Discoverability)
- GET: Eroforras lekerese (vagy listazasa). Pl: GET /blogposts v. GET /blogposts/1
- POST: Uj eroforras letrehozasa, pl: POST /blogposts
- PUT: Eroforras felulirasa, pl: PUT /blogposts/1
- PATCH: Eroforras reszleges modositasa, pl: PATCH /blogposts/1
- DELETE: Eroforras torlese, pl: DELETE /blogposts/1

Gyakran hasznalatos 4xx statusz kodok:

- 400: A kliens hulyeseget kuldott. Lasd meg: RFC7231
- 401: Ilyet kuldhet vissza az API, de kuldenie kell melle egy WWW-Authenticate fejlecet is. Ez a WWW-Authenticate hivatott megmondani a kliensnek hogy hogyan kell autentikalnia. Tovabbi infok: WWW-Authenticate @ MDN RFC7235
- 403: A kert eroforras az adott jogosultsagi szinttel nem elerheto vagy egyaltalan nem elerheto. Lasd meg: RFC7231
- 404: Az adott eroforras nem talalhato. Lasd meg: RFC7231
- 405: GET helyett POST-ot kuldott a kliens, stb. Lasd meg: RFC7231
- 406: A kliens az Accept fejlecben olyan adattipust vagy egyeb kovetelmenyt kert, ami nem all rendelkezesre. (pl. YAML-t kert, de Te csak JSON-t tamogatsz.) Lasd meg: RFC7231
- 409: Konfliktus, pl. az adott eroforras mar letezik (unique key para) Lasd meg: RFC7231
- 410: Az eroforras valaha letezett, de most mar nem letezik. Lasd meg: RFC7231
- 415: A kliens altal kuldott adattipus nem tamogatott, pl YAML-t kuldott de a szerver csak JSON-t tamogat. Lasd meg: RFC7231

Gyakran hasznalt fejlecek:

- Authorization: usernev/jelszo vagy API kulcs kuldesere alkalmas.
- WWW-Authenticate: autentikacios utasitas 401-es statusz kod eseten
- Content-Type: a keres vagy valasz adattipus a es potencialisan kodolasa
- Content-Encoding: tomorites tipusa (pl. gzip). Tobbnyire a webszerver megoldja, nem kell vele foglalkozni
- Accept: csak keresekben, megmondja a szervernek hogy milyen adatformatumban szeretne az adatot.
- Accept-Encoding: a Content-Encodinghoz megmondja a szervernek hogy milyen tomoritessel keri az adatot.
- Accept-Language: megmondja a szervernek hogy milyen nyelven kuldje az adatot
- Accept-Charset: megmondja a szervernek hogy milyen karakterkodolassal kuldje a valaszt.

Egyebkent nem kell mindenkinek REST API-t csinalnia, az amit az eloado leirt az egy sima RPC-jellegu API. Az is teljesen jol hasznalhato ha jol van megtervezve, csak nevezzuk neven a gyereket. (Az eloado leirt habitusabol gyanitom hogy itt a jol megtervezes nem all fent.)

--
Pásztor János

Az a nagy budos igazsag, hogy itt az eloadot maximum a tudatlansagaert es az azzal parosulo hamis biztonsagerzeteert lehetne megfeddni, mert amit csinalt az gyakorlatilag egy RPC API, (more or less) de ezzel egyebkent onmagaban semmi baj nem lenne, az RPC egy teljesen jol hasznalhato eszkoz sok feladatra.

Ezzel szemben egy normalis, tisztesseges (HATEOAS) REST API-t implementalni baromi nagy melo. (Lasd a fenti fejlec- es statusz kod tomkelegeket erosen ajanlott tamogatni ha tisztesseges HTTP implementaciot akarsz.) Raadasul tenyleg hozza kot a HTTP-hez, az informacio fele fejlecekben van, a masik fele meg a bodyban JSON formatumban. Ha mondjuk szeretned az uzeneteket 1:1 behanyni egy queue-ba, akkor itt mar mindjart problemakba utkozol es modositanod kell az API-n vagy atalakitani az adatokat szerver oldalon, ami kulon orom.

Szal jo divat ez a REST, es sok mindenki szereti mert lehet curl-bol API-kat hivogatni egyszeruen, de attol meg nem ez az egyetlen eszkoz a vilagon. :)

--
Pásztor János

Szerintem ez egy jó összefoglaló: https://www.mulesoft.com/resources/api/restful-api

"One of the most popular types of API is REST or, as they’re sometimes known, RESTful APIs. REST or RESTful APIs were designed to take advantage of existing protocols. While REST - or Representational State Transfer - can be used over nearly any protocol, when used for web APIs it typically takes advantage of HTTP. This means that developers have no need to install additional software or libraries when creating a REST API."

Bocsi, nem vitatkozni akarok, csak elvi kérdés szerintem: Szerintem nem köt a HTTP-hez. (Az más kérdés, hogy adja magát, hogy az legyen, és ez így alakult ki.) Emiatt REST: Representational State Transfer.

Nézd, az egész REST lószar innen indult: https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertati…

Minden más, ami ettől eltérő értelmezés a témakörben (például az, hogy nem köt a HTTP-hez), az csak a kihullott szar visszalapátolása a lóba. Legalábbis annak megpróbálása. Vagy a megpróbálás megmagyarázása.

Én nem látom ez alapján, hogy pl egy egyébként is HTTP-re épülő megoldásnál, ahol POST-ot használsz, és a hibakódot nem a HTTP státuszban adod vissza, milyen komplex workaround kellene. Egy teljesen saját protokollt kifejleszteni pedig nyilván (értelmetlen) feladat lenne, ezért használják normális helyen a HTTP-t, lehetőleg úgy, ahogy elterjedt. (nem ez ellen vagyok, ha van lehetőség, akkor method + hibakód, a HTTP lehetőségeit kihasználva). A REST architektúra kérdés, a HTTP-t pedig a megvalósításhoz használod.

"A REST architektúra kérdés, a HTTP-t pedig a megvalósításhoz használod."

Nem, nincs olyan, hogy REST architektúra... ha nem HTTP felett van a REST, akkor az nem REST, hanem valami más, ami olyan, mint a REST. A SOAP például nincs kötve transzport réteghez, azt bármin át tudod küldeni, akár még levélben is postással vagy telefonon élőszóban diktálva, mert elkülönül a transzport réteg, az envelope és a body is.

A REST esetén nincs ilyen elkülönülés, nincs igazi struktúrád se, amihez tartanod kellene magad és szerves része a hyper(text|media) közeg, attól nem tudod érdemben elválasztani, nem tudod csak úgy kicserélni a HTTP-t bármi másra anélkül, hogy mélyen bele ne kellene nyúlnod az egész stack-be.

A disszertáció fedőlapját nézd meg: "Architectural Styles and the Design of Network-based Software Architectures DISSERTATION"

Még egyszer: tényleg nem kötözködni akarok, csak mégis úgy gondolom, hogy a HTTP-t ki tudod cserélni bármi másra, mert az csak egy protokoll. De akkor nevezzük ezeket REST szerű API-nak. :) Csak annyit akartam mondani, hogy nem derült ki nekem a kommentekből, hogy a srác, aki az előadást tartotta REST API-t csinált (mondhatja jogosan), vagy nem REST API-t csinált. Mert a hozzászólások arról szóltak, hogy az elterjedt/elfogadott/tankönyvekben leírt módon valósította-e meg.

Még egy nagyon hülye példa (bocs), csak a példa kedvéért: Ha a HTTP-től abban tér el, hogy mindent visszafele ír a request-ben, és a response-ban, akkor akkor is REST API lesz, ami használja ezt a protokollt, ha a többi REST elvet megvalósítja, mert ez csak egy megvalósításbeli kérdés. Ez kb olyan (hogy ragaszkodunk a HTTP-hez), mintha azt mondanánk, hogy a REST API-t csak JAVA-ban lehet írni, mert azzal jól lehet kezelni a hálózatot, és assembly-ben sok gondunk lenne.

"Még egyszer: tényleg nem kötözködni akarok, csak mégis úgy gondolom, hogy a HTTP-t ki tudod cserélni bármi másra, mert az csak egy protokoll."

Oké, akkor adok egy email címet, mint endpoint-ot és megmutatnád egy rövid példán, hogy ezen át hogy képzelsz el egy REST kommunikációt, ami ettől nem HTTP over SMTP lesz?

Figyú, én küldök neked üzeneteket email-ben, és te a REST-nek megfelelően válaszolsz, ok?

A megkötéseket próbáljuk meg tartani: https://hu.wikipedia.org/wiki/REST

Sőt egy teljes weboldalt is letölthetünk így email-ben, elküldöm neked a GET-eket (vagy megállapodunk mit ,ettől lesz nem HTTP over SMTP) email-ben, Te pedig elküldöd a választ. De tömöríthetjük is a kérést, választ, a végeredmény jó lesz.

:) Tényleg nem kötözködni akarok, szerintem értjük egymást, én azt próbálom elmagyarázni, hogy (szerintem) nem feltétlen mondott hülyeséget az, aki azt mondta hogy REST API-t készített, annak ellenére, hogy használja ki a HTTP lehetőségeit, nem használ PUT-ot, DELETE-et, meg a HTTP hibakódok teljes repertoárját.

De ebben a WIKI-ben is ezt írták: "A REST eredetileg a HTTP keretein belül lett leírva, de nem korlátozódik erre a protokollra. Egy "RESTful" architektúra más alkalmazási rétegbeli protokollra is épülhet, amennyiben az már rendelkezik értelmes erőforrás-reprezentáció átvitelhez szükséges gazdag és egységes szókinccsel."

"Sőt egy teljes weboldalt is letölthetünk így email-ben, elküldöm neked a GET-eket (vagy megállapodunk mit ,ettől lesz nem HTTP over SMTP) email-ben, Te pedig elküldöd a választ. De tömöríthetjük is a kérést, választ, a végeredmény jó lesz."

De, ettől HTTP over SMTP lesz. Ha pedig fölé teszed a REST interfészed, akkor REST over HTTP over SMTP lesz, nem pedig REST over SMTP.

Egy gyakorlati példát mutass, hogy mit küldesz nekem a megadott email címre, ami olyan REST, amit bármelyik REST implementáció beszél, de nem szimulálsz a levélben HTTP kérés-választ.

Gyakorlati példa: Elküldöm neked magyarul MP3-ban CD-n a kérést, és Te felolvasva MP3-ban küldöd vissza a választ. Erről ugye elhihetjük, hogy nincs benne HTTP protokoll? :) (Nagyobb hülyeséget már nem tudok kitalálni, ami szemlélteti, hogy nem a HTTP protokollon múlik a dolog, pl FTP is lehet, vagy bármi ami megfelel a célnak). Ha ezt Te nem fogadod el, mert szerinted ez a példa HTTP-t "szimulálja", és csak ezért működik, akkor szerintem megegyezhetünk, hogy én sem használtam a HTTP protokollnak szigorúan megfelelő módon a HTTP hibakódokat, és method-okat stb..., más API-t is elfogadhatunk REST-API-nak, ami nem így tesz, de egyébként az alapelveknek megfelel (amiről ez az eredeti szál szólt), mert nem ezen múlik, ez csak megvalósítás kérdése volt (ez volt az eredeti felvetésem)

"Elküldöm neked magyarul MP3-ban CD-n a kérést, és Te felolvasva MP3-ban küldöd vissza a választ."

Ez a transzport réteg.

"Erről ugye elhihetjük, hogy nincs benne HTTP protokoll? :)"

Azt akkor hihetjük el, ha most leírod, hogy mit olvasnál fel, mert az a _szöveg_ a protokoll, amit felolvasol. Amin keresztül eljut hozzám, az nem a protokoll része. Meg lehet valósítani HTTP-t bármilyen transzport rétegen, ki is nyomtathatod, elküldöd galambpostán, én értelmezem, kinyomtatom a választ és visszaküldöm. Ha a karakterek halmaza betartja a megfelelő RFC-t, akkor ez HTTP protokoll lesz, csak nem TCP/IP felett, hanem RFC 1149 felett.

"Akkor ha le akarok kérni egy weboldalt, akkor csak telnet-el jelentkezzek rá fel,"

A telnet az a transzport réteg, ad the raw TCP/IP csatornát, amibe tudsz írni és tudsz belőle olvasni. Ugyanazt a telnet-et tudod használni SMTP-re, HTTP-re, POP3-ra, IMAP-ra vagy bármi más protokollra, amit a másik oldal beszél.

"és írjam be: "kérem az index oldalt", és működni fog, mert szerinted ez HTTP protokoll."

Az a HTTP protokoll, ha úgy írod ezt be, hogy ennek hatására megkapod az index oldalt egy HTTP szervertől. Minden más csak HTTP-szerű protokoll, amit egy HTTP-szerű szerver beszél.

De én arról beszélek, hogy nem úgy írom be, hanem úgy, ahogy írtam: "kérem az index oldalt", és ezért nem HTTP protokoll, a telnetet meg azért írtam ide, mert ad the raw TCP/IP csatornát, ahogy Te is mondtad, és nem másért. De szerintem elbeszélünk egymás mellett (már egy ideje)...

Így van. Nem HTTP protokoll, hanem HTTP-szerű. És nem is REST, hanem REST-szerű.

Mint írtam, a legnagyobb baj abból van, hogy sokan több év tapasztalattal sem tudják megkülönböztetni, hogy mi az,
a, amikor stateless resource van a szerver oldalán és azt kell létrehozni, elérni, módosítani vagy törölni;
b, amikor van a szerver oldalán egy metódus (procedure), ami csinál valamit, és ezt meg kell hívni különféle paraméterekkel, majd a válaszát fel kell dolgozni.

Az (a,) esetre jó a REST, a (b,) esetre pedig RPC-t kell használni.

Gányolt esetben ez az RPC rá lesz feszegetve a REST-re, kevésbé gányolt esetben pedig lesz rá REST endpoint, amin át egy *RPC protokollon lehet kérdezni. A tiszta dolog meg az, hogy teljesen külön csatornán megy az, ami REST és az, ami RPC.

Olvasd vissza légy szíves a hozzászólásaim, mert kb 1000-el ezelőtt írtam, hogy legyen akkor "REST szerű", és akkor közös nyelven beszélgetünk mi is :)

A felvetésem az volt, hogy nem kell valakit megkövezni azért, mert kiejtette a száján azt hogy REST API-t csinált, és nem frissen nézte meg az oktatóanyagokat+tankönyveket, hogy mi is az, hanem az *elviségét* követte, és nem használta a PUT meg DELETE methódusokat (gondolom nem véletlen, más megfontolás is lehet mögötte, mint hogy béna a programozó, vagy a tervező).

Nem ovastam a NAV-os API-t, csak megnyitottam, és gyorsan be is zártam, és nem is akarom megvédeni. :)

A NAV-os API nem REST, és nem is REST-elvű, vagy REST-szerű, sima saját HTTP feletti RPC protokoll, ilyen metódusokkal (igen, metódusokkal operál, nem erőforrások állapot-transzferével):
manageInvoice, queryInvoiceData, queryTaxpayer, tokenExchange

De közben meg ez van a leírásban:
1.7.2 Erőforrások
/manageInvoice
/queryInvoiceData
/queryInvoiceStatus
/queryTaxpayer
/tokenExchange

Ez egy hatalmas agyrém.

A közölt adatok is XML-ek.
Feltalálták a SOAP-ot, csak nem használják a SOAP jól bevált, jóldefiniált infrastruktúráját hozzá, inkább hegesztettek valamit, amit REST-nek hívnak, pedig nem REST, hanme RPC over HTTP. De arra meg már közel 20 éve van totál szabvány megoldás, interfészleírókkal, eszközkészlettel, könyvtártámogatással minden elterjedt programozási környezetre stb. De nem, találjuk ki, hogy RPC over HTTP, hívjuk REST-nek, viselkedjen úgy, mint egy lebutított SOAP és legalább senki szakmabeli nem fogja érteni. Egy gyalázat az egész.

És főleg azért tehetik ezt meg, mert sokan azt mondják, hogy ami custom RPC over HTTP, az REST, pedig baromira nem, és baromira káros ez a hozzáállás! NE akarj RPC-t építeni HTTP felett, arra már rég van szabványos megoldás. És főleg ne hívd REST-nek, mert nem azt jelenti a REST, hogy custom RPC over HTTP.
Ezért is taknyolásból áll a szakma legnagyobb része, mert senki nem tartja magát eszközökhöz, elvekhez, szabványokhoz, mindenki gányol, és mások simán rámondják: jó az úgy. Francokat!

Nem tudod, mert a HATEOAS kritérium a HTTP-hez köti a REST-et.
Attól lesz valami RESTful, hogy részletekbe menő protokoll elmagyarázás nélkül is tudod használni (vö. SOAP WSDL-ek, sémák, discovery, etc), mert elég a resource nevét tudnod (pl. account) és innentől a HTTP verb-ek segítségével üzemeltetni tudsz egy CRUD-féle megoldást.

Abban a pillanatban, hogy a kedves NAV nem használja a megfelelő HTTP response code-okat, az apijuk nem lesz REST, mert az interfészük nem "uniform". Onnantól kezdve ez egy egyedi webes api, de _nem_ REST. S kezdhetsz általános http client libekkel pöcsölni, mert ugye ki tudja, jövőre^Wjövő héten mi változik meg megint.

Miért fontos az uniformitás: hogy tákolás nélkül tudd használni pl. Jersey-ből, CXF-ből, Spring-ből, tudd tesztelni pl. Postman-ból.

Ha a szerver visszaad 200-as, 400-as, és 500-as hibát, és a többi hibakódot egy erre kialakított helyen adja vissza az üzenetben (mert pl nem akartak két helyen hibakódokat visszaadni, pl "a számla már több mint egy hónapja sztornózva lett", és a "számla nem található", mert az előbbire nem biztos hogy találnánk jó HTTP kódot mert egy alkalmazás specifikus hibakód, az utóbbira igen, mert REST, HTTP-vel-el értelmezhető), akkor azt ugyanúgy lehet tákolás nélkül használni, mert az adatmodell-ben egy erre kialakított részben ott van szépen a hibakód, nem hiszem, hogy bárkinek nagy fejtőrést fog okozni, hogy most mit csináljon. Én csak azt mondtam, hogy nem eszik ezt ilyen forrón. Arra pedig kíváncsi lennék, hogy a NAV, vagy más, akinek nincs kimondottan erre szüksége valami miatt, mikor fog HATEOAS kritériumnak megfelelő API-kat csinálni, és elküldözgetni az URL-eket, hogy merre tovább, csak azért, mert ez így van a nagykönyvben. Ezt beírta a doksiba. De értem amit írsz, nem vagyok ellene, és szerintem is így lenne szép.

"a számla már több mint egy hónapja sztornózva lett"
Az ilyen jellegű hibakód NEM írható le REST-tel. HTTP feletti RPC lesz belőle, az meg nem REST, egy idő után meg hasonlítani kezd a SOAP-ra.
REST esetén MINDEN hibakód a HTTP status mezőben írandó le.
Ugyanis nincs értelme annak, hogy "a számla már több mint egy hónapja sztornózva lett", olyan van, hogy az erőforrás, amin te GET, PUT, POST stb. műveletet akarsz végezni, létezik-e, más formában (Accept és Content-Type) létezik-e, megfelelő-e a verziója. REST = Representational State Transfer. Erőforrások komplett állapotait viszed át valamilyen reprezentációban (text/json, text/html, text/xml, image/png stb. reprezentációkban) egyik helyről (a hívótól aka kliens) a másik helyre (a hívott félre aka szerver).
Nincs itt semmilyen üzleti hibakód a HTTP státuszkódokon kívül.
Ami ezen felül akarna bármit is csinálni, az nem REST. Az RPC over HTTP.

Egyrészt a "számla" nem resource, pláne nem stateless resource, ha pedig vissza akarod írni, hogy "több mint egy hónapja sztornózva lett", akkor az egy RPC hívás és nem REST, csak valamilyen oknál fogva REST API-ra próbálod ráfeszíteni az RPC hívásaidat.

A REST API tökéletes az esetek igen kis százalékában, amikor stateless resource elérésére akarod használni. A többire ott az RPC, tessék azt használni... egyszerűen antipattern egy REST API-ra ráfeszegetni egy RPC hívást és birkózni azzal, hogy milyen kóddal tudod visszaküldeni azt, hogy a "több mint egy hónapja sztornózva lett", mert nem erre való, csak a hype driven development miatt sokan erre használják.

"Egy számla, elérhető neked pl egy URL-en, visszakapod egy XML-ben."

Ez így lehet REST, ezzel nincs is gond.

Attól nem lesz REST, ha nem egyben teszel fel egy XML-t, mint számlát, hanem mondjuk hozzáadsz egy tételt és ez olyan műveleteket indít el a háttérben, ami nem annyi, hogy hozzáadsz egy XML-hez egy plusz blokkot, hanem egy komplex folyamaton kell végigmenni, aminek a végén vagy módosulni fog az XML számlád egy csomó helyen vagy komplex hibákat jelzel vissza... mert ez már RPC.

Tényleg meg kellene tanulni, hogy mi a REST és mi az RPC. Ha pedig mégis REST-en toljuk át az RPC-t, akkor tudjuk, hogy ez rossz, de együtt tudunk élni a dologgal.

A REST API tökéletes az esetek igen kis százalékában, amikor stateless resource elérésére akarod használni.

REST esetén nem a resource-ok stateless-ek, hanem a szerver.
Lásd a PUT, POST, PATCH, DELETE methodokat.

Állapotmentesség
A kliens-szerver kommunikáció tovább korlátozott az által, hogy a szerveren nem tárolják a kliens állapotát a kérések között. Minden egyes kérés bármelyik klienstől tartalmazza az összes szükséges információt a kérés kiszolgálásához, és minden állapotot a kliens tárol. A szerver lehet állapottartó; ez a korlátozás csupán azt követeli meg, hogy a szerver oldali erőforrás-állapotok URL által címezhetőek legyenek. Ez nem csak a szerver felügyeletét teszi lehetővé, de megbízhatóbbá teszi őket a hálózati meghibásodásokkal szemben, valamit tovább fokozza a skálázhatóságot.

Hát, ha a resource stateless, az annyit tesz, hogy nincs rá PUT, DELETE, PATCH értelmezve, csak legfeljebb egy darab POST, amivel keletkezik a resource és a GET, amivel meg lekérdezed.
Arra gondolhatsz még, hogy úgy stateless a resource, hogy PUT, DELETE, PATCH nélkül nem változhat meg az állapota a szerveren.
De azért ez nem ugyanaz, mint a stateless resource! Az, hogy csak HTTP kérések alapján változhat meg az értéke, és az is csak REST módon, már eleve benne van abban a fogalomban, hogy resource.

"Hát, ha a resource stateless, az annyit tesz, hogy nincs rá PUT, DELETE, PATCH értelmezve, csak legfeljebb egy darab POST, amivel keletkezik a resource és a GET, amivel meg lekérdezed."

Saját magának nyilván van state-je. A stateless resource annyit tesz, hogy nem függ a rajta végrehajtott GET, PUT, ..., DELETE metódusok lefutása attól, hogy egy másik stateless resource-on végrehajtottam-e valamit vagy sem, tehát nem tárolsz semmilyen state-et a szerveren, amitől egyébként függővé teszed a resource viselkedését, nincs saját magán kívül másik state tárolva és értelmezve.

"Az, hogy csak HTTP kérések alapján változhat meg az értéke, és az is csak REST módon, már eleve benne van abban a fogalomban, hogy resource."

Miért lenne benne ez a resource fogalomban? Megváltoztathatod az értékét HTTP kéréseken kívül is, egészen komplex módon is akár...

"Megváltoztathatod az értékét HTTP kéréseken kívül is, egészen komplex módon is akár..."
Nem. Ha van egy REST resourceom, akkor két GET kérésnek ugyanazon eredményt kell adnia, ha arra a resource-ra nem volt a két GET kérés között PUT, POST, PATCH vagy DELETE végrehajtva.

"Nem. Ha van egy REST resourceom, akkor két GET kérésnek ugyanazon eredményt kell adnia, ha arra a resource-ra nem volt a két GET kérés között PUT, POST, PATCH vagy DELETE végrehajtva."

Na, ez az, ami nem igaz.

Ha a két GET között volt egy RPC hívásod is, ami miatt mondjuk az _összes_ adott típusú resource egy mezőjének az értéke változott, akkor bizony a két GET már más eredményt fog adni, de ezzel nem sérül a REST stateless viselkedése (például újratömörítetted a profilképeket és ezt nem a REST interfészen át csináltad egyesével).

Akkor se sérül a stateless viselkedése, ha egyébként van a szerver oldalon stateful logikád trazakciók kezelésével, mert egy másik rendszerből jön egy integránsan kezelendő resource csomag, amit nem a REST interfészeken tolsz be, mert azon át nem tudod garantálni az integritását, de REST-en át adsz ki olvasásra, mert a REST-en át már stateless a resource.

Röviden: elérhetővé tudod tenni REST interfészen egy stateful rendszer stateless részeit és teljesen mindegy, hogy a REST interfészen át elérhető részen kívüli részeken a state-et egy kliens vagy egy szerver kezeli. Amit nem szabad, az annyi, hogy a REST interfészen state jelenjen meg bármilyen módon.

"Ha a két GET között volt egy RPC hívásod is, ami miatt mondjuk az _összes_ adott típusú resource egy mezőjének az értéke változott, akkor bizony a két GET már más eredményt fog adni, de ezzel nem sérül a REST stateless viselkedése (például újratömörítetted a profilképeket és ezt nem a REST interfészen át csináltad egyesével)."

Nem, mert ekkor ez a valami nem lesz REST resource, csak egy URL által azonosított valami. Ugyanis REST resource-ot nem módosíthatsz máshogy, mint PUT-tal. Pont ez a lényege a REST-nek. HTTP-n elérhető erőforrást nyugodtan módosíthatsz REST-től eltérő módon, de az attól még nem lesz REST-es erőforrásod.

Attól, hogy stateless dolgokat HTTP-n ajánlasz ki, az nem lesz REST.

"Nem, mert ekkor ez a valami nem lesz REST resource, csak egy URL által azonosított valami."

Pedig a REST egy URL által azonosított valami, amin bizonyos engedélyezett műveleteket lehet végezni. Ennyi és nem több.

"Ugyanis REST resource-ot nem módosíthatsz máshogy, mint PUT-tal. Pont ez a lényege a REST-nek. HTTP-n elérhető erőforrást nyugodtan módosíthatsz REST-től eltérő módon, de az attól még nem lesz REST-es erőforrásod."

Kicsit értetlenül állok, mert nem értem, hogy mit akarsz ezzel mondani... mutass már egy ilyen rendszert, ami teljesíti ezt: vagyis semmilyen más módon nem módosítható a rendszer állapota, csak REST-en keresztül.

"Attól, hogy stateless dolgokat HTTP-n ajánlasz ki, az nem lesz REST."

Ha REST interfészen kiajánlok stateless dolgokat, az bizony REST. :)

Köszi a kigyűjtést - számomra ebben sok új információ nem volt.

Én olyasmire vagyok kíváncsi, hogy ami ott elhangzott, az valóban megállja-e a helyét (vö: RESTAPI esetén bizonyos hibákat más hibakódokkal látunk el, mint ahová a referencia szerint tartoznak). Kicsit messzire ment ez a vita, de van benne hasznos infó is. Annyi nagyjából látszik, hogy az előadónak nem feltétlen volt igaza.

Csak infóként: én azt a kérdést tettem fel (arra, hogy minden HTTP státuszt le kell kezelni), hogy miért kell nekem az 5XX-es csoporttal foglalkoznom, ahhoz semmi közöm, és nem is érdekel, max logolom, hogy azt kaptam. Erre jött a válasz, hogy nem úgy van az. (Volt egy olyan kérdésem is, hogy mit csináljak a 3XX-es kódokkal, ami azért fura lenne, de megnyugtattak, hogy nem lesz 3XX-es válasz. És volt még más kérdés is, amire kicsit aggasztóbb válasz érkezett :))

Nem akarok pro/kontra beleszólni a tervező és implementáló munkájába, azt minősíteni sem szeretném. Én nem így csináltam volna, ugyanakkor ehhez rengeteg embernek kell alkalmazkodnia, akiknek - megkockáztatom - valszeg így könnyebb.

Fent elhangzott egy kérdés: "miért mindig a hülyék magabiztosak magukban?" - én pl kételkedtem magamban, ezért tettem fel a kérdést. Ezt akkor vehetem dicséretnek? :)

Ezt hívják RPC-nek, amikor csak akkor adsz vissza HTTP hibakódot, ha technikailag nem érhető el a remote procedure - vagyis a HTTP transzport rétege okozza a hibát; ha technikailag elérhető a remote procedure, akkor minden egyéb hibát (beleérve ebbe akár authentikációs és authorizációs hibát is) már az RPC-n belül kezelsz le egy hiba válasszal, lásd például JSON-RPC vagy gRPC.

"Én olyasmire vagyok kíváncsi, hogy ami ott elhangzott, az valóban megállja-e a helyét (vö: RESTAPI esetén bizonyos hibákat más hibakódokkal látunk el, mint ahová a referencia szerint tartoznak)."

Igen, azt hiszem a GitHub csinal olyat, hogy ha nem vagy authentikalva es lekersz egy resource-ot ami igazabol letezik, de csak auth-al erheto el, akkor 404-et (ami ugye NOT FOUND) ad vissza.
Ez azert van, hogy ne lehessen auth nelkul megmondani, hogy az a resource letezik-e vagy nem.

Semennyivel nem logikusabb, mint attól függetlenül, hogy létezik e a subtree vagy sem 401-et adni vissza, és akkor legalább azt mondod, ami a valódi probléma.

Illetve de, mert akkor már hozzá kell generálni egy www-auth vagy mi a neve fejlécet is, hogy mégis hogyan kéne autholni.

Köszönöm mindenkinek a hozzászólást. Így átolvasva mégegyszer az egészet, az alábbi megállapításra jutottam :).

Volt belinkelve video, blog, szakdolgozat, mindenféle cikk a témáról, ill kaptunk néhány RFC hivatkozást a HTTP-re vonatkozóan.

Ami jól látható, a REST API nincs igazán jól definiálva. Ha a definíció jó lenne, valszeg nem értené 5 ember 5 különböző módon.

Innentől kezdve az adott témában ezt az implementációt szerintem senki nem kérheti számon a tervezőjétől :). Van pro és kontra érv, de az van mindenhol...

Ez van, biztos lehetne jobb is - elképzeltem, ahogy a fenti hozzászólók közül "A" személy a felelős, és egy konferencián találkozik egy másik, szintén az eddigi hozzászólók közül "B" személlyel. A szituáció ugyan az lenne (már ha merne kérdezni).

Nem mondom, hogy csalódtam, szerintem kérdezni lehet, érdemes, és kell is.

Zárjuk le ezt a topikot :).

A definíció jó. - erre írtam ezt:
Ha a definíció jó lenne, valszeg nem értené 5 ember 5 különböző módon.

Légyszi vedd észre, hogy ebben benne van az, hogy nem kételkedem a topicban vitázó emberek tudásában. Bizonyára mindenki érti - de mégis mindenki másképp érti. :)

Az API készítője a hatodik ember.

"Légyszi vedd észre, hogy ebben benne van az, hogy nem kételkedem a topicban vitázó emberek tudásában. Bizonyára mindenki érti - de mégis mindenki másképp érti. :)"

Nincs igazából mit másképp érteni.

Mondok példát.

Például egy 'GET /users/{uuid}' teljesen klasszikus REST, átadsz egy URI-t és kapsz vissza egy resource-t.

Viszont ha mondjuk regisztrálni akarsz egy felhasználót, akkor az már RPC, mert a validációs hibáktól kezdve a mindenféle egyéb hibákon át a warning üzenetig bármit visszaírhatsz, ezeket nem tudod ráfeszíteni 1:1 kapcsolatban a REST hibakódokra, illetve nem hozol létre egy user resource példányt, hanem egy komplex folyamatot indítasz el, aminek a végén lesz egy user resource, amit lekérdezhetsz egy REST API-n át.

Nézd, én értem, és elfogadom az álláspontodat, de nem tudok vele sok mindent kezdeni. :)

Én annyit láttam, hogy ment egy vita a REST/nem REST kérdésről, ez számomra csak azt mutatja, hogy - amennyiben elfogadjuk, hogy mindenki felkészült szakmailag - akkor a specifikáció nem egyértelmű. (Persze ebben ott van az is, hogy nem mindenki felkészült. :))

Ahogy írtam: volt itt blog, cikk, HTTP RFC (ami nem REST RFC, ugye...), Youtube video...

De mi az alap? A disszertáció? Van valahol mégis RFC? Van valami non-profit organization, aki leírja a REST alapokat? A te véleményed az?

Érted a dilemmámat? :)

Viszont ha mondjuk regisztrálni akarsz egy felhasználót, akkor az már RPC, mert a validációs hibáktól kezdve a mindenféle egyéb hibákon át a warning üzenetig bármit visszaírhatsz, ezeket nem tudod ráfeszíteni 1:1 kapcsolatban a REST hibakódokra

REST-tel is meg lehet csinálni a user regisztrációt.
A 403, 404, 500 hibakódokkal mindent le tudsz fedni, amire a többi nem alkalmas. A warningok meg sikeres végrehajtásnál vannak, ott meg egy 200 vagy más 2xx kód mehet vissza.

"REST-tel is meg lehet csinálni a user regisztrációt."

Igen? És hogy adod vissza hibakódokkal, hogy azért nem sikeres a regisztráció, mert a validáció szerint a megadott cím nem létezik?

"A 403, 404, 500 hibakódokkal mindent le tudsz fedni, amire a többi nem alkalmas. A warningok meg sikeres végrehajtásnál vannak, ott meg egy 200 vagy más 2xx kód mehet vissza."

Igen? És hogy adod vissza a warning-ot? Csak nem RPC hívást csinálsz, ahol nem a kért resource jön vissza, hanem egy struktúra, amiben visszajön a hívás státusza, a resource és az opcionális error vagy warning objektumok?

Igen? És hogy adod vissza hibakódokkal, hogy azért nem sikeres a regisztráció, mert a validáció szerint a megadott cím nem létezik?

Pl.:
403, Content-type: text/plain, Content: A validáció szerint a megadott cím nem létezik!

Igen? És hogy adod vissza a warning-ot?

Pl.:
200, Content-type: application/vnd.company.user-result+json, Content: {"warning": {...}, "user": {...}}

/ Egy resource-nak nem csak egy formája lehet, hanem tetszőlegesen sok és az Accept-tel megadhatod, hogy melyikeket tudod feldolgozni. /

A 403 biztosan nem jó ide.
Per definitionem: The 403 (Forbidden) status code indicates that the server understood
the request but refuses to authorize it.

If authentication credentials were provided in the request, the
server considers them insufficient to grant access. The client
SHOULD NOT automatically repeat the request with the same
credentials.

Ezen el lehet vitatkozgatni, én a w3 szerinti hivatalos változatot vettem:

400 Bad Request
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.

403 Forbidden
The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.

Ezek alapján a 403 a jó kód a fentire.

vs.

A REST alapvetően arról szól, hogy van valahol egy csomó stateless resource és azokat HTTP metódusokkal, HTTP protokoll használatával elérem.
Olvasd el a disszertációt a REST születéséről és megérted, hogy miért nem lehet szétválasztani a REST-et a HTTP-től.

A HTTP 200-nak mindig van eredménye, PUT és POST esetén pont a warningok leírására szolgál.
Mert ha nincs warning, akkor 204 a jó válasz ezekre a kérésekre.
És ez nem, nem RPC. PUT-tal tárolni akarsz egy új reprezentációt, majd a tárolás sikeres, de van warning, akkor HTTP 200 és leírás a warningról a válasz.
Míg ha a tárolás sikeres, és nincs warning, akkor HTTP 204. Ez baromira nem RPC.
Nem akarom, hogy az ellenoldal bármit számoljon az erőforráson és módosítson, hanem azt, hogy végezze el a tárolást - azaz ha én utána GET-elek, akkor pontosan azt kapjam vissza, amit előzőleg PUT-tal beküldtem. A szerver azon semmit nem módosíthat. Legfeljebb elutasíthatja a PUT kérést, leírva, hogy miért utasította el: kliensodali hiba, autentikációs hiba, szerveroldali hiba.

RPC esetén meg azt kéred meg a szervertől, hogy a beküldött adatok alapján keletkeztessen meg valami új adatot, amit ő számolt ki. Na, ilyen REST-nél nincs: a kliensnél van az alkalmazás állapota, ő végzi a számítást, a szerver meg a tárolást (hogy más kliensek is el tudják kérni ezt az állapotot).

Eleve REST-ben egyedi struktúra (reprezentáció) van. A REST nem szabja meg a reprezentációk formáját. A REST azt szabja meg, hogy az adatcsere az mindig reprezentációk cseréje, és semmi más, a reprezentációk változtatása (új reprezentáció kiszámítása) kliensoldali feladat, a szerver csak tárolja a reprezentációkat, hogy más kliensek is megkaphassák azt.

Azt viszont megszabja, hogy tartalmilag mi legyen egy reprezentációban. És a HTTP szépen le is írja, hogy mi az, ami a státuszkód, és mi az, ami a payload tartalma, amit valamilyen reprezentációban le kellene írni.

Szerveroldalon NINCS validációs logika REST-ben. Én amúgy sem szeretem a REST-et. A REST azt mondja, hogy a reprezentációk transzformálása kizárólag kliensoldali feladat (ettől lesz skálázható az egész), és a kliens és a szerver között reprezentációk cseréje történik mindig. A szerver az erőforrás reprezentációját nem is változtathatja meg, csak kiszolgálhatja a kliensek felé, illetve a kliensektől befogadhatja az új reprezentációkat.
A REST nem RPC, baromira nem erről szól. Például nincs tartalmi validációs logika a szerveren REST esetén.
És REST esetén ami stateless, az az interakció, nem a resource.
"All REST interactions are stateless. That is, each request contains all of the information necessary for a connector to understand the request, independent of any requests that may have preceded it."

REST, user regisztráció:
Létre akarod hozni a /user/Franko nevű usert, ezért PUT-olsz a /user/Franko végpontra egy user reprezentációt, annak minden adatával. A szerver nem számít ki hozzá semmit (pl. autoinkrement ID-t sem, semmit!)

A REST-nek a lényege, hogy KOMPLETT reprezentációkat küldesz át a felek között. És igen, nagyon sok rendszer, ami RESTfulnak mondja magát, nem RESTful.

REST esetén a kliens feladata, hogy a reprezentáció helyes legyen - a szerver azt nem ellenőrzi. Nem ellenőrzi, hogy a jelszópolicynek megfelelsz-e, azt a kliensnek kell biztosítania. Ettől még megoldható a user regisztráció - de a kliensben meg kell bízni. És igen, a REST nem is való mindenre.

Ahol nem bízol a kliensben, ott nem használható.

Ugyanis REST esetén az egész content authoring minden nyűggel együtt a kliens feladata, senki másé. A kliens feladata, hogy a content authoringhoz szükséges információkat a szerver(ekről) beszerezze.
Az erőforrást tároló és kiszolgáló szerver meg tárolja és kiszolgálja a reprezentációkat.

Tipikus REST user létrehozás (megbízható kliens és szerver által):
1. Kliens lekérdezi egy GET kéréssel hogy adott nevű felhasználó létezik-e: GET /user/Franko
Eredménye, ha 404, akkor minden fasza, mehetünk tovább.
2. Kliens létrehozza a Franko user reprezentációját a megfelelő szabályok szerint, majd PUT /user/Franko
3. A szerver megpróbálja letárolni a /user/Franko néven azonosított erőforrást.
Ha a kliens nem azonosította magát, de a létrehozáshoz azonosítani kell magát: HTTP 401 Unauthorized, és leírod a payloadban, hogy gebasz van.
Ha a kliensnek nincs joga létrehozni az erőforrást, HTTP 403 Forbidden és leírod a payloadban, hogy gebasz van.
Ha nem user reprezentációt küldtél, akkor HTTP 415 Unsupported Media Type, és leírod a problémát a payloadban a kliens számára értelmezhető módon.
Ha a kliens oldaláról minden fasza, és a szervernek sikerül az erőforrás létrehozása, akkor HTTP 201 Created, payloadban link a létrejött erőforrásra.
Ha a tárolás során kiderül, hogy az erőforrás már létezik, akkor HTTP 409 Conflict, és a payloadban leírod, hogy mi a gebasz.
Ha sikerül, de van warning (például hogy a letárolás a tárolórendszer latency miatt esetleg még nem rögzül azonnal), akkor HTTP 202 Accepted, meg egy payload, ami leírja a helyzetet.
Ha a tárolás során szerveroldali hiba van (hopp, elmászott a tárolóegység), akkor HTTP 500 Internal Server Error, a payloadban leírod a helyzetet.

És igen: REST-tel nem lehet mindent lefedni, nem egy univerzálisan jó dolog, mint sokan hiszik. Én sem hiszem, hogy a REST mindig jó lenne. De ha már azt mondjuk, hogy az API-nk RESTful, akkor legyen is olyan.
És a REST nem RPC over HTTP. Nem csinálunk RPC-t.

Ahol a kliens is egy olyan szoftver, illetve service, amit te készítesz. Például egy olyan service, ami egy UI-tól fogad inputot, validál, stb, és egy vagy több REST szolgáltatást hív az üzleti logika megvalósítása érdekében, hogy erőforrásokhoz jusson, létrehozzon, módosítson. Tehát például egy üzleti logikát megvalósító RPC nem adatbázisokhoz nyúl közvetlenül, hanem HTTP-n REST stílusban kiajanlott erőforrásokhoz. Itt az RPC megvalósítás, akit a UI lát, az nem REST, de REST szervizek megbízható kliense.

Egy kérdés: végzel DB oldalon adatvalidációt triggerekkel minden esetben, amikor adatbázist használsz?
Ha nem, akkor pontosan erről van szó. Ott is a kliens felel az adat helyességéért, és nem a szerver. A szerver csak egy tárolási réteg.
Csak éppen REST esetén a protokoll, amivel elvégzed a tárolást, az HTTP, és nem a MySQL/PostgreSQL/MongoDB/whatever saját protokollja.

Az, hogy azzal elabsztrahálom a tárolási réteget egy mindkét oldal felől crossplatform protokollra.

Hogy egy Javas példát mondjak: JPA-t is használsz belül, az is leborotvál minden értelmes dolgot, amit a middleware amúgy tudna, mert az egy címezhető erőforrások lekérdezését, módosítását, tárolását végző API.
Az erőforrások relációsak. A JPA a szerveroldali részt elabsztrahálja, a kliensoldal számára pedig előírás, hogy ez Java.

A REST címezhető erőforrások lekérdezését, módosítását, tárolását végző protokoll, ahol a conversation állapotmentes. Az erőforrások hierarchikusak.
Cserébe REST esetén van egy szabványosított interfész a kliens és a szerverre is, sokkal kevesebb a megkötés, mert mindkét oldal felől crossplatform. Nem vitatom, hogy a szabvány túlságosan megengedő, és ez baj.

Azaz tárolási rétegre mindkét oldal felől crossplatform megoldás tud lenni a REST, eljáráshívásra meg a SOAP.
Így az adattárolást elabsztrahálhatod, és elrakod egy interfész fölé, mint ahogy az eljáráshívást is elabsztrahálod, és berakod egy interfész fölé.

SOAP esetén is tök jó, hogy az interfész mindkét oldala platformfüggetlen. Ezért tök jó kétoldalról platformfüggetlen RPC-re.
REST esetén is tök jó, hogy az interfész mindkét oldala platformfüggetlen. Ezért tök jó kétoldalról platformfüggetlen CRUD-ra.

Szerintem tul szigoruan latod a helyzetet. Az eddigi legkozisztensebb (lehetet mutatni masikat ami jobb) REST API amit lattam a GitHub-tol jott.

Azok alapjan amit te mondasz ok sem REST API-t implementalnak.

Pelda:

https://developer.github.com/v3/repos/#create

Meghivtam a https://api.github.com/user/repos URL-t egy ures JSON Object-el es ezt kaptam valaszul:


Header:
access-control-allow-origin →*
access-control-expose-headers →ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
content-length →390
content-security-policy →default-src 'none'
content-type →application/json; charset=utf-8
date →Wed, 07 Mar 2018 16:25:56 GMT
server →GitHub.com
status →422 Unprocessable Entity
strict-transport-security →max-age=31536000; includeSubdomains; preload
x-accepted-oauth-scopes →public_repo, repo
x-content-type-options →nosniff
x-frame-options →deny
x-github-media-type →github.v3; format=json
x-oauth-scopes →admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete_repo, gist, notifications, repo, user, write:discussion
x-ratelimit-limit →5000
x-ratelimit-remaining →4992
x-ratelimit-reset →1520443432
x-runtime-rack →0.032168
x-xss-protection →1; mode=block

Body:
{
"message": "Repository creation failed.",
"errors": [
{
"resource": "Repository",
"code": "missing_field",
"field": "name"
},
{
"resource": "Repository",
"code": "custom",
"field": "name",
"message": "name is too short (minimum is 1 characters)"
}
],
"documentation_url": "https://developer.github.com/v3/repos/#create"
}

Igen, ez nem REST, hanem RPC, ami REST interfészen van kiajánlva... te a "create" művelet során nem egy repository resource-ot hozol létre, hanem elindítasz egy komplex folyamatot, aminek a végén lesz egy repository és erről kapsz vissza egy státuszt. Amikor meg lekérdezed, akkor se magát a repository-t kapod meg, hanem egy státuszt a repository-ról.

Igy viszont velemenyem szerint hasznalhatatlanna szukited a REST implementacio definiciojat, mert ezzel az erovel mindenre ra lehet mondani hogy "ez nem REST" ami bonyolultabb egy "hello world" szintu pelda app-nal.

Tudnal nekem egy olyan app-ot mutatni ami production-ben van es a te definiciod szerint REST-et implemental?

Az a tiszta REST, amire alapvetően való: CRUD-szerű weboldalak. Minden másra a Hype Driven Development vitte és az, hogy az RPC over HTTP több tudást igényel, mint egy szimpla REST, amiben mindent is meg lehet valósítani, csak feszülni fog rajta bármi, ami jóval több, mint egy CRUD.

Valoszinuleg igazad van abban, hogy a fent emlitett pelda egy bonyolultabb workflow-t triggerel a server oldalon.
De ez nekem mint az API felhasznalojanak blackbox es amig az endpoint pontsan azt csinalja amit egy REST API-tol elvarnek, az az letrehoz egy repo resource-ot a server oldalon amit kesobb "REST-es" modon lekerdezhetek, addig engem nem fog erdekelni, hogy mi tortenik server oldalon es szamomra es egy REST API lesz.

Gondolom te sem nezed meg minden library-nal az implementaciot, csak elolvasod, hogy mit ir a doku es az alapjan elhiszed, hogy az adott methodus hivas azt fogja csinalni amit te elvarnal.

A te definciod szerint a "tiszta" REST API egy koztes layernel nem ad tobbet hozza az App-odhoz, lehet igy is van, de amig ezzel a hozzallassal egymagad vagy addig nem sokra mesz, lehet esetleg el kene fogadni amit a tobbseg (nem csak az itteni HUP-os kollegak, hanem az az egy-ket "nagyobbacska" ceg is ami peldanak lett hozva) REST-nek hiv.

De en nem vagyok evangelist, ha mutatsz nekem egy olyan peldat ahol az ugy van leimplementalva ahogy te mondod akkor ertelemmel meggyozheto vagyok, ez eddig nem tortent meg, csak annyi tortent hogy az osszes konkret peldara amit neked hoztunk ramontad, hogy "ez nem REST".

Én értem és leszarom, hogy a többség a Hype Driven Development miatt mit nevez REST-nek és használom is. :)

Sőt, néha magam is szarok rá és RPC-t csinálok over REST, csak ilyenkor tudom, hogy szart csináltam és nem védem vehemensen, hogy márpedig ez a világ legjobb REST API-ja, mert egyáltalán nem az.

"Igen? És hogy adod vissza hibakódokkal, hogy azért nem sikeres a regisztráció, mert a validáció szerint a megadott cím nem létezik?"

The 4xx (Client Error) class of status code indicates that the client
seems to have erred. Except when responding to a HEAD request, the
server SHOULD send a representation containing an explanation of the
error situation, and whether it is a temporary or permanent
condition.

6.5.1. 400 Bad Request

The 400 (Bad Request) status code indicates that the server cannot or
will not process the request due to something that is perceived to be
a client error (e.g., malformed request syntax, invalid request
message framing, or deceptive request routing).

Szóval 400 a hibakód, és van egy reprezentáció, ami a hiba okát írja le. Ennyi. De olyan nincs, hogy minden kliens oldali hibára HTTP 400 a hibakód, aztán a payloadban meg van egy saját hibakezelési réteg.

"Szóval 400 a hibakód, és van egy reprezentáció, ami a hiba okát írja le. De olyan nincs, hogy minden kliens oldali hibára HTTP 400 a hibakód, aztán a payloadban meg van egy saját hibakezelési réteg."

Az az "van egy reprezentáció", ami ilyenkor visszamegy a 4xx hibakóddal karöltve és a hiba okát írja le, az pont egy saját hibakezelési réteg a payload-ban...

Vagy: https://cloud.google.com/storage/docs/json_api/v1/ Az oldalról: "his guide contains technical reference information for the Google Cloud Storage JSON API. Like the XML API, it is RESTful"

https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite Úgy látom, hogy az url-ben mondod meg, hogy mit mivel írsz felül (nem szigorúan egy valamire hivatkozol, akkor ez most RPC szerinted, vagy mi). Csak érdekes példa, ezért másoltam be. Bocs, ha tévedek, de ha jól értem: Nem várják el, hogy letöltsd, amit akarsz, és PUT-al fel.

Igen, az interfész maga RESTful, de van benne bőven RPC, a rewrite tipikusan RPC, nyilván azért, mert felesleges letöltened egy nagyobb tartalmat, aztán feltöltened, amikor a tartalom maga nem kell neked kliens oldalon, azt akarod, hogy egy műveletet hajtson végre a szerver oldal, aminek az eredménye érdekel.

"Igen? És hogy adod vissza a warning-ot? Csak nem RPC hívást csinálsz, ahol nem a kért resource jön vissza, hanem egy struktúra, amiben visszajön a hívás státusza"
Speciel POST, PUT esetén sem a keletkezett resource jön vissza.
6.3.1. 200 OK
POST a representation of the status of, or results obtained from,
the action;
PUT, DELETE a representation of the status of the action;

Az akció státusza jön vissza valamely reprezentációban. Ebben lehet már link a megkeletkeztetett, megávltoztatott erőforrás URL-jére és egyéb más is, mint például a warningok. Nem kell magát a megkeletkeztetett erőforrást leírnod válaszként.

Ha például nincs warning, meg semmi egyéb, akkor ildomosabb 204-et küldeni:
"6.3.5. 204 No Content

The 204 (No Content) status code indicates that the server has
successfully fulfilled the request and that there is no additional
content to send in the response payload body. For example, if a 204 status code is received in response to a PUT
request and the response contains an ETag header field, then the PUT
was successful and the ETag field-value contains the entity-tag for
the new representation of that target resource."

"Ami jól látható, a REST API nincs igazán jól definiálva."
Az nagyon jól van definiálva, hogy mi a REST, és az, hogy egy API REST, nagyon egyszerűen el lehet dönteni.

Sokan azt gondolják, hogy bármi HTTP fölött, ami nem SOAP = REST.
Nem, a REST maga a HTTP rendes, teljes használata. A HTTP fejlécek, a HTTP státuszkódok, a HTTP metódusok teljes körének szemantikus használata. Ez maga a REST. Úgymond, a "raw HTTP".

Az nem REST, ha HTTP felett kiépítünk egy saját kérés-válasz üzenetprotokollt, ami saját státuszkódokkal, saját szemantikával rendelkezik. Az nem REST.

+1

Ami jól látható, a REST API nincs igazán jól definiálva. Ha a definíció jó lenne, valszeg nem értené 5 ember 5 különböző módon.

Pontosan így van! Az egyetlen valamire való "definíció" az Roy Thomas Fielding doktori disszertációja, de az sem tér ki számos kérdésre, pl. melyik HTTP method-ot hogyan használjunk, melyik status code pontosan mire való, hogyan verziózzuk a resource-okat, ...
Ezek egy részére választ kaphatunk a HTTP specifikációjából, pl. a status code-ok értelmezése, de sok egyéb kérdés nyitva marad.
Sokak szerint HATEOAS nélkül nem is igazán van értelme a REST-ről beszélni (RESTful), ezt pl. nem tárgyalja ez a disszertáció, de sok ember szerint anélkül is teljesen jó a REST.

Szóval ezer vélemény sok mindenről, hogy mit, hogyan kell megoldani, de az alapok azok tiszták.
A topikban janoszen hozzászólását érdemes alapul venni, illetve itt található egy jó leírás, mit, hogy lehet és érdemes REST címszó alatt csinálni:
Best Practices for Designing a Pragmatic RESTful API