Spring Boot CORS: Cross-Origin Resource Sharing Configuration
Learn how to configure Cross-Origin Resource Sharing in Spring Boot for secure API access, including global config, annotations, and common pitfalls.
Learn how to configure Cross-Origin Resource Sharing in Spring Boot for secure API access, including global config, annotations, and common pitfalls. The guide uses practical examples to explain what is cors and why does it matter?, understanding the cors preflight flow and shows how to apply the ideas in a Spring Boot project.
Spring Boot CORS: Cross-Origin Resource Sharing Configuration
Cross-Origin Resource Sharing (CORS) is a browser security mechanism that controls whether web pages can request resources from a different domain. If your Spring Boot API needs to talk to a frontend on a different origin, CORS is what makes or breaks that connection.
Mess it up and your users see nothing but blocked requests and cryptic Access-Control-Allow-Origin errors in the console. This post covers everything you need: concepts, configuration approaches, failure modes, and production hardening.
What is CORS and Why Does It Matter?
Introduction
Cross-Origin Resource Sharing (CORS) controls which browser origins may call a Spring Boot application from a different origin. This guide explains preflight requests, allowed origins and methods, credential handling, and the configuration choices that make cross-origin APIs usable without creating an unnecessary security boundary.
Understanding the CORS Preflight Flow
Before getting into Spring Boot configuration, you need to understand how CORS actually works. The browser sends a preflight request to check permissions before the real request goes through.
sequenceDiagram
participant Browser as Browser Client
participant API as Spring Boot API
Browser->>API: OPTIONS /api/data (Preflight Request)<br/>Origin: http://localhost:3000<br/>Access-Control-Request-Method: GET
alt Preflight Approved
API-->>Browser: 200 OK<br/>Access-Control-Allow-Origin: http://localhost:3000<br/>Access-Control-Allow-Methods: GET, POST<br/>Access-Control-Allow-Headers: Content-Type<br/>Access-Control-Max-Age: 3600
Browser->>API: GET /api/data (Actual Request)<br/>Origin: http://localhost:3000
API-->>Browser: 200 OK<br/>Access-Control-Allow-Origin: http://localhost:3000<br/>{ "data": "response" }
else Preflight Denied
API-->>Browser: 403 Forbidden<br/>No CORS headers
Note over Browser: Request blocked,<br/>error in console
end
The preflight is an HTTP OPTIONS request that includes headers describing the actual request the browser wants to send. If the server approves, it responds with allowed methods, headers, and cache duration. The browser then decides whether to proceed with the real request.
Spring Boot CORS Configuration Methods
Spring Boot gives you three main ways to handle CORS. Here’s when to use each.
Method 1: Global CORS Configuration with WebMvcConfigurer
For most applications, this is the way to go. A global configuration applies to all endpoints, so you can audit and change your CORS policy in one place.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000", "https://myfrontend.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("Content-Type", "Authorization", "X-Request-ID")
.exposedHeaders("X-Custom-Header")
.allowCredentials(true)
.maxAge(3600);
}
};
}
}
exposedHeaders tells the browser which response headers the JavaScript code is allowed to read. One thing to remember: when allowCredentials is true, you cannot use allowedOrigins(“*”) — the browser rejects that combination.
Method 2: Using the @CrossOrigin Annotation
For controller-level or method-level control, @CrossOrigin gives you a declarative approach. This is useful when different endpoints need different CORS policies.
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class ProductController {
// Allow CORS for this specific endpoint
@CrossOrigin(origins = "http://localhost:3000")
@GetMapping("/products")
public List<Product> getProducts() {
return productService.findAll();
}
// Different endpoint, different origin
@CrossOrigin(origins = "https://admin.example.com", methods = { RequestMethod.GET, RequestMethod.POST })
@PostMapping("/products")
public Product createProduct(@RequestBody Product product) {
return productService.save(product);
}
// Allow all origins for this endpoint
@CrossOrigin(origins = "*", methods = RequestMethod.GET)
@GetMapping("/public/products")
public List<Product> getPublicProducts() {
return productService.findPublic();
}
}
Put @CrossOrigin at the class level to apply it across all methods, or on individual methods to override. When you combine both, the most permissive settings win.
Method 3: CORS with Spring Security
With Spring Security in the mix, CORS needs to hook into the security filter chain rather than being handled separately.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(
"http://localhost:3000",
"https://myfrontend.com"
));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("Content-Type", "Authorization"));
configuration.setAllowCredentials(true);
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/**", configuration);
return source;
}
}
With Spring Security, the CORS filter runs before authentication kicks in. That is necessary because preflight OPTIONS requests do not carry credentials.
Configuration Properties Reference
Spring Boot also supports CORS through properties, which is handy for environment-specific settings without changing code.
# application.properties
# For actuator endpoints only
management.endpoints.web.cors.allowed-origins=http://localhost:3000,https://monitoring.example.com
management.endpoints.web.cors.allowed-methods=GET,POST
management.endpoints.web.cors.allowed-headers=Content-Type,Authorization
management.endpoints.web.cors.exposed-headers=X-Custom-Header
management.endpoints.web.cors.allow-credentials=true
management.endpoints.web.cors.max-age=3600
These properties only apply to Spring Boot Actuator endpoints. For your application endpoints, you still need one of the programmatic approaches described above.
Failure Scenarios and Common Mistakes
Knowing what can go wrong helps you debug faster.
Misconfiguration: Using “*” with Credentials
A common mistake is trying to use a wildcard with credentials enabled.
// THIS WILL NOT WORK
registry.addMapping("/api/**")
.allowedOrigins("*") // Wildcard not allowed with allowCredentials
.allowCredentials(true);
When allowCredentials is true, browsers require explicit origins. The server must list each one. This combination fails at the browser level, regardless of what headers the server sends.
Misconfiguration: Missing OPTIONS Handler
If preflight requests return 404 or 500, your application is not handling OPTIONS requests. Spring’s CORS support handles this automatically when properly configured, but you need to make sure your filter chain is set up correctly.
Misconfiguration: Case Sensitivity in Headers
CORS headers are case-sensitive. content-type will not match what the browser sends as Content-Type. Always use canonical header names.
Network-Level Blocking
Sometimes the problem is not your application but something in front of it. AWS ALB, nginx, and Cloudflare can all modify or strip CORS headers. If CORS works locally but fails in production, check your infrastructure.
Security Considerations
CORS misconfiguration can expose your API to risks.
Restrict Allowed Origins
Avoid allowedOrigins(“*”) in production unless your API is completely public. Wildcard origins mean any website can make requests to your API on behalf of authenticated users.
Validate Origin Header Carefully
The Origin header comes from the browser and is generally trustworthy because browsers enforce CORS rules. Still, validating origins against an allowlist is good practice.
Do Not Rely on CORS for Authorization
CORS controls which origins can access your resources, not who can access them. Authentication and authorization belong in your application code.
Preflight Caching
A sensible maxAge reduces unnecessary preflight requests. Stable resources benefit from longer cache durations. Resources that change frequently may need shorter ones.
When to Use / When NOT to Use
When CORS Applies
CORS is the right tool when you have a browser-based frontend running on a different origin than your Spring Boot API. Single-page applications, mobile web clients, or any client that runs in a browser and needs to call your API across origins all require CORS headers. Partner integrations that use browser-based JavaScript to call your APIs also need CORS configured.
When to Avoid CORS
CORS is a browser-enforced mechanism. Server-to-server communication, backend services calling each other directly, native mobile applications, and command-line tools do not enforce CORS policies and do not need these headers. If your service mesh or API gateway handles authentication and authorization between services, CORS adds nothing. Do not configure CORS headers for non-browser clients.
When to Use Global Configuration (WebMvcConfigurer)
Use global CORS configuration when you have a consistent CORS policy across most or all of your endpoints. It is easier to audit, modify, and reason about than annotation-based per-endpoint configuration. Changes to the policy happen in one place, which reduces the risk of inconsistent CORS settings across your API.
When to Use @CrossOrigin Annotations
Use @CrossOrigin on specific controllers or methods when different endpoints genuinely need different CORS policies. If your API exposes both a public set of endpoints and an admin-only set that should allow different origins, annotation-based configuration makes that boundary explicit in the code.
When to Use Spring Security CORS Integration
If you are already using Spring Security, integrate CORS into your security filter chain rather than using a separate configuration. This ensures CORS processing happens before authentication, which is required since preflight OPTIONS requests do not carry credentials.
Common Pitfalls / Anti-Patterns
Using Wildcard Origins with Credentials
Setting allowedOrigins(“*”) while also enabling allowCredentials(true) is rejected by browsers. This combination would allow any website to make authenticated requests on behalf of a logged-in user, which is a security risk. When credentials are required, you must enumerate explicit origins.
Fix: List each allowed origin explicitly. If you have many origins, consider an origin validator that checks against a configured allowlist rather than hardcoding every domain.
Missing OPTIONS Handler for Preflight
If preflight OPTIONS requests return 404 or 500 instead of proper CORS headers, the browser blocks the subsequent actual request. Spring’s CORS filter handles this automatically when the filter chain is correctly configured, but a missing or misconfigured filter chain can silence it.
Fix: Verify your CORS configuration is registered as a filter and that it runs before any authentication filters. Test preflight with curl -X OPTIONS -H “Origin: http://localhost:3000” -H “Access-Control-Request-Method: GET” http://localhost:8080/api/endpoint and confirm you get Access-Control-Allow-* headers back.
Case-Sensitive Header Names
CORS headers are case-sensitive. Browsers send Content-Type and Authorization with canonical capitalization. If your configuration uses lowercase content-type, the preflight check fails silently at the browser level.
Fix: Always use canonical header names in CORS configuration. Spring’s HttpHeaders class uses canonical names internally, so stick to the constants like HttpHeaders.CONTENT_TYPE.
Infrastructure Stripping CORS Headers
When your Spring Boot app sits behind an AWS Application Load Balancer, nginx, Cloudflare, or a reverse proxy, those intermediate layers can modify or strip CORS headers. CORS works locally but fails in staging or production for this reason.
Fix: Check the response headers at each hop in your infrastructure chain. Ensure your load balancer and proxy configurations pass through Access-Control-* headers. This is a infrastructure problem, not a Spring Boot problem.
Not Caching Preflight Results
Without a maxAge setting, the browser sends a preflight OPTIONS request before every actual request. For high-frequency API calls, this doubles your request volume. Preflight caching eliminates this overhead for stable CORS policies.
Fix: Set maxAge(3600) (or a sensible duration for your policy stability) on your CORS configuration to cache preflight results for an hour.
Using CORS for Authorization
CORS only controls which origins can access your resources. It does not authenticate users or authorize actions. A request that passes CORS checks can still be rejected by your business logic for authorization reasons. Do not treat CORS headers as a security control.
Fix: Implement proper authentication and authorization in your application code, independent of CORS configuration.
Trade-off Table
| Scenario | Recommended Configuration | Rationale |
|---|---|---|
| Development environment | allowedOrigins(“*”) |
Simplifies testing across multiple localhost ports |
| Single frontend domain | Specific origin list | Restricts access to known domains only |
| Multiple trusted domains | Origin patterns with ** |
Supports subdomains without listing each |
| Credentials required | Explicit origins, allowCredentials(true) |
Required combination for auth cookies/tokens |
| Public API | allowedOrigins(“*”) with short maxAge |
No credential-based access expected |
| Third-party integration | Dedicated CORS config per integration | Isolates third-party access policies |
Observability Checklist
Having the right logging and monitoring in place makes CORS debugging tractable.
Verify that your application logs include CORS-related information at DEBUG or TRACE level. Spring’s CorsProcessor logs show when requests are allowed or denied and why.
Track the ratio of OPTIONS requests to actual requests. A spike in OPTIONS requests often means clients are not caching preflight results, which hurts performance.
Set up alerts for missing Access-Control-Allow-Origin headers in responses where you expect them.
Test CORS behavior in each environment using browser DevTools. Chrome’s Network tab shows CORS headers in responses, and the Console displays clear error messages when requests are blocked.
Quick Recap Checklist
Use this checklist when implementing or auditing CORS configuration.
- Identify all origins that need API access
- Choose global configuration, annotations, or Spring Security integration
- Never use
allowedOrigins(“*”)withallowCredentials(true) - Handle OPTIONS requests for all CORS-enabled endpoints
- Set appropriate
maxAgefor preflight caching - Validate CORS headers in development browser tools
- Test in staging environment with same-origin restrictions as production
- Document allowed origins for future maintainers
- Review CORS configuration during security audits
- Monitor CORS error rates in production
Interview Questions
A preflight request is an HTTP OPTIONS request the browser sends before the actual cross-origin request. It asks the server what origins, methods, and headers are permitted for the request that follows. This gives servers a chance to validate whether the request should be allowed before the potentially expensive or state-changing actual request is sent. Preflight results can be cached using the Access-Control-Max-Age header so the browser does not repeat the check for every request.
It would be a security hole. If credentials are allowed and any origin is allowed, any website could make authenticated requests to your API if a user visits a malicious page while already logged in. The CORS spec requires explicit origins when credentials are involved. Browsers enforce this rejection at the client level.
Spring Security integrates CORS into its filter chain rather than handling it separately. You configure a CorsConfigurationSource bean and pass it to the cors() method in your SecurityFilterChain. This ensures CORS headers are processed before authentication logic runs, which is necessary because preflight OPTIONS requests do not carry credentials. Spring Security also covers WebSocket endpoints and other protocol upgrades that standard MVC filters might miss.
allowedHeaders controls which request headers the browser may send — things like Content-Type, Authorization, or custom headers your JavaScript code sets. exposedHeaders controls which response headers the browser makes accessible to JavaScript code. By default, only a small set of safe response headers are exposed. If your API returns custom headers that the frontend needs to read, you must list them in exposedHeaders.
You can simulate preflight checks with curl. Send an OPTIONS request with the appropriate Origin and Access-Control-Request-Method headers and see what your server actually returns. Compare those response headers against what the browser expects. Check any proxies, load balancers, or gateways between your app and the internet. Enable detailed CORS logging in your application and look at access logs for OPTIONS request patterns and response codes. For ongoing monitoring, instrument your frontend to report CORS errors to your logging service.
The sameSite attribute controls when cookies are sent with cross-site requests. With sameSite=strict, cookies are never sent on cross-origin requests. With sameSite=lax, cookies are sent only for safe methods (GET, HEAD, OPTIONS) but not for POST, PUT, DELETE. With sameSite=none and Secure=true, cookies are sent on all cross-origin requests that also pass CORS validation. When using CORS with credentials, ensure your cookie's sameSite setting is compatible with your CORS origin policy, or users will experience authentication failures even when CORS headers are correct.
The Origin header is sent automatically by the browser during cross-origin requests and indicates the exact origin (protocol + domain + port) of the requesting page. It cannot be modified by JavaScript, making it trustworthy for CORS validation. The Referer header is older, contains the full URL of the requesting page (including path), can be stripped by browsers or extensions, and is not sent in all cross-origin scenarios. CORS specifications require Origin validation, not Referer validation, because Origin is more reliable and consistent.
CORS forces a separation between authentication methods. Cookie-based authentication requires careful sameSite and CORS credential configuration, which can be complex with multiple trusted origins. Token-based authentication (JWT in headers) works more naturally with CORS because the Authorization header is explicitly allowed and does not involve cookie state. Many modern API designs prefer header-based tokens specifically to avoid CORS credential complications. Additionally, CORS means authentication logic must not rely on cookies for cross-origin scenarios, pushing toward stateless token designs.
Without preflight caching (maxAge), every cross-origin request triggers a preflight OPTIONS request before the actual request, effectively doubling network round trips for non-simple requests. For high-frequency APIs, this significantly impacts latency and throughput. Setting appropriate maxAge values (e.g., 3600 seconds) caches preflight results, eliminating preflight overhead for subsequent requests within the cache window. However, longer maxAge means changes to CORS policy take longer to propagate since browsers cache the old configuration.
API gateways and reverse proxies (nginx, AWS ALB, Cloudflare) sit between the browser and your Spring Boot application and can modify or strip CORS headers. If CORS headers set by your application are removed by the proxy, browsers see no CORS approval and block requests. You must configure your proxy to pass through Access-Control-* headers, or configure CORS directly at the proxy layer. Many teams configure CORS at the gateway to handle it centrally rather than in each microservice, which is a valid architectural choice but requires consistent policy management.
The Same-Origin Policy (SOP) is the broad restriction that prevents scripts from one origin accessing resources from another. CORS is a specific mechanism that relaxes SOP by allowing servers to explicitly declare which cross-origin requests they permit. Without CORS, the browser blocks all cross-origin requests regardless of server intent. CORS adds the Access-Control-Allow-Origin header as a server-controlled override. SOP blocks both requests and responses; CORS allows servers to unblock responses by sending the appropriate header.
In microservices, you have two main approaches. First, configure CORS at the API gateway or load balancer layer so all services share one CORS policy. Second, configure CORS per-service when services need different policies (e.g., internal services vs public-facing ones). Service-to-service communication without browsers does not need CORS. If using Spring Cloud Gateway or a similar edge proxy, CORS is typically configured there. Ensure that whatever layer handles CORS runs before authentication filters since preflight requests lack credentials.
CORS works alongside other security headers. Content-Security-Policy (CSP) specifies which resources can be loaded and can restrict form submissions and script sources. Strict-Transport-Security (HSTS) ensures connections use HTTPS, preventing man-in-the-middle attacks that could modify Origin headers. X-Content-Type-Options prevents MIME type sniffing. The Referrer-Policy controls how much referrer information is shared. These headers together create defense in depth — CORS controls origin access while others control resource loading and transport security.
CORS does not prevent CSRF attacks. CORS controls which origins can make requests, but a malicious site can still send requests (without CORS headers) from a user's browser to your site — the browser will send cookies automatically. The SameSite cookie attribute is actually the effective defense against CSRF. CORS can help in a limited way if you require Authorization headers (which cannot be sent cross-origin without CORS permission), but the standard CSRF mitigation is SameSite cookies, CSRF tokens, or double-submit patterns. Do not rely on CORS for CSRF protection.
When a cross-origin request receives a redirect, the browser does not automatically include CORS headers on the redirected request. If your API returns a 302 redirect to a different origin, the browser will not follow it with CORS credentials. The preflight applies only to the initial URL, not to redirects. For API designs that use redirects, ensure redirects stay within allowed origins, or use JavaScript-based redirect handling that explicitly makes a new request to the redirect target with proper CORS context.
Non-standard methods must be explicitly listed in allowedMethods. By default, browsers only "simple" methods (GET, POST, HEAD) without preflight. Methods like PATCH, PUT, DELETE, or TRACE trigger preflight because they are less common. If your API uses PATCH for partial updates, you must include "PATCH" in allowedMethods. Similarly, custom HTTP methods your API defines must be explicitly allowed. This is a common oversight that causes PATCH requests to fail with CORS errors even when GET and POST work fine.
Simple requests meet all these criteria: GET, POST, or HEAD method; only safe headers (Accept, Accept-Language, Content-Language, Content-Type with application/x-www-form-urlencoded, multipart/form-data, or text/plain); no custom headers; no ReadableStream or XMLHttpRequestUpload objects. Simple requests go directly to the server with the Origin header and expect CORS headers in the response. Preflighted requests fail any of these criteria, trigger an OPTIONS preflight first, and wait for approval before sending the actual request. Understanding this distinction helps you optimize by avoiding unnecessary preflights.
Content-Type determines if a POST request is simple or requires preflight. POST with application/x-www-form-urlencoded, multipart/form-data, or text/plain is simple and skips preflight. POST with application/json (Content-Type: application/json) is not simple because it indicates structured data that might include custom headers, triggering a preflight. This is why sending JSON to your API from a frontend almost always requires CORS preflight handling. If you use form-encoded data for your API, you can avoid preflight complexity but lose the ability to send complex nested structures easily.
Access-Control-Allow-Origin missing means the server did not send any CORS header — configure CORS or check if the request is reaching your app. Access-Control-Allow-Origin value not matching Origin header means your allowedOrigins list does not include the requesting origin. Response to preflight has invalid HTTP status code means the OPTIONS endpoint returned something other than 200/204 — check your filter chain. Credentials not supported if Origin header is "*" is the wildcard+credentials rejection. Access-Control-Allow-Methods does not match indicates your allowedMethods does not include the method the browser wants to use.
Use a CORS proxy when you cannot configure the target server (third-party APIs, legacy systems) or when you need to aggregate multiple APIs under one origin for frontend convenience. The proxy adds CORS headers on behalf of the target. However, proxies become a bottleneck, add latency, hide errors, and introduce a single point of failure. If you control the server, configure CORS directly — it is more efficient, more reliable, and gives you full control over the policy. Proxies are a last resort for third-party APIs, not a preferred architecture.
Further Reading
- MDN Web Docs: CORS — Comprehensive browser reference on Cross-Origin Resource Sharing
- Spring CORS Documentation — Official Spring Boot CORS guide
- Spring Security CORS Integration — CORS in the Spring Security filter chain
- RFC 6454: The Origin Header — The IETF specification for the Origin concept
- CORS W3C Recommendation — Full CORS specification
- Chrome DevTools: Debug CORS — Using browser tools to diagnose CORS issues
- SameSite Cookies Explained — Understanding the sameSite attribute and its interaction with CORS
Conclusion
CORS is a browser-enforced mechanism that governs whether a web page at one origin can make requests to a server at a different origin. It exists because browsers enforce the same-origin policy by default, and CORS is the controlled relaxation of that policy through explicit server-side headers. Understanding that CORS does not apply to server-to-server communication—and therefore does not matter for backend services calling each other, native mobile apps, or CLI tools—is the foundation for not over-engineering CORS solutions where they are not needed.
Spring Boot gives you three ways to configure CORS: global configuration via WebMvcConfigurer, per-controller or per-method @CrossOrigin annotations, and Spring Security integration. Global configuration via WebMvcConfigurer is the right default for most applications because it keeps CORS policy in one auditable place. @CrossOrigin is useful when different endpoints genuinely need different origin policies. The Spring Security integration is required when you are already using Spring Security, because CORS filters must run before authentication filters for preflight OPTIONS requests to work correctly.
The most common CORS mistake in production is allowing allowedOrigins(“*”) while also setting allowCredentials(true)—a combination browsers explicitly reject as a security risk. Another common failure is forgetting that preflight OPTIONS requests must be handled, which happens automatically in Spring MVC but only if your filter chain is correctly configured. When your application sits behind an AWS ALB, nginx, or Cloudflare, those intermediate layers can strip CORS headers, causing failures that are impossible to reproduce locally. Always test CORS end-to-end in an environment that mirrors your production infrastructure topology. Setting a sensible maxAge value avoids unnecessary preflight round trips on every request for stable CORS policies, reducing latency for high-frequency API calls.
Category
Related Posts
Spring Boot Build Tools: Maven & Gradle
Configure Maven and Gradle for Spring Boot projects—plugins, dependency management, packaging JARs and WARs, and build automation essentials.
Embedded Web Servers in Spring Boot: Tomcat, Jetty, Undertow
Configure embedded servers in Spring Boot: compare Tomcat, Jetty, and Undertow, tune thread pools, enable access logs, and switch implementations.
JUnit 5 & Jupiter: Lifecycle, Nested & Parameterized Tests
Explore JUnit 5 Jupiter features: master test lifecycle annotations, organize tests with @Nested, and parameterize tests with @CsvSource and @MethodSource.