Come funziona CORS e come leggere il risultato del test
Origine e Same-Origin Policy
Per il browser un'origine è la combinazione di schema, dominio e porta: https://app.esempio.it e https://api.esempio.it sono origini diverse, e lo sono anche http:// e https:// dello stesso dominio. Per sicurezza il browser impedisce al codice JavaScript di una pagina di leggere le risposte di un'altra origine, a meno che il server chiamato non lo autorizzi esplicitamente con le intestazioni CORS (Cross-Origin Resource Sharing).
Richieste semplici e richieste con preflight
Le richieste GET, HEAD e POST senza intestazioni personalizzate e con Content-Type application/x-www-form-urlencoded, multipart/form-data o text/plain partono subito: il browser controlla solo la risposta. Tutte le altre, comprese le chiamate con application/json o con l'intestazione Authorization, sono precedute da una richiesta OPTIONS di verifica, il preflight. Il tester simula proprio questo passaggio e mostra se il server lo supera.
Le intestazioni che contano
- Access-Control-Allow-Origin: l'origine autorizzata, oppure * per tutte (non con le credenziali).
- Access-Control-Allow-Methods: i metodi ammessi nel preflight, per esempio GET, POST, PUT, DELETE.
- Access-Control-Allow-Headers: le intestazioni che il client può inviare, per esempio Content-Type e Authorization.
- Access-Control-Allow-Credentials: true se la richiesta porta cookie o autenticazione.
- Access-Control-Max-Age: per quanti secondi il browser può riusare l'esito del preflight.
- Access-Control-Expose-Headers: le intestazioni della risposta che il JavaScript può leggere oltre a quelle standard.
Gli errori più comuni
«No 'Access-Control-Allow-Origin' header is present»: il server non ha risposto con l'intestazione, spesso perché la configurazione vale solo per alcune rotte o non per gli errori (una risposta 401 o 500 senza intestazioni CORS appare nel browser come errore CORS).
Preflight fallito: la richiesta OPTIONS riceve un redirect, un 401 o un 404. Il preflight non porta credenziali, quindi deve passare senza autenticazione e rispondere con un codice 2xx.
Jolly con le credenziali: Access-Control-Allow-Origin: * insieme a cookie o withCredentials viene rifiutato; serve l'origine esatta più Access-Control-Allow-Credentials: true.
Intestazione duplicata: applicazione e proxy aggiungono entrambi Access-Control-Allow-Origin e il browser trova due valori. Va impostata in un solo punto.
Come usare il report
Inserisci come origine l'indirizzo esatto del sito che chiama, con schema e porta, e come destinazione l'endpoint che fallisce. Se il preflight non passa, parti dalla prima intestazione segnalata come mancante e applica la configurazione generata per il tuo server (Nginx, Apache, PHP, Express o Cloudflare); ricorda di aggiungere Vary: Origin se la risposta cambia a seconda dell'origine, così le cache non mescolano le risposte.
Domande frequenti su CORS
Perché la chiamata funziona con curl o Postman ma non dal browser?
CORS è una regola del browser: è il browser che legge le intestazioni della risposta e decide se consegnare il risultato al codice JavaScript della pagina. curl, Postman e le chiamate da server a server non applicano CORS, quindi la stessa richiesta può riuscire fuori dal browser e venire bloccata dentro.
Che cos'è la richiesta preflight OPTIONS?
Prima di una richiesta "non semplice" (per esempio con metodo PUT o DELETE, con un Content-Type come application/json o con intestazioni personalizzate come Authorization) il browser invia una richiesta OPTIONS con Access-Control-Request-Method e Access-Control-Request-Headers. Solo se la risposta autorizza metodo, intestazioni e origine il browser invia la richiesta vera.
Posso usare Access-Control-Allow-Origin: * con i cookie?
No. Quando la richiesta porta credenziali (cookie o autenticazione HTTP, con credentials: include o withCredentials) il server deve restituire l'origine esatta in Access-Control-Allow-Origin e aggiungere Access-Control-Allow-Credentials: true. Il carattere jolly * con le credenziali viene rifiutato dal browser.
Perché il browser segnala più valori in Access-Control-Allow-Origin?
Succede quando l'intestazione viene aggiunta due volte, per esempio sia dall'applicazione sia dal web server o dal proxy davanti. L'intestazione accetta un solo valore: va impostata in un solo punto della catena.
A cosa serve Vary: Origin?
Se il server restituisce un Access-Control-Allow-Origin diverso a seconda dell'origine che chiama, Vary: Origin dice alle cache (CDN, proxy, browser) di conservare una copia distinta per ogni origine. Senza, una cache può servire a un sito la risposta preparata per un altro, e la chiamata fallisce in modo intermittente.