Jak nastavit CORS pro REST API server (nginx)

Dnes jsem se potýkal s odmítnutím requestů odeslaných z prohlížeče na REST API server – ten je odmítl zpracovat z důvodu nastavené CORS politiky. Pokud se také potýkáte s tímto problémem, v tomto článku se dozvíte, jak ho vyřešit.

Trocha teorie

CORS, celým názvem Cross-Origin Resource Sharing, je nastavení (politika) serveru, která říká, jak naložit s požadavky z prohlížeče z jiných domén, než je doména daného serveru.

Máme-li doménu api.jetlio.com, na které běží API server a doménu cizidomena.cz, ze které vytvoříme AJAX požadavek na api.jetlio.com, bude tento požadavek odmítnut (není-li správně nastavena politika CORS).

Simple request

Splňuje-li požadavek náležitosti tzv. jednoduchého requestu (simple), pro jeho zpracování postačí nastavení hlavičky Access-Control-Allow-Origin. V opačném případě se jedná o tzv. preflight request.

Požadavek je v běžných situacích simple v případě, že jsou splněny všechny následující podmínky:

  • jedná se o GET, POST nebo HEAD požadavek
  • v případě, že se jedná o POST požadavek, Content-Type nabývá jedné z následujících hodnot: text/plainapplication/x-www-form-urlencodedmultipart/form-data
  • požadavek neobsahuje jinou hlavičku než AcceptAccept-LanguageContent-LanguageContent-TypeDPRDownlinkSave-DataViewport-Width nebo Width

Preflight request

Nesplňuje-li požadavek podmínky simple požadavku, je označen jako preflight. V takové situaci prohlížeč ve skutečnosti pošle na server celkem požadavky dva.

V prvním (OPTION) požadavku se dotáže na metody a hlavičky, které jsou v cross-site požadavku serverem povoleny. Pokud původní požadavek z prohlížeče podmínky splňuje, je odeslán na server také. Tam je následně zpracován a výsledná odpověď putuje zpět ke klientovi.

Nastavení v nginx

V konfiguračním souboru domény, u níž chcete CORS pro testovací účely nebo vývoj vhodně nastavit, upravte (nebo přidejte) následující nastavení:

location / {
    # cors (simple request)
    if ($request_method ~* "(GET|POST|PUT|PATCH|DELETE)") {
        add_header Access-Control-Allow-Origin *;
    }

    # cors (preflight request)
    if ($request_method = OPTIONS) {
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD";
        add_header Access-Control-Allow-Headers "Authorization, Origin, X-Requested-With, Content-Type, Accept";
        return 200;
    }
}

Můžete odstranit nebo přidat další metody, které plánujete v REST API používat. V tomto případě jsou povoleny často používané GET, POST, PUT, PATCH a DELETE. Obdobně to platí u odesílaných hlaviček.

Až budete mít produkt hotový a otestovaný po funkční stránce, je důležité upravit nastavení Access-Control-Allow-Origin, kde změňte hodnotu * na seznam domén, ze kterých chcete požadavky povolit.

Kdybyste změnu neprovedli, celé CORS zabezpečení postrádá smysl. Existují ale samozřejmě i případy, kdy provoz ze všech domén povolit chcete – například u veřejných API služeb. Tam je na místě zase jiný druh zabezpečení (jako třeba omezení co do počtu požadavků z jedné IP adresy).

Pro podrobnější nastudování CORS problematiky doporučuji navštívit příslušnou stránku na webu MDN, která mi velmi pomohla: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS.