Browsers enforce the Same-Origin Policy by default—scripts on domain A cannot access resources on domain B. This protects users from malicious cross-site requests, but blocks legitimate API calls between domains.
CORS (Cross-Origin Resource Sharing) is a mechanism that lets servers explicitly declare which domains (origins) can access their resources and under what conditions.
For simple requests (GET/POST/HEAD with standard headers):
- Client sends request with
Originheader - Server checks policy, responds with
Access-Control-Allow-Origin - Browser allows/blocks response based on header
For non-simple requests (PUT, DELETE, custom headers, non-standard Content-Type):
- Browser sends OPTIONS request first (pre-flight)
- Server responds with allowed methods, headers, and origins
- Browser caches this (via
Access-Control-Max-Age) - Then sends actual request
| Header | Purpose |
|---|---|
Origin | Client’s domain (sent by browser) |
Access-Control-Allow-Origin | Allowed origins (server) |
Access-Control-Allow-Methods | Allowed methods (server) |
Access-Control-Allow-Headers | Allowed headers (server) |
Access-Control-Max-Age | Cache duration for pre-flight |
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:5173")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true);
}
}- Server controls access—not the client
- Pre-flight caching reduces overhead
- Credentials require specific origin (not ’*’)
- Related to: HTTP Headers (uses headers for negotiation: Access-Control-Allow-Origin)
- Builds on: HTTP Methods (OPTIONS is the pre-flight method)
- Related to: HTTP Status Codes (401, 403 errors appear in CORS failures)
- Related to: Statelessness (CORS requests must include all auth per request)
- CORS errors in browser console ≠ server error; request reached server
- Preflight required for PUT, DELETE, PATCH methods
- Authorization header triggers pre-flight (custom header)
- Misconfiguration appears as “blocked by CORS policy”