Testing CORS in Spring Boot
CORS (Cross-Origin Resource Sharing) is a mechanism that allows resources on a web server to be requested from another domain. In Spring Boot, configuring and testing CORS can be straightforward, especially with the support of tools like MockMvc. Let us delve to discuss and understand how to configure CORS in a Spring Boot application and how to test it using MockMvc.
1. Introduction
Cross-Origin Resource Sharing (CORS) is a security feature implemented by web browsers to control how resources on a web server can be requested from a different domain than the one that served the web page. This is essential in modern web applications where front-end applications, often served from a different domain (e.g., localhost:3000), need to interact with back-end services on another domain (e.g., api.example.com). Without CORS, browsers would block such cross-origin requests to protect users from potential security threats. However, when configured correctly, CORS allows safe and controlled communication between different domains. In a Spring Boot application, CORS can be configured at various levels to specify which domains are allowed to access the server’s resources, what HTTP methods are permitted, and whether credentials such as cookies can be shared. Understanding and testing CORS configuration is crucial for ensuring that your application behaves as expected in a cross-domain environment while maintaining security.
2. Configuring CORS in Spring Boot
Spring Boot provides several ways to configure CORS, such as through global configuration, controller-specific configuration, and using filters. Below is an example of global CORS configuration using a Spring configuration class.
2.1 Global CORS Configuration
The global CORS configuration is applied across the entire application. It can be done by defining a bean of type WebMvcConfigurer
in a configuration class.
// Import statements 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("/**") .allowedOrigins("http://localhost:3000") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("*") .allowCredentials(true); } }; } }
In the above code:
addMapping("/**")
: Configures CORS to be applied to all endpoints in the application.allowedOrigins("http://localhost:3000")
: Specifies the allowed origin for CORS requests. Here, only requests fromhttp://localhost:3000
are allowed.allowedMethods("GET", "POST", "PUT", "DELETE")
: Specifies the HTTP methods allowed for CORS requests.allowedHeaders("*")
: Allows all headers in CORS requests.allowCredentials(true)
: Allows sending credentials such as cookies in CORS requests.
Once the global configuration is in place, CORS is enabled for all endpoints across the application.
3. Testing CORS Using MockMvc
MockMvc is a powerful tool for testing Spring MVC applications. It can be used to simulate HTTP requests, including those with CORS configurations. Below is an example of how to test CORS using MockMvc.
3.1 Testing CORS with MockMvc
Let’s create a test class to verify the CORS configuration.
// Import statements import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest @AutoConfigureMockMvc public class CorsTest { @Autowired private MockMvc mockMvc; @Test public void testCorsHeaders() throws Exception { mockMvc.perform(options("/api/resource") .header("Origin", "http://localhost:3000") .header("Access-Control-Request-Method", "GET")) .andExpect(status().isOk()) .andExpect(header().string("Access-Control-Allow-Origin", "http://localhost:3000")) .andExpect(header().string("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE")) .andExpect(header().string("Access-Control-Allow-Headers", "*")) .andExpect(header().string("Access-Control-Allow-Credentials", "true")); } }
In the above test:
options("/api/resource")
: Simulates an HTTP OPTIONS request to the endpoint/api/resource
. OPTIONS requests are typically used by browsers to determine the allowed CORS methods and headers.header("Origin", "http://localhost:3000")
: Sets theOrigin
header to match the allowed origin in the CORS configuration.header("Access-Control-Request-Method", "GET")
: Simulates a CORS preflight request for the GET method.andExpect(status().isOk())
: Asserts that the response status is200 OK
.andExpect(header().string("Access-Control-Allow-Origin", "http://localhost:3000"))
: Verifies that theAccess-Control-Allow-Origin
header is correctly set.andExpect(header().string("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE"))
: Verifies that theAccess-Control-Allow-Methods
header is correctly set.andExpect(header().string("Access-Control-Allow-Headers", "*"))
: Verifies that theAccess-Control-Allow-Headers
header is correctly set.andExpect(header().string("Access-Control-Allow-Credentials", "true"))
: Verifies that theAccess-Control-Allow-Credentials
header is correctly set.
This test ensures that the CORS configuration is correctly applied to the specified endpoint.
3.1.1 Test Output
The expected output for the above test is as follows:
MockHttpServletResponse: Status = 200 Error message = null Headers = {Access-Control-Allow-Origin=[http://localhost:3000], Access-Control-Allow-Methods=[GET,POST,PUT,DELETE], Access-Control-Allow-Headers=[*], Access-Control-Allow-Credentials=[true]} Content type = null Body = Forwarded URL = null Redirected URL = null
The test output shows that the CORS headers are correctly applied to the response.
4. Conclusion
In this article, we explored how to configure CORS in a Spring Boot application and how to test it using MockMvc. By using the provided code examples, you can ensure that your application correctly handles CORS requests and passes CORS-related tests.