Spring Cloud Gateway in CloudFoundry - spring-boot

I've been trying to get my apps to run after deploing them to a CloudFoundry instance. The instance I'm using will not allow to perform requests using http (they will simply timeout) so I have to route all requests to https.
The components/versions I am using are:
Java 10
Spring Boot 2.0.4.RELEASE/Spring Cloud Finchley.SR1
spring-cloud-gateway
spring-cloud-config-server
spring-cloud-starter-netflix-eureka
The failing config
EurekaClient Config (in gateway and the backend where the gw should route to)
eureka:
client:
serviceUrl:
defaultZone: ${DISCOVERY_SERVICE_URL:http://localhost:8061}/eureka/
instance:
hostname: ${vcap.application.uris[0]:localhost}
nonSecurePortEnabled: false
securePortEnabled: true
securePort: ${server.port}
statusPageUrl: https://${eureka.instance.hostname}/actuator/info
healthCheckUrl: https://${eureka.instance.hostname}/actuator/health
homePageUrl: https://${eureka.instance.hostname}/
secure-virtual-host-name: https://${vcap.application.application_uris[0]}
Gateway Config
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/user/**
filters:
- RewritePath=/user/(?<segment>.*), /$\{segment}
Things I have already tried:
Using lb:https://user-service like described in docs -> Will have no effect as far as I can see
Use real urls to the apps (uri: https://user-service.cf-instance.io) -> Routing works as expected.
But I do not want to define the urls in my config, they should returned by eureka and build up correctly by the gateway.
Thanks in advance
Edit:
Here is the output of /eureka/apps
https://pastebin.com/WP3b6PQG
I am currently working to get the current code into GitHub I will edit this post when I've found the time to get a clear state.
Edit 2:
You can find the full example (With SpringCloudGateway, Eureka, ...) at my GitHub
This is an running example, the applied config will not use the Eureka. To use Eureka the gateway-service-cloud.yml in config service has to be adopted.
- id: user-service
uri: lb://user-service
Please ignore the documentation service, this will not work yet, I first need to rewrite the path.

Ok, I found out the solution during fixing the "routing" problem with my documentation-service.
My problem was setting the property eureka.instance.securePort to ${server.port}. This property has to be set to 443 (the default 443 is not applied when nothing is set). When adding this to my configurations everything works as expected after pushing my application.

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 load balance request to list of URIs in Spring Cloud Gateway

I don't have eureka, load balancer and so on. I want to load balance the request to list of URIs on which instances of backend run.
spring:
cloud:
gateway:
routes:
- id: myService-endpoints
uri: myServiceIp1, myServiceIp2
predicates:
- Path=/myservice/**
myServiceIp1 and myServiceIp2 are my backend service IPs. How can I achieve load balancing in this scenario?
If you are not using service registry, you can still use load-balancing in your app. You will just need to use the SimpleDiscoveryClient that allows you to set your service instance URIs via a property file, like so:
spring.cloud.discovery.client.simple.instances.service1[0].uri=http://s11:8080
Then you can just follow the guides for setting up load-balanced routes in Gateway, like so:
spring:
cloud:
gateway:
routes:
- id: myRoute
uri: lb://service
predicates:
- Path=/service/**

Invalid redirect uri parameters for google oauth2 in spring boot microservice docker implementaion

I'm using spring stack (Spring Boot 2.0.0.RELEASE) for creating a site that delegues user authentication/registration to Google via OAuth2. It is implemented as a few Spring Cloud microservices with a Zuul gateway running on port 8080.
Google Auth Server
Zuul Gateway(:8080)
/ \
/ \
/ \
Other OAuth2 Client Microservice(:8000)
Microservices
I use Google as an OAuth2 server, and use spring-security-oauth2 as a client, which is implemented as a separate microservice. If all my cloud is deployed at localhost everything works fine. But if my microservices are deployed at different machines, e.g. Docker, OAuth2 login doesn't work. getting invalid redirect Uri parameter error.
Zuul configuration for Docker:
zuul:
ignoredServices: '*'
host:
connection-timeout-millis: 20000
socket-timeout-millis: 20000 routes:
authserver_oauth:
path: /oauth2/**
serviceId: authserver
stripPrefix: false
sensitiveHeaders:
Eureka Configuration for Docker:
eureka:
instance:
prefer-ip-address: false
client:
serviceUrl:
defaultZone: http://eureka-server:8761/eureka/
Authserver configuration:
spring:
security:
oauth2:
client:
registration:
google:
clientId: ***
clientSecret: ***
redirectUriTemplate: "{baseUrl}/oauth2/callback/{registrationId}"
scope:
- email
- profile
When I debug for Oauth2 condition I am getting unequal uri for request and response:
authorizationResponse.getRedirectUri()
(java.lang.String) http://authserver:8080/oauth2/callback/google
authorizationRequest.getRedirectUri()
(java.lang.String) http://localhost:8080/oauth2/callback/google
I had a similar issue with Spring boot 2.2.2RELEASE with a cloud environment (NGINX, Docker, Cubernettes) where customising NGINX configuration was not an option at all. Tried methods like setting the x-forwarded-for property, mocking the prod with docker, NGINX setup (https://juplo.de/how-to-redirect-to-spring-security-oauth2-behind-a-gateway-proxy-hiding-the-app-behind-a-reverse-proxy-gateway/) but nothing works. Finally I updated my Spring boot version to 2.4.1 and it worked without any other configuration.

Auto-configure routes with Zuul and Eureka

Through reading various books / tutorials, it appears that it is possible to auto-configure routes in Zuul when using it in combination with Eureka service discovery. That means that I don't have to explicitly add routes to Zuul's application.properties.
So I understand this correctly? Or do I still need to add routes explicitly to Zuul in order it to work as a gateway?
I would like it to automatically create routes from the application name's that are registered with Eureka. Is this possible?
(Note: I have actually tried this, but when I go to http://localhost:8762/routes I just get an error page.)
Sure. In most microservices implementations, internal microservices endpoints are not exposed outside. A set of public services will be exposed to the clients using an API gateway.
The zuul proxy internally uses the Eureka Server for service discovery.
I would like it to automatically create routes from the application name's that are registered with Eureka. Is this possible?
Sure. I will show you gateway example.
1. Create your service project (user-service)
create application.properties file
# --- Spring Config
spring:
application:
name: OVND-USER-SERVICE
# Eureka client
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URL:http://localhost:8761/eureka/}
2. Setting up Zuul project (Gateway-service)
1.#EnableZuulproxy to tell Spring Boot that this is a Zuul proxy
#SpringBootApplication
#EnableZuulProxy
#EnableDiscoveryClient
public class GatewayServiceApplication {
2.create an application.properties file
# =======================================
# Gateway-service Server Configuration
# =======================================
# --- Spring Config
spring:
application:
name: gateway-service
server:
port: ${PORT:8080}
# Eureka client
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URL:http://localhost:8761/eureka/}
zuul:
host:
routes:
## By default, all requests to user service for example will start with: "/user/"
## What will be sent to the user service is what comes after the path defined,
## So, if request is "/user/v1/user/tedkim", user service will get "/v1/user/tedkim".
user-service:
path: /user/**
service-id: OVND-USER-SERVICE
another-service:
path: /another/**
service-id: OVND-ANOTHER-SERVICE
Eureka website ( localhost:8761 )
Yes. You can integrate Zuul with Eureka and configure the routes based on application names registered in Eureka. Just add the following configuration to Zuul application:
zuul:
ignoredServices: "*"
routes:
a-service: /a-service/**
b-service: /b-service/**
c-service: /c-service/**
d-service: /d-service/**

Zuul Routing when using eureka services

I have a reasonably simple Spring Cloud Netflix setup. We are using Zuul as a reverse proxy and Eureka for service discovery and registry. we have legacy services we are slowly choking out. We have many simple services that have their endpoints configured like this:
{host}:{port}/{service-name}/**
so now when each service is registered with eureka, and subsequently has a route added to Zuul, the zuul endpoint looks like this:
{zuul-host}:{zuul-port}/{service-name}/{service-name}/**
I want to stop Zuul from striping the prefix off the routed URIs for eureka services so that my zuul endpoints look like this:
{zuul-host}:{zuul-port}/{service-name}/**
and forward to:
{zuul-host}:{zuul-port}/{service-name}/**
I would like this to be done in a way such that I do not have to add configs for each and every service.
I would have assumed that zuul.strip-prefix would have done the trick, but that doesn't appear to be the case.
current Zuul application.yml:
zuul:
routes:
oldservice:
path: /oldservice/**
url: http://oldservice-host:9080/api/v1/oldservice
strip-prefix: false
eureka:
client:
serviceUrl:
defaultZone: http://eureka-host:8761/eureka/
Anyone have a suggestion for how I can configure zuul in this way?
Since you are registering your service with eureka why not use the service-id for routing like below.
the service-id is the id that your service gets registered in Eureka with.
zuul:
routes:
path: /oldservice/**
service-id: oldservice
strip-prefix: false
eureka:
client:
serviceUrl:
defaultZone: http://eureka-host:8761/eureka/
For your current scenario I moved the strip-prefix inside the routes I have it like that in my system you can try that.
zuul:
routes:
oldservice:
path: /oldservice/**
url: http://oldservice-host:9080/api/v1/oldservice
strip-prefix: false
eureka:
client:
serviceUrl:
defaultZone: http://eureka-host:8761/eureka/

Resources