SlideShare a Scribd company logo
1 of 34
Download to read offline
Dynamic OpenAPIs with
Spring Cloud Gateway
Iván López
@ilopmar
@ilopmar
Iván López
Who am I?
● Iván López (@ilopmar)
● JVM Developer
● Staff Software Engineer at VMware
● @MadridGUG Coordinator
● Speaker: GeeCon, Codemotion, Devoxx, SpringOne,
RigaDevDays, CommitConf, Spring IO,...
🇪🇸🇮🇹🇬🇧🇦🇹🇨🇦🇧🇪🇨🇿🇺🇦🇩🇰🇸🇪🇺🇸🇷🇺🇪🇪🇱🇻🇭🇷🇵🇱🇹🇷🇷🇴🇧🇬
OpenAPI
@ilopmar
Iván López
OpenAPI Specification
● Old Swagger Specification
● API description format for REST APIs
● Endpoints, operations, parameters, authentication,...
● Programming language agnostic
● YAML or JSON
@ilopmar
Iván López
Swagger
● Set of opensource tools build around OpenApi Spec
● Swagger Editor
● Swagger UI
● Swagger Codegen
● Swagger Core, Parser,...
@ilopmar
Iván López
Why use OpenAPI?
● Standard widely used
● Huge userbase
● Stable implementation
● Swagger Codegen to generate server stub and
client libraries!
● Integrations with many languages, libraries and
frameworks
Spring Cloud
Gateway
@ilopmar
Iván López
What is an API Gateway?
● API proxy between an API Client and API Server
● Single entry point for the backend API and services
● Cross-cuttings concerns: security, rate-limiting,
monitoring, logging, metrics,...
@ilopmar
Iván López
Spring Cloud Gateway
● API Gateway for the Spring Ecosystem
● Built on top Spring Boot, WebFlux and Reactor
● Dynamic routing
● Route matching: Path, Method, Header, Host,...
● Filters
● Rate Limiting, Circuit Breaker
● Path Rewriting
@ilopmar
Iván López
Spring Cloud Gateway Basics
● Route, Predicate and Filter
● Route Predicates: Cookie, Header, Host, Method,
Path,...
● Gateway Factories: Add/Remove
Request/Response Header/Parameter, Rewrite
path
● Global and custom filters
● YAML configuration & Programmatic API
@ilopmar
Iván López
Spring Cloud Gateway examples
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Foo, some-value
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: https://example.org
predicates:
- Path=/foo/**
filters:
- RewritePath=/foo/?(?<segment>.*), /${segment}
The problem
“I just want to expose
the OpenAPI of my
application”
@ilopmar
Iván López
Current status
● Spring Cloud Gateway in front of all different services
● All services expose OpenAPI
● API First?
– Code -> OpenAPI
– OpenAPI -> Code
● Internal endpoints vs Public endpoints
● Manual configuration in SCG
@ilopmar
Iván López
Requirements
● Expose product Public OpenAPI in Gateway
● Aggregate endpoints from different services
● Public endpoints defined on every service
● Optionally rewrite some endpoints
● Expose only public schemas and not all of them
● Rewrite and group tags
● Update Public OpenAPI and routing must be dynamic
@ilopmar
Iván López
My approach
● I did a 1 week spike
● We use SCG OSS
● The feature is available in SCG Commercial: Only
Tanzu Application Service and Kubernetes
● We deploy on K8S but wanted to keep everything
agnostic: local development, on-premise,...
● Libraries to read/write OpenAPI specifications
● SCG Programmatic API
Solution
@ilopmar
Iván López
Every service defines...
● Which endpoint is made public
paths:
/pipelines:
post:
x-vmw-public: true
summary: Create a new pipeline definition
description: Given a pipeline, it creates an execution
graph and prepares it to be run
@ilopmar
Iván López
Every service defines...
● How an endpoint is rewritten
paths:
/reports:
get:
x-vmw-public: true
x-vmw-rewrite: /vulnerabilities/reports
summary: Get all reports, optionally filtered by artifact version
description: It returns a collection of report metadata...
@ilopmar
Iván López
Every service defines...
● How tags are rewritten
tags:
- name: products
description: Using these endpoints you can manage the products...
x-vmw-rewrite: inventory
- name: artifacts
description: Using these endpoints you can manage the artifacts...
x-vmw-rewrite: inventory
- name: artifact-versions
description: Using these endpoints you can manage the artifact versions...
x-vmw-rewrite: inventory
- name: inventory
description: Using these endpoints you can see the products, artifacts and
artifact versions and their relationships in your organization inventory
@ilopmar
Iván López
Every service defines...
● How tags are rewritten
tags:
- name: products
description: Using these endpoints you can manage the products...
x-vmw-rewrite: inventory
- name: artifacts
description: Using these endpoints you can manage the artifacts...
x-vmw-rewrite: inventory
- name: artifact-versions
description: Using these endpoints you can manage the artifact versions...
x-vmw-rewrite: inventory
- name: inventory
description: Using these endpoints you can see the products, artifacts and
artifact versions and their relationships in your organization inventory
@ilopmar
Iván López
OpenAPI creation
● Gateway polls services every 5 minutes
● Filter, transform and combine all the OpenAPI specs
● Creates Public OpenAPI specification on the fly
@ilopmar
Iván López
Expose OpenAPI
@GetMapping(value = "/v1/api.yml", produces = APPLICATION_X_YAML)
public ResponseEntity<String> v1() {
return openApiService.generateOpenApi()
.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
@ilopmar
Iván López
Spring Cloud Gateway routes
@Bean
@RefreshScope
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder, RouteService routeService) {
RouteLocatorBuilder.Builder routeLocator = routeLocatorBuilder.routes();
List<GatewayRoute> gatewayRoutes = routeService.findGatewayRoutes();
for (GatewayRoute gatewayRoute : gatewayRoutes) {
routeLocator.route(gatewayRoute.routeId(), r -> r
.order(gatewayRoute.order())
.path(gatewayRoute.gatewayPath())
.and().method(gatewayRoute.openApiRoute().method())
.filters(gatewayFilterSpec -> gatewayFilterSpec.rewritePath(gatewayRoute.regexp(),
gatewayRoute.rewritePath())
)
.uri(gatewayRoute.openApiRoute().uri()));
}
return routeLocator.build();
}
● Routes refreshed dynamically
@ilopmar
Iván López
● Routes refreshed dynamically
Spring Cloud Gateway routes
@Bean
@RefreshScope
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder, RouteService routeService) {
RouteLocatorBuilder.Builder routeLocator = routeLocatorBuilder.routes();
List<GatewayRoute> gatewayRoutes = routeService.findGatewayRoutes();
for (GatewayRoute gatewayRoute : gatewayRoutes) {
routeLocator.route(gatewayRoute.routeId(), r -> r
.order(gatewayRoute.order())
.path(gatewayRoute.gatewayPath())
.and().method(gatewayRoute.openApiRoute().method())
.filters(gatewayFilterSpec -> gatewayFilterSpec.rewritePath(gatewayRoute.regexp(),
gatewayRoute.rewritePath())
)
.uri(gatewayRoute.openApiRoute().uri()));
}
return routeLocator.build();
}
@ilopmar
Iván López
Gateway Routes
public List<GatewayRoute> findGatewayRoutes() {
return openApiService.findOpenApiRoutes()
.stream()
.map(RouteConverter::convertOpenApiRouteToGatewayRoute)
.filter(Optional::isPresent)
.map(Optional::get)
.toList();
}
@ilopmar
Iván López
Example: Route conversion (I)
OpenApiRoute[
originalPath=/v1/reports
newPath=/v1/vulnerabilities/reports
method=GET
uri=https://vulnerability-service.xxxxxxxxxxxxx
]
GatewayRoute[
routeId=GET__/v1/vulnerabilities/reports
gatewayPath=/v1/vulnerabilities/reports
regexp=/v1/vulnerabilities/reports
rewritePath=/v1/reports
order=0
]
@ilopmar
Iván López
Example: Route conversion (II)
OpenApiRoute[
originalPath=/v1/target-platforms/{target_platform_id}
newPath=/v1/tp/{target_platform_id}
method=GET
uri=https://provisioning-service.xxxxxxxxxxxxx
]
GatewayRoute[
routeId=GET__/v1/tp/{target_platform_id}
gatewateyPath=/v1/tp/?*
regexp=/v1/tp/(?<id1>.*)
rewritePath=/v1/target-platforms/${id1}
order=10
]
@ilopmar
Iván López
Spring Cloud Gateway routes
@Bean
@RefreshScope
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder, RouteService routeService) {
RouteLocatorBuilder.Builder routeLocator = routeLocatorBuilder.routes();
List<GatewayRoute> openApiRoutes = routeService.findOpenApiRoutes();
for (GatewayRoute gatewayRoute : openApiRoutes) {
routeLocator.route(gatewayRoute.routeId(), r -> r
.order(gatewayRoute.order())
.path(gatewayRoute.gatewayPath())
.and().method(gatewayRoute.openApiRoute().method())
.filters(gatewayFilterSpec -> gatewayFilterSpec.rewritePath(gatewayRoute.regexp(),
gatewayRoute.rewritePath())
)
.uri(gatewayRoute.openApiRoute().uri()));
}
return routeLocator.build();
}
● Routes refreshed dynamically
@ilopmar
Iván López
Example: Gateway Routes (I)
OpenApiRoute[
originalPath=/v1/reports
newPath=/v1/vulnerabilities/reports
method=GET
uri=https://vulnerability-service...
]
GatewayRoute[
routeId=GET__/v1/vulnerabilities/reports
gatewateyPath=/v1/vulnerabilities/reports
regexp=/v1/vulnerabilities/reports
rewritePath=/v1/reports
order=0
]
routeLocator.route("GET__/v1/vulnerabilities/reports", r -> r
.order(0)
.path("/v1/vulnerabilities/reports")
.and().method("GET")
.filters(s -> s.rewritePath("/v1/vulnerabilities/reports", "/v1/reports"))
.uri("https://vulnerability-service.xxxxxxxxxxxxxxxxxx"));
@ilopmar
Iván López
Example: Gateway Routes (II)
OpenApiRoute[
originalPath=/v1/target-platforms/{target_platform_id}
newPath=/v1/tp/{target_platform_id}
method=GET
uri=https://provisioning-service...
]
GatewayRoute[
routeId=GET__/v1/tp/{target_platform_id}
gatewateyPath=/v1/tp/?*
regexp=/v1/tp/(?<id1>.*)
rewritePath=/v1/target-platforms/${id1}
order=10
]
routeLocator.route("GET__/v1/tp/{target_platform_id}", r -> r
.order(10)
.path("/v1/tp/?*")
.and().method("GET")
.filters(s -> s.rewritePath("/v1/tp/(?<id1>.*)", "/v1/target-platforms/${id1}"))
.uri("https://provisioning-service.xxxxxxxxxxxxxxx"));
Demo
@ilopmar
Iván López
Summary
Solved the problem
in one week
+1 year in Production
without problems
Reuse existing
OSS libraries
Platform agnostic Spring Cloud Gateway
is awesome
Public and Dynamic
OpenAPI
Thank you!
Questions?
Iván López
@ilopmar
lopez.ivan@gmail.com
https:/
/github.com/ilopmar
https:/
/bit.ly/springio-dynamic-apis

More Related Content

What's hot

RESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP FrameworkRESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP Framework
Bo-Yi Wu
 

What's hot (20)

Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
 
Angular 6 - The Complete Guide
Angular 6 - The Complete GuideAngular 6 - The Complete Guide
Angular 6 - The Complete Guide
 
Spring 3.x - Spring MVC - Advanced topics
Spring 3.x - Spring MVC - Advanced topicsSpring 3.x - Spring MVC - Advanced topics
Spring 3.x - Spring MVC - Advanced topics
 
Spring boot
Spring bootSpring boot
Spring boot
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Deep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKDeep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UK
 
GraalVM Overview Compact version
GraalVM Overview Compact versionGraalVM Overview Compact version
GraalVM Overview Compact version
 
RxJS - The Basics & The Future
RxJS - The Basics & The FutureRxJS - The Basics & The Future
RxJS - The Basics & The Future
 
Real Life Clean Architecture
Real Life Clean ArchitectureReal Life Clean Architecture
Real Life Clean Architecture
 
Exploring the power of Gradle in android studio - Basics & Beyond
Exploring the power of Gradle in android studio - Basics & BeyondExploring the power of Gradle in android studio - Basics & Beyond
Exploring the power of Gradle in android studio - Basics & Beyond
 
How to GraphQL
How to GraphQLHow to GraphQL
How to GraphQL
 
Introduction to gradle
Introduction to gradleIntroduction to gradle
Introduction to gradle
 
Fetch API Talk
Fetch API TalkFetch API Talk
Fetch API Talk
 
RESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP FrameworkRESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP Framework
 
Spring MVC
Spring MVCSpring MVC
Spring MVC
 
Practical non blocking microservices in java 8
Practical non blocking microservices in java 8Practical non blocking microservices in java 8
Practical non blocking microservices in java 8
 
Spring GraphQL
Spring GraphQLSpring GraphQL
Spring GraphQL
 
Spring data jpa
Spring data jpaSpring data jpa
Spring data jpa
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Reactive Card Magic: Understanding Spring WebFlux and Project Reactor
Reactive Card Magic: Understanding Spring WebFlux and Project ReactorReactive Card Magic: Understanding Spring WebFlux and Project Reactor
Reactive Card Magic: Understanding Spring WebFlux and Project Reactor
 

Similar to Spring IO 2023 - Dynamic OpenAPIs with Spring Cloud Gateway

Enforcing API Design Rules for High Quality Code Generation
Enforcing API Design Rules for High Quality Code GenerationEnforcing API Design Rules for High Quality Code Generation
Enforcing API Design Rules for High Quality Code Generation
Tim Burks
 

Similar to Spring IO 2023 - Dynamic OpenAPIs with Spring Cloud Gateway (20)

OpenAPI and gRPC Side by-Side
OpenAPI and gRPC Side by-SideOpenAPI and gRPC Side by-Side
OpenAPI and gRPC Side by-Side
 
LF_APIStrat17_OpenAPI and gRPC Side-by-Side
LF_APIStrat17_OpenAPI and gRPC Side-by-SideLF_APIStrat17_OpenAPI and gRPC Side-by-Side
LF_APIStrat17_OpenAPI and gRPC Side-by-Side
 
LCU14 310- Cisco ODP v2
LCU14 310- Cisco ODP v2LCU14 310- Cisco ODP v2
LCU14 310- Cisco ODP v2
 
OpenAPI Extensions for OSLC
OpenAPI Extensions for OSLCOpenAPI Extensions for OSLC
OpenAPI Extensions for OSLC
 
How to build a tool for operating Flink on Kubernetes
How to build a tool for operating Flink on KubernetesHow to build a tool for operating Flink on Kubernetes
How to build a tool for operating Flink on Kubernetes
 
Using JHipster 4 for generating Angular/Spring Boot apps
Using JHipster 4 for generating Angular/Spring Boot appsUsing JHipster 4 for generating Angular/Spring Boot apps
Using JHipster 4 for generating Angular/Spring Boot apps
 
apidays LIVE Australia 2020 - Have your cake and eat it too: GraphQL? REST? W...
apidays LIVE Australia 2020 - Have your cake and eat it too: GraphQL? REST? W...apidays LIVE Australia 2020 - Have your cake and eat it too: GraphQL? REST? W...
apidays LIVE Australia 2020 - Have your cake and eat it too: GraphQL? REST? W...
 
Build Great Networked APIs with Swift, OpenAPI, and gRPC
Build Great Networked APIs with Swift, OpenAPI, and gRPCBuild Great Networked APIs with Swift, OpenAPI, and gRPC
Build Great Networked APIs with Swift, OpenAPI, and gRPC
 
Introduction to Jhipster
Introduction to JhipsterIntroduction to Jhipster
Introduction to Jhipster
 
Enforcing API Design Rules for High Quality Code Generation
Enforcing API Design Rules for High Quality Code GenerationEnforcing API Design Rules for High Quality Code Generation
Enforcing API Design Rules for High Quality Code Generation
 
apidays LIVE Helsinki - Implementing OpenAPI and GraphQL Services with gRPC b...
apidays LIVE Helsinki - Implementing OpenAPI and GraphQL Services with gRPC b...apidays LIVE Helsinki - Implementing OpenAPI and GraphQL Services with gRPC b...
apidays LIVE Helsinki - Implementing OpenAPI and GraphQL Services with gRPC b...
 
BKK16-106 ODP Project Update
BKK16-106 ODP Project UpdateBKK16-106 ODP Project Update
BKK16-106 ODP Project Update
 
SFO15-102:ODP Project Update
SFO15-102:ODP Project UpdateSFO15-102:ODP Project Update
SFO15-102:ODP Project Update
 
Odo improving the developer experience on OpenShift - hack &amp; sangria
Odo   improving the developer experience on OpenShift - hack &amp; sangriaOdo   improving the developer experience on OpenShift - hack &amp; sangria
Odo improving the developer experience on OpenShift - hack &amp; sangria
 
Java2 days 5_agile_steps_to_cloud-ready_apps
Java2 days 5_agile_steps_to_cloud-ready_appsJava2 days 5_agile_steps_to_cloud-ready_apps
Java2 days 5_agile_steps_to_cloud-ready_apps
 
How we scale up our architecture and organization at Dailymotion
How we scale up our architecture and organization at DailymotionHow we scale up our architecture and organization at Dailymotion
How we scale up our architecture and organization at Dailymotion
 
Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...
Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...
Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...
 
Flink Forward Berlin 2018: Thomas Weise & Aljoscha Krettek - "Python Streamin...
Flink Forward Berlin 2018: Thomas Weise & Aljoscha Krettek - "Python Streamin...Flink Forward Berlin 2018: Thomas Weise & Aljoscha Krettek - "Python Streamin...
Flink Forward Berlin 2018: Thomas Weise & Aljoscha Krettek - "Python Streamin...
 
Nodejs
NodejsNodejs
Nodejs
 
Using JHipster for generating Angular/Spring Boot apps
Using JHipster for generating Angular/Spring Boot appsUsing JHipster for generating Angular/Spring Boot apps
Using JHipster for generating Angular/Spring Boot apps
 

More from Iván López Martín

More from Iván López Martín (20)

SalmorejoTech 2024 - Spring Boot <3 Testcontainers
SalmorejoTech 2024 - Spring Boot <3 TestcontainersSalmorejoTech 2024 - Spring Boot <3 Testcontainers
SalmorejoTech 2024 - Spring Boot <3 Testcontainers
 
CommitConf 2024 - Spring Boot <3 Testcontainers
CommitConf 2024 - Spring Boot <3 TestcontainersCommitConf 2024 - Spring Boot <3 Testcontainers
CommitConf 2024 - Spring Boot <3 Testcontainers
 
Voxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdf
Voxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdfVoxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdf
Voxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdf
 
VMware - Testcontainers y Spring Boot
VMware - Testcontainers y Spring BootVMware - Testcontainers y Spring Boot
VMware - Testcontainers y Spring Boot
 
CommitConf 2023 - Spring Framework 6 y Spring Boot 3
CommitConf 2023 - Spring Framework 6 y Spring Boot 3CommitConf 2023 - Spring Framework 6 y Spring Boot 3
CommitConf 2023 - Spring Framework 6 y Spring Boot 3
 
Construyendo un API REST con Spring Boot y GraalVM
Construyendo un API REST con Spring Boot y GraalVMConstruyendo un API REST con Spring Boot y GraalVM
Construyendo un API REST con Spring Boot y GraalVM
 
jLove 2020 - Micronaut and graalvm: The power of AoT
jLove 2020 - Micronaut and graalvm: The power of AoTjLove 2020 - Micronaut and graalvm: The power of AoT
jLove 2020 - Micronaut and graalvm: The power of AoT
 
Codemotion Madrid 2020 - Serverless con Micronaut
Codemotion Madrid 2020 - Serverless con MicronautCodemotion Madrid 2020 - Serverless con Micronaut
Codemotion Madrid 2020 - Serverless con Micronaut
 
JConf Perú 2020 - ¡Micronaut en acción!
JConf Perú 2020 - ¡Micronaut en acción!JConf Perú 2020 - ¡Micronaut en acción!
JConf Perú 2020 - ¡Micronaut en acción!
 
JConf Perú 2020 - Micronaut + GraalVM = <3
JConf Perú 2020 - Micronaut + GraalVM = <3JConf Perú 2020 - Micronaut + GraalVM = <3
JConf Perú 2020 - Micronaut + GraalVM = <3
 
JConf México 2020 - Micronaut + GraalVM = <3
JConf México 2020 - Micronaut + GraalVM = <3JConf México 2020 - Micronaut + GraalVM = <3
JConf México 2020 - Micronaut + GraalVM = <3
 
Developing Micronaut Applications With IntelliJ IDEA
Developing Micronaut Applications With IntelliJ IDEADeveloping Micronaut Applications With IntelliJ IDEA
Developing Micronaut Applications With IntelliJ IDEA
 
CommitConf 2019 - Micronaut y GraalVm: La combinación perfecta
CommitConf 2019 - Micronaut y GraalVm: La combinación perfectaCommitConf 2019 - Micronaut y GraalVm: La combinación perfecta
CommitConf 2019 - Micronaut y GraalVm: La combinación perfecta
 
Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!
Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!
Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!
 
Greach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut ConfigurationsGreach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut Configurations
 
VoxxedDays Bucharest 2019 - Alexa, nice to meet you
VoxxedDays Bucharest 2019 - Alexa, nice to meet youVoxxedDays Bucharest 2019 - Alexa, nice to meet you
VoxxedDays Bucharest 2019 - Alexa, nice to meet you
 
JavaDay Lviv 2019 - Micronaut in action!
JavaDay Lviv 2019 - Micronaut in action!JavaDay Lviv 2019 - Micronaut in action!
JavaDay Lviv 2019 - Micronaut in action!
 
CrossDvlup Madrid 2019 - Alexa, encantado de conocerte
CrossDvlup Madrid 2019 - Alexa, encantado de conocerteCrossDvlup Madrid 2019 - Alexa, encantado de conocerte
CrossDvlup Madrid 2019 - Alexa, encantado de conocerte
 
Madrid-GUG - ¡Micronaut en acción!
Madrid-GUG - ¡Micronaut en acción!Madrid-GUG - ¡Micronaut en acción!
Madrid-GUG - ¡Micronaut en acción!
 
Codemotion Madrid 2018 - Microservicios Reactivos con Micronaut
Codemotion Madrid 2018 - Microservicios Reactivos con MicronautCodemotion Madrid 2018 - Microservicios Reactivos con Micronaut
Codemotion Madrid 2018 - Microservicios Reactivos con Micronaut
 

Recently uploaded

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Recently uploaded (20)

AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
API Governance and Monetization - The evolution of API governance
API Governance and Monetization -  The evolution of API governanceAPI Governance and Monetization -  The evolution of API governance
API Governance and Monetization - The evolution of API governance
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
 
Quantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation ComputingQuantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation Computing
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Choreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software EngineeringChoreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software Engineering
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Simplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptxSimplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptx
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 

Spring IO 2023 - Dynamic OpenAPIs with Spring Cloud Gateway

  • 1. Dynamic OpenAPIs with Spring Cloud Gateway Iván López @ilopmar
  • 2. @ilopmar Iván López Who am I? ● Iván López (@ilopmar) ● JVM Developer ● Staff Software Engineer at VMware ● @MadridGUG Coordinator ● Speaker: GeeCon, Codemotion, Devoxx, SpringOne, RigaDevDays, CommitConf, Spring IO,... 🇪🇸🇮🇹🇬🇧🇦🇹🇨🇦🇧🇪🇨🇿🇺🇦🇩🇰🇸🇪🇺🇸🇷🇺🇪🇪🇱🇻🇭🇷🇵🇱🇹🇷🇷🇴🇧🇬
  • 4. @ilopmar Iván López OpenAPI Specification ● Old Swagger Specification ● API description format for REST APIs ● Endpoints, operations, parameters, authentication,... ● Programming language agnostic ● YAML or JSON
  • 5. @ilopmar Iván López Swagger ● Set of opensource tools build around OpenApi Spec ● Swagger Editor ● Swagger UI ● Swagger Codegen ● Swagger Core, Parser,...
  • 6. @ilopmar Iván López Why use OpenAPI? ● Standard widely used ● Huge userbase ● Stable implementation ● Swagger Codegen to generate server stub and client libraries! ● Integrations with many languages, libraries and frameworks
  • 8. @ilopmar Iván López What is an API Gateway? ● API proxy between an API Client and API Server ● Single entry point for the backend API and services ● Cross-cuttings concerns: security, rate-limiting, monitoring, logging, metrics,...
  • 9. @ilopmar Iván López Spring Cloud Gateway ● API Gateway for the Spring Ecosystem ● Built on top Spring Boot, WebFlux and Reactor ● Dynamic routing ● Route matching: Path, Method, Header, Host,... ● Filters ● Rate Limiting, Circuit Breaker ● Path Rewriting
  • 10. @ilopmar Iván López Spring Cloud Gateway Basics ● Route, Predicate and Filter ● Route Predicates: Cookie, Header, Host, Method, Path,... ● Gateway Factories: Add/Remove Request/Response Header/Parameter, Rewrite path ● Global and custom filters ● YAML configuration & Programmatic API
  • 11. @ilopmar Iván López Spring Cloud Gateway examples spring: cloud: gateway: routes: - id: method_route uri: https://example.org predicates: - Method=GET,POST spring: cloud: gateway: routes: - id: add_request_header_route uri: https://example.org filters: - AddRequestHeader=X-Foo, some-value spring: cloud: gateway: routes: - id: rewritepath_route uri: https://example.org predicates: - Path=/foo/** filters: - RewritePath=/foo/?(?<segment>.*), /${segment}
  • 13. “I just want to expose the OpenAPI of my application”
  • 14. @ilopmar Iván López Current status ● Spring Cloud Gateway in front of all different services ● All services expose OpenAPI ● API First? – Code -> OpenAPI – OpenAPI -> Code ● Internal endpoints vs Public endpoints ● Manual configuration in SCG
  • 15. @ilopmar Iván López Requirements ● Expose product Public OpenAPI in Gateway ● Aggregate endpoints from different services ● Public endpoints defined on every service ● Optionally rewrite some endpoints ● Expose only public schemas and not all of them ● Rewrite and group tags ● Update Public OpenAPI and routing must be dynamic
  • 16. @ilopmar Iván López My approach ● I did a 1 week spike ● We use SCG OSS ● The feature is available in SCG Commercial: Only Tanzu Application Service and Kubernetes ● We deploy on K8S but wanted to keep everything agnostic: local development, on-premise,... ● Libraries to read/write OpenAPI specifications ● SCG Programmatic API
  • 18. @ilopmar Iván López Every service defines... ● Which endpoint is made public paths: /pipelines: post: x-vmw-public: true summary: Create a new pipeline definition description: Given a pipeline, it creates an execution graph and prepares it to be run
  • 19. @ilopmar Iván López Every service defines... ● How an endpoint is rewritten paths: /reports: get: x-vmw-public: true x-vmw-rewrite: /vulnerabilities/reports summary: Get all reports, optionally filtered by artifact version description: It returns a collection of report metadata...
  • 20. @ilopmar Iván López Every service defines... ● How tags are rewritten tags: - name: products description: Using these endpoints you can manage the products... x-vmw-rewrite: inventory - name: artifacts description: Using these endpoints you can manage the artifacts... x-vmw-rewrite: inventory - name: artifact-versions description: Using these endpoints you can manage the artifact versions... x-vmw-rewrite: inventory - name: inventory description: Using these endpoints you can see the products, artifacts and artifact versions and their relationships in your organization inventory
  • 21. @ilopmar Iván López Every service defines... ● How tags are rewritten tags: - name: products description: Using these endpoints you can manage the products... x-vmw-rewrite: inventory - name: artifacts description: Using these endpoints you can manage the artifacts... x-vmw-rewrite: inventory - name: artifact-versions description: Using these endpoints you can manage the artifact versions... x-vmw-rewrite: inventory - name: inventory description: Using these endpoints you can see the products, artifacts and artifact versions and their relationships in your organization inventory
  • 22. @ilopmar Iván López OpenAPI creation ● Gateway polls services every 5 minutes ● Filter, transform and combine all the OpenAPI specs ● Creates Public OpenAPI specification on the fly
  • 23. @ilopmar Iván López Expose OpenAPI @GetMapping(value = "/v1/api.yml", produces = APPLICATION_X_YAML) public ResponseEntity<String> v1() { return openApiService.generateOpenApi() .map(ResponseEntity::ok) .orElseGet(() -> ResponseEntity.notFound().build()); }
  • 24. @ilopmar Iván López Spring Cloud Gateway routes @Bean @RefreshScope public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder, RouteService routeService) { RouteLocatorBuilder.Builder routeLocator = routeLocatorBuilder.routes(); List<GatewayRoute> gatewayRoutes = routeService.findGatewayRoutes(); for (GatewayRoute gatewayRoute : gatewayRoutes) { routeLocator.route(gatewayRoute.routeId(), r -> r .order(gatewayRoute.order()) .path(gatewayRoute.gatewayPath()) .and().method(gatewayRoute.openApiRoute().method()) .filters(gatewayFilterSpec -> gatewayFilterSpec.rewritePath(gatewayRoute.regexp(), gatewayRoute.rewritePath()) ) .uri(gatewayRoute.openApiRoute().uri())); } return routeLocator.build(); } ● Routes refreshed dynamically
  • 25. @ilopmar Iván López ● Routes refreshed dynamically Spring Cloud Gateway routes @Bean @RefreshScope public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder, RouteService routeService) { RouteLocatorBuilder.Builder routeLocator = routeLocatorBuilder.routes(); List<GatewayRoute> gatewayRoutes = routeService.findGatewayRoutes(); for (GatewayRoute gatewayRoute : gatewayRoutes) { routeLocator.route(gatewayRoute.routeId(), r -> r .order(gatewayRoute.order()) .path(gatewayRoute.gatewayPath()) .and().method(gatewayRoute.openApiRoute().method()) .filters(gatewayFilterSpec -> gatewayFilterSpec.rewritePath(gatewayRoute.regexp(), gatewayRoute.rewritePath()) ) .uri(gatewayRoute.openApiRoute().uri())); } return routeLocator.build(); }
  • 26. @ilopmar Iván López Gateway Routes public List<GatewayRoute> findGatewayRoutes() { return openApiService.findOpenApiRoutes() .stream() .map(RouteConverter::convertOpenApiRouteToGatewayRoute) .filter(Optional::isPresent) .map(Optional::get) .toList(); }
  • 27. @ilopmar Iván López Example: Route conversion (I) OpenApiRoute[ originalPath=/v1/reports newPath=/v1/vulnerabilities/reports method=GET uri=https://vulnerability-service.xxxxxxxxxxxxx ] GatewayRoute[ routeId=GET__/v1/vulnerabilities/reports gatewayPath=/v1/vulnerabilities/reports regexp=/v1/vulnerabilities/reports rewritePath=/v1/reports order=0 ]
  • 28. @ilopmar Iván López Example: Route conversion (II) OpenApiRoute[ originalPath=/v1/target-platforms/{target_platform_id} newPath=/v1/tp/{target_platform_id} method=GET uri=https://provisioning-service.xxxxxxxxxxxxx ] GatewayRoute[ routeId=GET__/v1/tp/{target_platform_id} gatewateyPath=/v1/tp/?* regexp=/v1/tp/(?<id1>.*) rewritePath=/v1/target-platforms/${id1} order=10 ]
  • 29. @ilopmar Iván López Spring Cloud Gateway routes @Bean @RefreshScope public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder, RouteService routeService) { RouteLocatorBuilder.Builder routeLocator = routeLocatorBuilder.routes(); List<GatewayRoute> openApiRoutes = routeService.findOpenApiRoutes(); for (GatewayRoute gatewayRoute : openApiRoutes) { routeLocator.route(gatewayRoute.routeId(), r -> r .order(gatewayRoute.order()) .path(gatewayRoute.gatewayPath()) .and().method(gatewayRoute.openApiRoute().method()) .filters(gatewayFilterSpec -> gatewayFilterSpec.rewritePath(gatewayRoute.regexp(), gatewayRoute.rewritePath()) ) .uri(gatewayRoute.openApiRoute().uri())); } return routeLocator.build(); } ● Routes refreshed dynamically
  • 30. @ilopmar Iván López Example: Gateway Routes (I) OpenApiRoute[ originalPath=/v1/reports newPath=/v1/vulnerabilities/reports method=GET uri=https://vulnerability-service... ] GatewayRoute[ routeId=GET__/v1/vulnerabilities/reports gatewateyPath=/v1/vulnerabilities/reports regexp=/v1/vulnerabilities/reports rewritePath=/v1/reports order=0 ] routeLocator.route("GET__/v1/vulnerabilities/reports", r -> r .order(0) .path("/v1/vulnerabilities/reports") .and().method("GET") .filters(s -> s.rewritePath("/v1/vulnerabilities/reports", "/v1/reports")) .uri("https://vulnerability-service.xxxxxxxxxxxxxxxxxx"));
  • 31. @ilopmar Iván López Example: Gateway Routes (II) OpenApiRoute[ originalPath=/v1/target-platforms/{target_platform_id} newPath=/v1/tp/{target_platform_id} method=GET uri=https://provisioning-service... ] GatewayRoute[ routeId=GET__/v1/tp/{target_platform_id} gatewateyPath=/v1/tp/?* regexp=/v1/tp/(?<id1>.*) rewritePath=/v1/target-platforms/${id1} order=10 ] routeLocator.route("GET__/v1/tp/{target_platform_id}", r -> r .order(10) .path("/v1/tp/?*") .and().method("GET") .filters(s -> s.rewritePath("/v1/tp/(?<id1>.*)", "/v1/target-platforms/${id1}")) .uri("https://provisioning-service.xxxxxxxxxxxxxxx"));
  • 32. Demo
  • 33. @ilopmar Iván López Summary Solved the problem in one week +1 year in Production without problems Reuse existing OSS libraries Platform agnostic Spring Cloud Gateway is awesome Public and Dynamic OpenAPI