Cross-Site XMLHttpRequest

JavaScript Firefox

Cross-Site XMLHttpRequest nebo též Cross-Origin Resource Sharing (CORS) je nová a zatím nepříliš rozšířená technika, která může pomoci řešit problémy s přístupem k datům třetích stran z webových aplikací. Pokud potřebujete do své aplikace získat data odjinud, může se hodit i vám. Blíže si CORS představíme v článku.

JavaScript je nejoblíbenějším programovacím jazykem webových aplikací a ačkoliv se jeho podpora v prohlížečích posunula v posledních letech o značný kus dál, některé jeho vlastnosti mohou představovat významná omezení. Jedním z nejvýraznějších, na které dříve či později narazí většina programátorů, se jmenuje otázka stejného původu.

Zkoumání stejného původu je bezpečnostní schéma, které by mělo zajišťovat, že v rámci stránky (nechť je to pro potřeby tohoto článku totéž, co webová aplikace) je možné spustit pouze skripty, které pocházejí ze stejného zdroje. Pod stejným zdrojem se myslí doménová adresa serveru, ze kterého jsou (dodatečně) stahovaná data. Data – obecně jakákoliv – mohou být z jiného adresáře, ale musí sdílet celé doménové jméno daného WWW serveru; porušením tohoto pravidla je použití poddomény, jiného protokolu (např. HTTPS namísto HTTP) i jiného portu webového serveru. Kostra tohoto schématu pochází z doby, kdy skript v rámci stránky typicky prováděl manipulaci s uživatelskými daty a odesílal je formuláři na serveru, který se postaral o jejich zpracování. Omezení pak především mělo zabránit tomu, aby bylo možné do stránky vložit cizí kód, který by prováděl s uživatelskými daty něco nepěkného.

Doba pokročila a v dnešní době lze v JavaScriptu vytvořit a provozovat značně komplexní aplikace; u těch nejsložitějších je již člověk často na vážkách, zda jde skutečně ještě o webovou aplikaci. Velmi často je potřeba zobrazovat a pracovat s daty z jiných datových zdrojů, než je samotný webový server. Mnoho služeb dnes poskytuje zdokumentované API, které je možné využít pro získání, příp. i modifikaci dat. S těmito daty je pak potřeba pracovat v naší aplikaci. Při použití asynchronního zpracování dotazů pomocí techniky XMLHttpRequest (nebo její sesterské ActiveXObject("Microsoft.XMLHTTP")) máme problém.

Chci data odjinud!

Na každý problém existuje minimálně jedno jednoduché, elegantní a nesprávné řešení. Nejjednodušší a dle mých zkušeností i nejpoužívanější řešení našeho problému spočívá v tom, že si v rámci serverové části aplikace, např. v rámci interního API, vytvoříme vlastní proxy skript, kterému jako parametr dáme URL požadovaných dat, on se postará o jejich získání z původního zdroje a nám je vrátí, jako by to byla jeho odpověď. Takový skript často může řešit částečnou nebo úplnou transformaci dat do vhodné podoby, jejich spojení s jinými daty apod.

Někdy ovšem není vhodné pracovat s takovým proxy skriptem – třeba pokud chceme vytvořit aplikaci, do níž si uživatel může jako datový zdroj přidat jakoukoliv dostupnou službu, která nemusí být přístupná ze sítě, v níž se nachází server. V některých případech dokonce není možné použít proxy skript, prostě proto, že není možné modifikovat serverovou část aplikace. Problém se také objeví ve chvíli, kdy se klientský kód má spouštět i v lokálním režimu, tj. při načtení stránky z filesystému; pak vůbec žádná serverová strana neexistuje, a přesto je potřeba získat data z externích zdrojů.

Nechci slyšet, že to nejde

Když to nejde na serverové straně aplikace, musí to jít jinde. Částečné řešení může představovat JSON-P nebo použití elementu <iframe>. Hlavní nevýhoda tohoto postupu je v tom, že na zpracování kódu v klientské aplikaci spuštěné z vašeho serveru musel myslet tvůrce služby, která poskytuje data. Pokud se tak nestalo, máte smůlu; např. ačkoliv prohlížeč dokáže bez problémů zobrazit data z veřejné URL, vy se k nim v klientském kódu nedostanete.

Co na to W3C

Na další (bohužel opět pouze částečné) řešení jsem narazil nedávno, když jsem řešil problém s přístupem ke službám z lokálně spouštěného kódu, tedy bez serverové části aplikace. Jedná se o poměrně čerstvý kousek z dílny konsorcia W3C, a sice o specifikaci Cross-Origin Resource Sharing. Jde o návrh (working draft) pracovní skupiny pro webové aplikace, jehož aktuálně dostupná verze je z 16. června tohoto roku. Specifikace je zajímavá především tím, že ji implementuje Firefox 3.5. Protože můj problém se týkal aplikace napsané v XULu, začal jsem vše zkoumat trochu podrobněji.

Myšlenka je jednoduchá a stejně jako v případě JSON-P se neobejde bez zásahu na straně poskytovatele dat – v tomto případě jde o nastavení hlaviček, které vrací webový server. Specifikace totiž definuje, že pokud server poskytující data (tj. v našem případě třetí strana) v hlavičkách odpovědi uvede některou platnou direktivu Access-Control-*, klientský kód smí získaná data použít k dalšímu zpracování. Hlaviček je momentálně v návrhu osm, tou nejdůležitější z nich je Access-Control-Allow-Origin, která řídí původ (tj. serverovou stranu) dotazující se strany. Pokud tedy server webapp.example­.com vrátí na konkrétní dotaz odpověď s hlavičkou Access-Control-Allow-Origin: http://my-domain.example.com, znamená to, že moje aplikace smí pracovat s daty získanými z webapp.exam­ple.com pomocí  XMLHttpRequest.

Specifikace upravuje i složitější případy užití, umožňuje omezit např. časovou platnost dotazu nebo HTTP metody (resp. REST verb(s)). Specifikace také operuje s přípravným dotazem (preflight request), který může webová aplikace použít ke zjištění, jestli jsou pro ni požadovaná data dostupná. V mém případě stačilo pro účely testování přidat do hlaviček web serveru daného virtuálního adresáře přidat direktivu Access-Control-Allow-Origin: * a aplikace funguje korektně z jakéhokoliv lokálního i intranetového zdroje.

Ačkoliv se nejedná o převratnou novinku, nabízí specifikace řešení jednoho z problémů, se kterými se programátor webových aplikací může občas potkat. Skutečnost, že se první funkční implementace objevila tak brzy, naznačuje, že se nejedná o čistě akademický problém. Můžeme jen doufat, že další prohlížeče specifikaci v brzké době implementují také.

K dalšímu čtení

Jak pohlížíte na techniku, popsanou v článku?

Autor vystudoval astronomii na MFF UK. Ve firmě ARCDATA PRAHA se zabývá GISem a serverovými aplikacemi. Ve volném čase se věnuje rodině, hudbě a astronomii.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 43

Přehled komentářů

huh JavaScript je nejoblíbenějším programovacím jazykem webových aplikací
petrik Re: JavaScript je nejoblíbenějším programovacím jazykem webových aplikací
David Ondřich Re: JavaScript je nejoblíbenějším programovacím jazykem webových aplikací
Ped Re: JavaScript je nejoblíbenějším programovacím jazykem webových aplikací
David Ondřich Re: JavaScript je nejoblíbenějším programovacím jazykem webových aplikací
Ped Re: JavaScript je nejoblíbenějším programovacím jazykem webových aplikací
Michal Augustýn Re: Cross-Site XMLHttpRequest
David Ondřich Re: Cross-Site XMLHttpRequest
soudruh Re: Cross-Site XMLHttpRequest
ah01 IE8 a jeho XDomainRequest
brut4r Re: IE8 a jeho XDomainRequest
David Ondřich Re: IE8 a jeho XDomainRequest
Borek Bernard Proč je cross-site request nebezpečný?
ah01 Re: Proč je cross-site request nebezpečný?
Borek Bernard Re: Proč je cross-site request nebezpečný?
Envel Re: Proč je cross-site request nebezpečný?
Borek Bernard Re: Proč je cross-site request nebezpečný?
David Ondřich Re: Proč je cross-site request nebezpečný?
Borek Bernard Re: Proč je cross-site request nebezpečný?
David Ondřich Re: Proč je cross-site request nebezpečný?
Daniel Steigerwald Re: Proč je cross-site request nebezpečný?
Martin Straka Re: Proč je cross-site request nebezpečný?
David Ondřich Re: Proč je cross-site request nebezpečný?
Borek Bernard Re: Proč je cross-site request nebezpečný?
Jakub Vrána Re: Proč je cross-site request nebezpečný?
Borek Bernard Re: Proč je cross-site request nebezpečný?
Jakub Vrána Re: Proč je cross-site request nebezpečný?
Borek Bernard Re: Proč je cross-site request nebezpečný?
Jakub Vrána Re: Proč je cross-site request nebezpečný?
Martin Re: Proč je cross-site request nebezpečný?
Daniel Steigerwald Re: Proč je cross-site request nebezpečný?
rtgfv Re: Proč je cross-site request nebezpečný?
NG Cross-site request funguje
Martin Malý Re: Cross-site request funguje
NG Re: Cross-site request funguje
Daniel Steigerwald Re: Cross-site request funguje
NG Re: Cross-site request funguje
David Ondřich Re: Cross-site request funguje
David Ondřich Re: Cross-site request funguje
NG Re: Cross-site request funguje
David Ondřich Re: Cross-site request funguje
NG Re: Cross-site request funguje
_ Nemožnosť získať cudzí HTML kód
Zdroj: https://www.zdrojak.cz/?p=3074