Spring API Gateway
👉 Learn Spring Cloud concepts.
8. API Gateway
Project ref: b7-api-gateway
- Purpose / Feature
- All requests will be routed via API Gateway.
- This gives us flexibility to implement all common features at one place.
- Build on top of Spring WebFlux (Reactive Approach).
- Provide cross cutting concerns
- Security
- Monitoring / Metrics
- Features:
- Match routes to any request attribute to route to right service.
- Allows to define Predicates (Matcher) & Filters (eg. Authentication, Authorization, Logging etc.).
- Integrates with Spring Cloud Discovery client to load balancing to the service for which the request is received.
- Path rewriting.
- Steps
- Step-1: Ensure following dependencies are added.
- Eureka Discovery Client
- Reactive API Gateay
- Step-2: Enable API gateway client discovery in
application.properties - Step-3: Now, we can access services with the Service name registered in Eureka server and path to controller API.
- http://localhost:8765/B5-CURRENCY-CONVERSION-SERVICE-OPENFEIGN/currency-conversion-feign/from/UsD/to/iNr/quantity/100
- Step-4: Add property to accept service name in lower case
- http://localhost:8765/b5-currency-conversion-service-openfeign/currency-conversion-feign/from/UsD/to/iNr/quantity/100
- Step-1: Ensure following dependencies are added.
- Maven / External dependency
- Required dependency. ```xml
org.springframework.cloud spring-cloud-starter-gateway org.springframework.cloud spring-cloud-starter-netflix-eureka-client
- Required dependency. ```xml
- Code / Config changes
- Application Config:application.properties
spring.application.name=b7-api-gateway server.port=8765 # Start: Eureka client config # Map of availability zone to list of fully qualified URLs to communicate with eureka server. # Each value can be a single URL or a comma separated list of alternative locations. # Typically the eureka server URLs carry protocol,host,port,context and version information if any. # Example: https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ eureka.client.service-url.defaultZone=http://localhost:8761/eureka # Enables the Eureka health check handler. eureka.client.healthcheck.enabled=true eureka.instance.lease-renewal-interval-in-seconds=60 eureka.instance.lease-expiration-duration-in-seconds=60 # End: Eureka client config # Start: Api Gateway # Flag that enables Discovery Client gateway integration. # This allows us to invoke service using service-name registered in Eureka # http://localhost:8765/B3-CURRENCY-EXCHANGE-SERVICE/currency-exchange/from/usd/to/inr spring.cloud.gateway.discovery.locator.enabled=true # Option to lower case serviceId in predicates and filters, defaults to false. # Useful with eureka when it automatically uppercases serviceId. so MYSERIVCE, would match /myservice/** spring.cloud.gateway.discovery.locator.lower-case-service-id=true # End: Api Gateway
- Application Config:application.properties
Note: This is an important note.
- Notes:
- Service client discovery is
disabledby default. It need to be enabed explicitly inapplication.properties. Check above config for details.
- Service client discovery is
- References:
9. Routes with spring cloud gateway
Project ref: b8-api-gateway-routes
- Purpose / Feature
- API Gateway
RoutersandFiltersprovides the option to intercept and process the requests. - It provides methods/APIs to match request on any attribute -
method, header, cookie, path, host etc.. - It allow to route specific URLs to desired service.
- We can add HTTP headers & params in the request.
- We can also rewrite the URL.
- We can also implement common checks such as authentication, authorization, logging etc.
- API Gateway
- Steps
- Step-1: Considering tht API Gateway is already implemented.
- If not, refer
section 8above for API Gateway coniguration.
- If not, refer
- Step-2: Update application configuration in
application.properties.- Disable
gateway discovery locatorconfiguration inapplication.propertiesto auto discover clients from Eureka server.
- Disable
- Step-3: Create a Configuration class.
- Create a Bean of
o.s.c.gateway.route.RouteLocatorclass with method acceptingRouteLocatorBuilderclass as argument. - Now using
RouteLocatorBuilderinstance, we can customize routes, e.g.- Route any URL to
lb://<service-name-in-eureka>to redirect and do load-balancing. - Route to any external service http://httpbin.org/.
- Request failing for
HTTPSrequests, requires SSL confguration.
- Request failing for
- Rewrite the requested URL to corresponfing inernal service URL using filters.
- Route any URL to
- Create a Bean of
- Step-1: Considering tht API Gateway is already implemented.
- Maven / External dependency
- Required dependency. ```xml
org.springframework.cloud spring-cloud-starter-gateway org.springframework.cloud spring-cloud-starter-netflix-eureka-client
- Required dependency. ```xml
- Code / Config changes
- Configuratio:ApiGatewayConfiguration.java
- imports
import org.springframework.cloud.gateway.route.RouteLocator;import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder.Builder;
- Create a
BeanofRouteLocatorclass. ```java /**Configuration class to build custom routes and request customization. */ @Configuration public class ApiGatewayConfiguration {
/**
- Define routes.
- @param routeLocatorBuilder
- @return / @Bean RouteLocator getwayRoute(RouteLocatorBuilder routeLocatorBuilder) { /
- Redirect request to external service. Also, optionally we can add http
- headers and request params in the request. */ Builder routeLocator = routeLocatorBuilder.routes() .route((p) -> p.path(“/get”) .filters(f -> f.addRequestHeader(“MY-HEADER”, “MY-CUSTOM-HEADER”) .addRequestParameter(“MY-REQUEST-PARAM”, “MY-CUSTOM-REQUEST-PARAM”)) .uri(“http://httpbin.org:80/”));
/**
- Route URLs to load balancer and eureka service name */ routeLocator = routeLocator.route(p -> p.path(“/currency-exchange/”).uri(“lb://b3-currency-exchange-service”)) .route(p -> p.path(“/currency-conversion-feign/”) .uri(“lb://b5-currency-conversion-service-openfeign”));
/**
- Rewrite URL and copy the path */ routeLocator.route(p -> p.path(“/ccfs/**”) .filters(f -> f.rewritePath(“/ccfs/(?
.*)", "/currency-conversion-feign/${segment}")) .uri("lb://b5-currency-conversion-service-openfeign"));
return routeLocator.build(); } } ```
- imports
- Application Config:application.properties
spring.application.name=b8-api-gateway-routes server.port=8765 # Start: Eureka client config # Map of availability zone to list of fully qualified URLs to communicate with eureka server. # Each value can be a single URL or a comma separated list of alternative locations. # Typically the eureka server URLs carry protocol,host,port,context and version information if any. # Example: https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ eureka.client.service-url.defaultZone=http://localhost:8761/eureka # Enables the Eureka health check handler. eureka.client.healthcheck.enabled=true eureka.instance.lease-renewal-interval-in-seconds=60 eureka.instance.lease-expiration-duration-in-seconds=60 # End: Eureka client config # Start: Api Gateway # Flag that enables Discovery Client gateway integration. # This allows us to invoke service using service-name registered in Eureka # http://localhost:8765/B3-CURRENCY-EXCHANGE-SERVICE/currency-exchange/from/usd/to/inr # Disbling - to use Routes and Filters #spring.cloud.gateway.discovery.locator.enabled=true spring.cloud.gateway.discovery.locator.enabled=false # Option to lower case serviceId in predicates and filters, defaults to false. # Useful with eureka when it automatically uppercases serviceId. so MYSERIVCE, would match /myservice/** # Disbling - to use Routes and Filters #spring.cloud.gateway.discovery.locator.lower-case-service-id=true spring.cloud.gateway.discovery.locator.lower-case-service-id=false # Option to lower case serviceId in predicates and filters, defaults to false. # Useful with eureka when it automatically uppercases serviceId. so MYSERIVCE, would match /myservice/** # spring.cloud.gateway.discovery.locator.lowerCaseServiceId=true # End: Api Gateway
- Configuratio:ApiGatewayConfiguration.java
Note: When using routes in API Gateway, eureka discover client must be disabled in
application.properties.
10. API Gateway : Global filter
Project ref: b8-api-gateway-routes
- Purpose / Feature
- Contract for interception-style, chained processing of gateway requests that may be used to implement cross-cutting, application-agnostic requirements such as security, timeouts, and others
- Only applies to matched gateway routes. Copied from framework WebFilter.
- Steps
- Step-1: Considering tht API Gateway is already implemented with working routes config
- If not, refer
section 8§ion 9above for API Gateway coniguration.
- If not, refer
- Step-2: Create a class implementing
o.s.c.g.filter.GlobalFilter class. - Step-3: Override
filter(....) methodand add the business logic.
- Step-1: Considering tht API Gateway is already implemented with working routes config
- Maven / External dependency
- Required dependency. ```xml
org.springframework.cloud spring-cloud-starter-gateway org.springframework.cloud spring-cloud-starter-netflix-eureka-client
- Required dependency. ```xml
- Code / Config changes
- Configuration:LoggingGlobalFilter.java
- imports
import some.dependent.resourceimport org.springframework.cloud.gateway.filter.GatewayFilterChain;import org.springframework.cloud.gateway.filter.GlobalFilter;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;
- Implement
o.s.c.g.filter.GlobalFilter classandfilter(...) method.@Component public class LoggingGlobalFilter implements GlobalFilter { private static Logger logger = LoggerFactory.getLogger(LoggingGlobalFilter.class); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // log the request logger.info("Request -> Method: {}, Path: {}", exchange.getRequest().getMethod(), exchange.getRequest().getPath()); return chain.filter(exchange); } }
- imports
- Configuration:LoggingGlobalFilter.java