Configure CORS Policy for Spring Cloud Gateway
Cross-Origin Resource Sharing (CORS) is a mechanism that allows web applications hosted on one domain to interact with resources hosted on a different domain. By default, web browsers block such cross-origin requests for security reasons. However, with CORS, servers can explicitly allow specific origins, headers, and methods. In this article we will investigate how to configure CORS policy for Spring Cloud Gateway.
Spring Cloud Gateway is a popular API Gateway solution built on Spring Boot and Project Reactor. It provides a way to route and filter requests, adding features like rate limiting, path rewriting, and CORS handling to modern microservices architectures.
Properly configuring a CORS policy in Spring Cloud Gateway ensures that client applications, such as single-page applications (SPAs), can securely access APIs hosted on different domains.
1. Code Example
Here is a code example that uses Spring Cloud gateway to route requests and configure a CORS configuration. Before exploring the code, make sure to include the following dependencies in your pom.xml
file.
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> </dependencies>
1.1 Create a Main class
package com.example.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
1.1.1 Code explanation
The code defines the main class of a Spring Boot application using the @SpringBootApplication
annotation, which serves as a convenience annotation combining three essential annotations:
@Configuration
(for declaring Java-based configuration), @EnableAutoConfiguration
(for enabling Spring Boot’s auto-configuration mechanism), and @ComponentScan
(for scanning components in the package and its sub-packages).
The GatewayApplication
class includes the main
method, which serves as the entry point for the application. Inside the main
method, the static SpringApplication.run()
method is called, passing the GatewayApplication.class
and args
as parameters.
This method initializes the Spring application context, starts the embedded server (e.g., Tomcat or Netty), and bootstraps the entire Spring Boot application.
By running this class, the Spring Boot application is launched, enabling it to act as the gateway in a microservices architecture, handling incoming requests, routing them to appropriate backend services, and applying filters like the CORS policy.
1.2 Create a Configuration class
package com.example.gateway.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsWebFilter; import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; @Configuration public class CorsConfig { @Bean public CorsWebFilter corsWebFilter() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); // Allow all origins config.addAllowedMethod("*"); // Allow all HTTP methods config.addAllowedHeader("*"); // Allow all headers config.setAllowCredentials(true); // Allow credentials UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsWebFilter(source); } }
Note that a controller is not strictly required in this article, as the primary focus is on configuring the CORS policy in Spring Cloud Gateway rather than setting up a full backend API. However, you can add a mock backend service that is exposed at the URL /api/data
and runs on port 8081
.
@RestController @RequestMapping("/api") public class BackendController { @GetMapping("/data") public String getData() { return "Hello from Backend Service!"; } }
1.2.1 Code explanation
The CorsConfig
class is annotated with @Configuration
, indicating that it is a Spring configuration class. This class defines a bean for configuring Cross-Origin Resource Sharing (CORS) in the application.
The corsWebFilter
method is annotated with @Bean
, making it a Spring-managed bean. It creates and returns a CorsWebFilter
, which is a reactive filter for handling CORS requests in Spring WebFlux applications.
Inside the method, a CorsConfiguration
object is instantiated and configured:
config.addAllowedOrigin("*");
: Allows requests from all origins. This is useful for development but should be restricted to specific origins in production for security reasons.config.addAllowedMethod("*");
: Permits all HTTP methods, such as GET, POST, PUT, and DELETE.config.addAllowedHeader("*");
: Allows all HTTP headers to be sent in the request.config.setAllowCredentials(true);
: Enables the inclusion of credentials like cookies in cross-origin requests.
A UrlBasedCorsConfigurationSource
object is created to map the CORS configuration to specific URL patterns. The source.registerCorsConfiguration("/**", config);
line applies the CORS policy to all incoming requests (denoted by /**
).
Finally, a CorsWebFilter
is created using the configured UrlBasedCorsConfigurationSource
, ensuring that all requests passing through the application are subject to the defined CORS rules.
This configuration ensures that the application can handle cross-origin requests securely and flexibly, which is critical when serving APIs to frontend applications hosted on different domains.
1.3 Updating Application yml
spring: cloud: gateway: routes: - id: example-service uri: http://localhost:8081 predicates: - Path=/api/** server: port: 8080
1.3.1 Properties explanation
The provided configuration snippet is for setting up Spring Cloud Gateway and defining routing rules for incoming requests. Under spring.cloud.gateway.routes
, a route is defined with the following properties:
id: example-service
: This is a unique identifier for the route. It is used to refer to this specific route configuration within the application.uri: http://localhost:8081
: This specifies the target URI for the route. Any request matching the specified predicate will be forwarded to this URI. In this case, requests will be routed tolocalhost:8081
, which is presumably a backend service running on port 8081.predicates:
: This defines the conditions under which the route is triggered. In this case, the predicate isPath=/api/**
, meaning that any incoming request with a path starting with/api/
will be routed to the specified URI (i.e.,http://localhost:8081
).
Finally, the server.port: 8080
property specifies the port on which the Spring Boot application (in this case, Spring Cloud Gateway) will run. The application will listen for incoming requests on port 8080.
2. Run the code
To run the Spring Boot application, ensure that you have Maven installed on your system. Navigate to the project directory in your terminal and execute the command mvn spring-boot:run
. This will start the application, and the embedded web server will listen for requests on the port specified in the application.properties
file (default is 8080
).
Once the application is running, you can test the CORS policy using tools like Postman or your web browser’s developer tools. Ensure that the correct CORS headers are returned for cross-origin requests.
- Make a
GET
request tohttp://localhost:8080/api/data
from a client (e.g., a browser or Postman). - The request will be routed through the gateway, which applies the CORS policy, and forwarded to the backend service running at
http://localhost:8081/api/data
. - The backend service should respond with a message, such as
"Hello from Backend Service!"
.
3. Conclusion
Configuring a CORS policy in Spring Cloud Gateway is essential for enabling secure and seamless communication between client applications and backend services. By following the steps outlined in this article, you can ensure your API Gateway is CORS-compliant while maintaining security and flexibility.