Spring cloud Gateway - spring

I have anexo API with some endpoints, like:
Localhsost:8080/api/clients -> GET findall
Localhsost:8080/api/clients/id -> GET findByID
Localhsost:8080/api/clients -> POST insert a cliente
Localhsost:8080/api/clients/id DELETE deleteByID
How do I use Spring Cloud Gateway with those endpoints?

If you're having trouble seeing where to start you could try following property-based the example from the dzone article 'Spring Cloud Gateway - Configuring a Simple Route'. You could configure just one of your services to begin with. That example suggests creating a spring cloud gateway project from the spring initializr by selecting the 'gateway' dependency and adding a route to the application.yaml:
spring:
cloud:
gateway:
routes:
- predicates:
- Path=/props/**
filters:
- StripPrefix=1
uri: "http://httpbin.org"
So you could replace httpbin.org with localhost:8080 and replace /props/** with your path - /api/clients/**. You could test that by making an http get call and then try adding in a second service afterwards. In your case I suspect you want to remove the filter to strip the prefix as it sounds like your service is exposing an /api/clients endpoint so you'd presumably want to preserve that whole path. That's something you'd need to check.

Related

Is there a way to route sub calls as well from spring cloud gateway routes?

I am building a spring cloud gateway to act as gateway with multiple backends. Some backends are internally calling websocket call ws://x.x.x.x:0000
user -> http://localhost:8085/ -> http://x.x.x.x:0000 -> ws://x.x.x.x:0000/websockify
if i don't explicitly setup a route for websocket call as well, it is taking localhost:8085 as host and port from origin server but not from http://x.x.x.x:0000.
Below is my application.yaml of spring cloud gateway and it is working. But i dont want to mention websocket_route which is being made internally from first route uri (http://x.x.x.x:0000) and i have other apps also internally making similar calls so can't setup individual routes for every app. please help
spring:
cloud:
gateway:
routes:
- id: inst-user1-target-77
uri: http://x.x.x.x:0000
predicates:
- Path=/inst-user1-target-77/**
filters:
- RewritePath=/inst-user1-target-77/(?<segment>.*), /$\{segment}
- id: websocket_route
uri: ws://x.x.x.x:0000
predicates:
- Path=/websockify

How to use SetPath with query strings in Spring Cloud Gateway

I am using Spring Cloud Gateway and I am trying to remap a url to another one (using the SetPath filter) that uses a query string (involves a ?).
Consider the Spring Cloud Gateway config YAML below:
spring:
cloud:
gateway:
routes:
- id: demoEndpoint
uri: lb://demo-service
predicates:
- Path=/api/v1/user/{userId}/items
filters:
- SetPath=/items?searchUser={userId}
When I do a GET request on the endpoint (/api/v1/user/testUserId/items), Spring Cloud Gateway maps the request to: lb://demo-service/items but what I expected to get is lb://demo-service/items?searchUser=testUserId
It appears that Gateway has some issue when a question mark is involved in the path.
Question
How do I use query string in SetPath? Do I need to escape the ? character? Or is this a bug in Spring Cloud Gateway?
Other Info
I have tried this other config:
spring:
cloud:
gateway:
routes:
- id: demoEndpoint
uri: lb://demo-service
predicates:
- Path=/api/v1/user/{userId}/items
filters:
- SetPath=/items/searchUser={userId}
When I do a GET request on the endpoint (/api/v1/user/testUserId/items), Spring Cloud Gateway maps the request to: lb://demo-service/items/searchUser=testUserId
This helps me confirm that setPath is finding the uri segments properly (userId) and that only usage of the question mark might be causing issues.
Spring Cloud version: 2021.0.1
Spring Cloud Gateway version: 3.1.1

Calling resource server with JWT returns HTTP 403 by way of Spring Cloud Gateway

I have two projects. Both are reactive Spring. Project one is a combination of a Javascript application and Spring Cloud Gateway for reverse proxying. The second project is a Spring resource server.
Project one proxies requests from /api/artists to project two at http://localhost:8081/v1/artists.
If I call the resource server (project two) directly with a valid JWT, the response comes back HTTP 200. If I go by way of the reverse proxy in project one, and hit http://localhost:8080/api/artists with the same JWT, I receive an HTTP 403 from project two, which propagates back through project one.
Here is my Spring Cloud Gateway configuration:
spring:
cloud:
gateway:
routes:
- id: experience-api
uri: http://localhost:8081/v1/artists
predicates:
- Path=/api/artists/**
filters:
- TokenRelay=
The HTTP 403 indicates that while the token was valid, it must be lacking some other permission to perform the action. Though, I'm not sure why it works when I call it directly versus calling it by way of the reverse proxy/Spring Cloud Gateway.
After stepping away for a couple days, I realized that my gateway configuration was incorrect. I realized that the original configuration was proxying requests to /v1/artists/api/artists, which doesn't exist on project two, but my security configuration was set up so that /v1/** required authentication. I suspect that is why I saw an HTTP 403 Forbidden before I saw an HTTP 404 Not Found.
I ended up using the below configuration:
spring:
cloud:
gateway:
routes:
- id: experience-api
uri: http://localhost:8081
predicates:
- Path=/v1/artists/**
filters:
- TokenRelay=
Note that I removed /v1/artists from the uri property. Now, requests to project one at http://localhost:8080/v1/artists are getting proxied to http://localhost:8081/v1/artists. I could have used the StripToken predicate filter but it wasn't as clean as this.

Can Spring Cloud Gateway map a single request to two downstream services?

The background is my application needs to insert an user input into two databases, which are MongoDB and Elasticsearch. There are already two database-level services with save function.
Now I am working on an experiment to duplicate a single request to two downstream database services.
I have tried using Spring Cloud Gateway with routes, it can route a request to either MongoDB or Elasticsearch.
If the route to MongoDB is placed advanced of that to Elasticsearch, then Spring Cloud Gateway routes the request to MongoDB. The route to Elasticsearch is ignored even it has the same predicates with MongoDB's. And vice versa.
Here is the configuration in Yaml. Can anyone advise if duplicating a request is doable or not in Spring Cloud Gateway ? Thanks.
spring:
cloud:
gateway:
routes:
- id: http-others-route-to-mongo
uri: http://localhost:9064/
predicates:
- Path=/api/**
- Method=POST,PUT,DELETE
- Between=2020-01-15T23:59:59.000+08:00[Asia/Shanghai], 2100-12-31T23:59:59.000+08:00[Asia/Shanghai]
- id: http-others-route-to-es
uri: http://localhost:9037/
predicates:
- Path=/api/**
- Method=POST,PUT,DELETE
- Between=2020-01-15T23:59:59.000+08:00[Asia/Shanghai], 2100-12-31T23:59:59.000+08:00[Asia/Shanghai]

How to detect new REST calls dynamically as and when they are available?

I am creating an API gateway using Netflix Zuul and Netflix Eureka doing the part of service registration for service discovery for a microservices framework.
I am trying to support a use case where new micro-services may come up which expose REST calls, or existing micro-services may get upgraded to expose new REST calls with version as part of their URL etc. Eureka runs as a dedicated springboot application and Zuul runs as a dedicated application. The application.prop or application.yml file of Zuul is where i am putting config for zuul.routes for each micro-services
My zuul's application.yml looks something like this to support one microservice config.
zuul:
routes:
example:
path: /example/**
stripPrefix: false
serviceId: zuul-service
If i bring down zuul add another such snippet of config under zuul:routes:
and then bring up zuul again, i will start seeing the new endpoint. But i want that to happen dynamically. Like Eureka will dynamically detect any new micro-services that come up or go down. If zuul can get in sync with Eureka then all my rest endpoints can be exposed perfectly through my Zuul api gateway.
Any suggestions on what i may be missing or add any other open source third party to achieve this will be helpful.

Resources