REST: architektura pro webové API

Čtete v dokumentaci u různých webových aplikačních rozhraní často zkratku REST nebo RESTful? Zajímá vás, jak tato architektura vypadá, co vlastně popisuje a jak se s ní pracuje? V dnešním článku se seznámíme s jejími hlavními rysy a ukážeme si některé základní operace na jednoduchých příkladech práce s Twitterem.
Nálepky:
Web 2.0 přinesl, kromě oblých rohů, pastelových barev a velkých písmen, především intenzivnější spolupráci serverů mezi sebou při výměně dat. Do popředí zájmu se tak dostaly pojmy jako jsou API, webové služby či vzdálené volání procedur. Spolu s nimi se začal intenzivně skloňovat termín REST. Pojďme si jej podrobněji představit.
REST
REST (Representational State Transfer) – viz definice REST na Wikipedii – je architektura rozhraní, navržená pro distribuované prostředí. Pojem REST byl představen v roce 2000 v disertační práci Roye Fieldinga, jednoho ze spoluautorů protokolu HTTP. Proto nepřekvapí, že REST má s HTTP hodně společného.
REST je, na rozdíl od známějších XML-RPC či SOAP, orientován datově, nikoli procedurálně. Webové služby definují vzdálené procedury a protokol pro jejich volání, REST určuje, jak se přistupuje k datům.
Rozhraní REST je použitelné pro jednotný a snadný přístup ke zdrojům (resources). Zdrojem mohou být data, stejně jako stavy aplikace (pokud je lze popsat konkrétními daty). Všechny zdroje mají vlastní identifikátor URI a REST definuje čtyři základní metody pro přístup k nim.
Metody pro přístup ke zdrojům
REST implementuje čtyři základní metody, které jsou známé pod označením CRUD, tedy vytvoření dat (Create), získání požadovaných dat (Retrieve), změnu (Update) a smazání (Delete). Tyto metody jsou implementovány pomocí odpovídajících metod HTTP protokolu.
GET (Retrieve)
Základní metodou pro přístup ke zdrojům je získání zdroje – metoda GET. Setkává se s ní každý uživatel webu dnes a denně – není to nic jiného než starý dobrý požadavek na stránku.
GET /api/user/pepa
Host: www.server.cz
Jak jsme si už řekli, má každý zdroj (resource) podle rozhraní REST vlastní identifikátor (URI). Pomocí HTTP GET požadavku získáme data konkrétního zdroje. Ukažme si praktický příklad – získání posledních zpráv konkrétního uživatele (bude to „lupacz“) na Twitteru. Twitter poskytuje pro přístup k datům právě rozhraní REST (jeho API je, řečeno terminologií, RESTful – myslím ale, že se volný překlad „RESTovací“ pravděpodobně neujme, což je škoda, pozn. aut.).
Podle dokumentace REST API Twitteru lze získat zprávy konkrétního uživatele jako zdroj „/statuses/user_timeline“. Přesný tvar je http://twitter.com/statuses/user_timeline/uživatel.formát
. Data uživatele „Lupacz“ ve formátu XML získáme tedy takovýmto HTTP požadavkem:
GET /statuses/user_timeline/lupacz.xml
Host: twitter.com
Což odpovídá téměř naprosto přesně požadavku, který webový prohlížeč odešle, když klikneme na následující odkaz: http://twitter.com/statuses/user_timeline/lupacz.xml – můžeme si tedy sami velmi jednoduše vyzkoušet, jak vypadá výsledek. Můžeme zkusit změnit formát dat – máme na výběr XML, JSON, RSS a ATOM. Takto například vypadá tentýž zdroj, když je formátován jako RSS: http://twitter.com/statuses/user_timeline/lupacz.rss
API služby Twitter je poměrně dobrým příkladem rozhraní, které je postaveno na architektuře REST, a tak jeho studium může sloužit jako dobrý odrazový můstek pro prozkoumání možností podobných RESTful API.
Pokud potřebujeme získaná data nějak upravit či filtrovat, můžeme je předat jako součást požadavku tak, jak jsme zvyklí – jako tzv. „Query parametry“, tedy za otazníkem. Například http://twitter.com/statuses/user_timeline/lupacz.xml?count=100
POST (Create)
Získání dat je jednoduché a přímočaré. Stejně tak i vytvoření dat bude většině webových vývojářů připadat povědomé. Pro vytvoření dat slouží totiž metoda POST, známá (minimálně) z HTML formulářů.
U metody POST není ve chvíli volání známý přesný identifikátor zdroje (logicky, protože zdroj ještě neexistuje). Proto se pro POST používá domluvený společný identifikátor („endpoint“). Znovu se podíváme na ilustraci na konkrétním příkladu služby Twitter.
K vytvoření dat (zprávy) je potřeba zavolat zdroj s URI „/statuses/update“ pomocí HTTP metody POST. V parametru „status“ se předává text pro nově vytvořenou zprávu. Vzhledem k tomu, že vytvoření nové zprávy ovlivňuje uživatelská data, je třeba, aby volání bylo autorizováno. Twitter podporuje dvě metody autentizace: prostá HTTP autentizace nebo OAuth. OAuth poskytuje mnohem větší úroveň zabezpečení než prostá HTTP autentizace, při níž se posílá jméno a heslo v otevřeném textu, navíc umožňuje vytvářet aplikace, které využívají API, aniž by potřebovaly znát uživatelovo jméno a heslo. Implementace OAuth však není triviální, proto si pro zjednodušení ukážeme použití POST metody s jednoduchou HTTP autentizací.
curl -u user:password -d "status=Zkousime REST API" http://twitter.com/statuses/update.xml
Po odeslání by měl server vrátit patřičný návratový kód – HTTP má k tomu účelu stavový kód 201 – Created, v němž lze předat URI nově vytvořeného zdroje. Pokud došlo k chybě, měl by server vrátit chybový kód.
DELETE
Zdroj lze smazat pomocí volání URI HTTP metodou DELETE. Volání je obdobné volání metody GET:
DELETE /api/user/pepa
Host: www.server.cz
V praxi bývá někdy problematické vyvolat HTTP metodu DELETE – spousta HTTP nástrojů či HTML formuláře jsou omezeny pouze na metody POST a GET. V praxi se proto u REST rozhraní používají náhradní způsoby – např. volání pomocí POST s parametrem, který sděluje, že má být ve skutečnosti použita metoda DELETE, nebo speciální URI:
http://twitter.com/statuses/destroy/číslo.formát
Pokud máme nástroj, který umožňuje vyvolat metodu DELETE, můžeme ji použít:
curl -u user:password --http-request DELETE http://twitter.com/statuses/destroy/1472669360.xml
PUT (Update)
Operace změny je podobná operaci vytvoření (create, metoda POST), s tím rozdílem, že voláme konkrétní URI konkrétního zdroje, který chceme změnit, a v těle předáme novou hodnotu (jako u metody POST). Na rozdíl od POST je u úprav zdroje jeho URI už známá, takže ji lze zadat.
U metody PUT platí totéž, co bylo napsáno výše o metodě DELETE: Ne každý nástroj ji podporuje, a proto některá RESTful API používají různé náhradní metody, jak bylo zmíněno výše. Například:
curl -u user:password -d "url=http://zdrojak.root.cz" http://twitter.com/account/update_profile.xml
Shrnutí
REST je architektura, který umožňuje přistupovat k datům na určitém místě pomocí standardních metod HTTP (HTTP 1.1 methods). Pomocí REST lze ovládat i stav aplikace, pokud jej dokážeme popsat takovým způsobem, že si vystačí s modelem „zdroje – CRUD akce“.
REST nabývá na významu a stává se spolu s JSON defacto standardem pro API webových služeb. Jeho rozšíření napomáhá i technika AJAX, které REST vychází vstříc. Jeho rozšíření napomohlo i to, že se nijak zásadně neliší od standardního volání a získávání dat pomocí HTTP, pouze je zobecňuje. Dá se říct, že REST je architektura, která umožňuje CRUD operace pomocí standardních HTTP dotazů. (Pokud vám pojem CRUD stále evokuje databázové tabulky, tak jste na správné stopě – a ano, existuje nástroj, který funguje jako REST rozhraní k databázi.)
Moderní frameworky pro vývoj server-side aplikací pomáhají vytváření REST rozhraní tím, že dokáží nadefinovat patřičné procedury pro všechny potřebné metody, takže vytvoření vlastního RESTful rozhraní je opravdu snadné. Čím dál tím častěji je vidět v přehledech vlastností frameworků kromě (např.) „Podporuje MVC“ i „Podporuje REST“.
REST svou bezestavovostí vychází vstříc moderním metodám vývoje webových aplikací, které jsou založené na paralelním zpracování distribuovaného obsahu. Tato jeho vlastnost, spolu s výše zmíněnými výhodami (jednoduchost a nenáročnost) naznačuje, že se s rozhraními, postavenými na modelu REST, budeme do budoucna setkávat stále častěji.
REST je styl softverovej architektury!
Dnes vela ludi o RESTe hovori, ale len malo z nich mu rozumie. Tych, ktori nerozumeju, co je za pojmom REST spoznate podla toho, ze o nom hovoria ako o protokole. Myslim ze vystizne o tom pise Roy T. Fielding na svojom blogu http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
Ano, děkuji za upozornění, REST je architektura, nikoli protokol. Opravil jsem na dvou místech spojení slov „REST“ a „protokol“, kde nemělo význam „protokol (typu) REST“, tedy „protokol založený na architektuře REST“.
REST nie je dokonca ani architektura, ale styl softverovej architektury. ROA je architektura, ktora splna REST a suvisi s HTTP a URI. http://en.wikipedia.org/wiki/Resource_oriented_architecture
Ano krokodyl je sice plaz, ale hlavne patri mezi obratlovce, ci jeste lepe mezi strunatce…
Nemozes ale povedat ze kazdy plaz je krokodil ;)
Dakujem za pripomienku, v tom prvom prispevku som to uviedol, ale uz som nechcel tak bazirovat na terminologii aby sa autor neurazil. :)
Celkom pekny clanok. Dufam ze o RESTe a RESTovskych webovych sluzbach sa bude na roote viac pisat.
Díky i za pochvalu. Na Zdrojáku se o podobných věcech psát určitě bude.
Škoda že není doplněno pár odkazů na knihovny které s RESTem umí pracovat. Např pro PHP, Python, Javu atd.
S RESTful rozhraním dokáže pracovat každá knihovna, která umí poslat HTTP požadavek. Třeba i prostý JavaScript. Takže se nedá říct, že existují speciální „knihovny pro práci s RESTem“. Jsou konkrétní knihovny pro konkrétní API určité služby. Jak tu už bylo řečeno: REST není konkrétní protokol (protokol je třeba „obyčejné“ HTTP).
Pozor, ano i ne. S RESTful rozhraními lze pracovat třebas jen curlem, jak hezky ukazuje článek. A právě ta „transparence“ RESTful rozhraní je jednou z killer features. Ale právě „wrappery“ pro různé platformy jsou to, co práci s RESTem dělá příjemnou a zajímavější. Typicky např. pro Ruby:
HTTParty [http://railstips.org/2008/7/29/it-s-an-httparty-and-everyone-is-invited]
RestClient [http://rest-client.heroku.com/rdoc/]
A v neposlední řadě nekompromisní „objektově relační“ abstrakce nad REST rozhraním v podobě ActiveResource v Ruby on Rails [http://api.rubyonrails.org/classes/ActiveResource/Base.html]
Děkuji za doplnění
Zdá se mi to, nebo Atom je RESTful? Mám na mysli Atom jako protokol, v článku byl zmíněn „jen“ jako syndikační datový formát.
Mimochodem, používá vůbec někdo Atom pro něco víc než možná tak jako alternativu RSS, jako že by třeba svůj blog psal v nějaké desktopové aplikaci a přes Atom postoval na web?
Nezdá… nakolik jsem ATOM studoval, tak jeho možnosti publikování jsou postavené právě na REST architektuře. (ATOM nebyl zmíněn jako „syndikační formát“, ale jako jeden z „formátů dat“, který nabízí Twitter. Já osobně ATOM nepovažuju za syndikační formát a snažím se jej všude uvádět jako „publikační datový formát“.)
Ano, Atom je právě moc hezká ukázka důsledného využití REST architektury, ostatně s tímto cílem byl i primárně vytvářen. To, že se postupem času ve většině využití redukoval jenom na syndikační formát, neboli druhé RSS, je věc druhá.
… a je to škoda (ale to jen tak mezi námi).
Napriklad my pouzivame atom na integraci systemu.
Podla RESTovskych zasad by URL nemalo obsahovat sloveso.
To znamena, ze spravne by sa mazat malo takto:
curl -u user:password --http-request DELETE http://twitter.com/statuses/1472669360.xml
Detto pre POST a PUT.
Autori API to nepochybne vedeli. Jedna sa asi o „ustupok vseobecnemu vkusu“.
Privital by som clanok, ktory by ukazal ako sa ten isty problem vyriesi pomocou tradicneho „RPC“ pristupu a pomocou REST pristupu.
Řekl bych, že šlo o důvod, který zmiňuju v článku, tedy o „workaround“ pro ty klienty, kteří neumějí jiné HTTP metody než GET a POST.
take bych rekl
jen pro doplneni – dalsi takovou obechcavkou je dynamicke vygenerovani maleho formulare odesilajiciho data metodou POST pomoci javascriptu, viz Rails (bylo to tam driv, nevim jestli to nezmenili). Informace o tom, ze se ve skutecnosti jedna o PUT je prenasena v hidden field
ten formular vypada nejak takto:
– jmeno autora je Roy Fielding, nikoliv Field
– doporucuju jeden z nejlepsich clanku vysvetlujicich samou podstatu RESTu: http://tomayko.com/writings/rest-to-my-wife
– Stalo by za to vice rozvest vztah „stavu“ a „stavovosti“ k RESTu. Tedy ze jde o prenos reprezentaci stavu jednotlivych resources, ktery ale sam o sobe musi byt bezstavovy, tedy ze odpoved na kazdy request musi obsahovat veskera data potrebna pro jeji interpretaci a nesmi zaviset na datech ze zadneho prechazejiciho nebo nasledujiciho requestu.
– Mozna vic duraz na presnost terminologie… REST sam o sobe napr. neimplementuje zadne metody (POST, GET…). REST je neco jako interface treba v Jave, jeho aplikace v HTTP prostredi je neco jako implementace toho interface… viz ten Tomaykuv clanek, ktery abstrahuje REST od HTTP. REST na HTTP nutne nezavisi, ze je v 99.9 % dnes implementovan pres HTTP je vec jina. Take formulace „Pomocí HTTP GET požadavku získáme data konkrétního zdroje“ neni presna, ziskavame reprezentaci stavu zdroje… jasny, jsou to data, ale kdyz uz, drzel bych se terminologie…
Děkuji za upřesnění. Fielding je opraven, díky.
Snažil jsem se o popis spíš z praktického hlediska než z hlediska terminologické přesnosti, protože nejde o odborné pojednání, ale o to, aby si čtenáři udělali zhruba obrázek „oč jde, když se řekne…“
Ano, je to „reprezentace stavu zdroje“, ale 80% webových vývojářů si pod tímhle termínem těžko něco představí a budou se tu hromadit komentáře „to je zase nějaký abstraktní blábol, nepoužitelné v praxi, blablabla…“ Takže ano, HTTP GET vrátí reprezentaci stavu zdroje, ale říct, že jsou to data, je na tomto místě přípustné zjednodušení. Totéž abstrakce REST a HTTP – je samosebou lepší, ale jsme na Zdrojáku, kde 99% čtenářů tvoří lidé, pro něž je HTTP denním chlebem, takže jsem si opět dovolil zjednodušení.
Každopádně děkuji za doplnění a upřesnění terminologie.
Kromě skvělého Ryana Tomayka bych přidal ještě odkaz na „žargonu prostý“ Tilkovův seriál na InfoQ: http://www.infoq.com/articles/rest-introduction
Tak jsem si zkusil kliknout na příklad GET z twitteru ve formátu XML. A výsledkem byl krásný XML dokument. O pár řádků níže je příklad téhož, ve formátu rss (http://twitter.com/statuses/user_timeline/lupacz.rss). Kliknu a .. mám opět krásné XML. Vypadá to, že text hyperlinku správně obsahuje koncovku .rss, ale samotný hyperlink odkazuje stále na .xml.
Ano, překlep, opraven, děkuji.
Vim ze hlavni deviza RESTu je jeho bezstavovost. Znamena to tedy, ze uzivatel se neustale znovu autentifikuje?
Muzu v RESTu ziskat od serveru nejaky hodnotu, kterou nasledne pouziju k volani? A co takto ziskat identifikator session?
Ano, je potřeba se pokaždé znovu autentifikovat. Zkuste na celou věc nazírat jako na atomické operace nad daty: Klient požádá o operaci s daty, dodá potřebné informace, a operace proběhne (i když výsledkem může být chybové sdělení). Tato akce není závislá na žádné předchozí akci a neovlivňuje žádnou následující akci. To je základní princip architektury REST.
Ostatně trend vývoje webových aplikací směřuje k tomu uchovávat autentifikační informace i „session“ na straně klienta.
Pánové, prosím, jsme na odborném webu: identifikace – autentizace (ještě snesu autentikace) – autorizace – (accounting).
Nikdy, ale nikdy „autentifikace“. :-/
Klasická sentence praví: „Nikdy neříkej nikdy“ – jedná se o synonyma, jsou to tři různě utvořené české tvary bez významového rozdílu, a můžeme se dohadovat o zvyklostech, ale nikoli o tom, které z nich je „správné“. Na toto téma viz článek Dalibora Behúna.
Ale jinak máte pravdu, zvyklost na Zdrojáku velí „autentizace“, ovšem za mne to řeší korektorka, takže jsem v tomto případě použil stejné slovo, jaké použil tazatel. :)
Ani „autentizace“ do češtiny nepatří. Rozhodně jsem ji nenašel ve slovníku.
Diky za clanek. Zrovna minuly tyden jsem si rekl: Sakra, podivam se poradne, co to je. Jedine, co jsem vedel bylo, ze je to zpusob bezstavovych pozadavku na zdroje predavanych jako atomicke operace. Kupodivu to staci ! :-)
mezi nami – prikazy v davce take mohou REST – copy, zip, … Proste reknete tady pridej a ono se to udela, pak pod to pridam dalsi informace a ocekavam, ze to bude nebo se mi oznami chyba. to je REST.
dotaz? Komplexni zmena (tj. tam, kde bych delal transakci) musi obsahovat vsechny informace a byt postavena jako jedna operace?
trochu hustší pro ty co o tom slyší poprvé, ale stojí za to (Flash required): Stefan Tilkov: RESTful Design