Praveen Dass
Praveen Dass

Reputation: 616

Spring cloud gateway deployed in GCP App engine flexible causes infinite redirect loop

I have a two services running in GCP app engine; let's say service A and B, and then I deployed a spring cloud gateway service to route external traffic to these two services based on path predicates. service A and B are deployed in app engine flexible. initially I had the gateway deployed in app engine flexible and it was working perfectly well. because we have some batch services which has response time of more than 10 mins (app engine standard has max-response-timeout of 10 mins), we had to decide to migrate the gateway to app engine flexible.

The gateway service is dockerized and runs in the port 8080. My app.yaml looks like this:

runtime: custom
env: flex

service: beta-gateway

env_variables:
  SPRING_PROFILES_ACTIVE: "beta"

resources:
  cpu: 1
  memory_gb: 2

liveness_check:
  path: "/actuator/health"
  check_interval_sec: 30
  timeout_sec: 4
  failure_threshold: 2
  success_threshold: 2
  initial_delay_sec: 300

readiness_check:
  path: "/actuator/health"
  check_interval_sec: 5
  timeout_sec: 4
  failure_threshold: 2
  success_threshold: 2
  app_start_timeout_sec: 300

The service gets deployed correctly, the actuator endpoints works perfectly, I call /actuator/gateway/routes end point and the routing config looks good (And I route it to the services A and B using the appshot dns uri; Not the best approach should use a service registry in future).

The Problem: The problem is that for any endpoint other that the actuator endpoint, the request goes in to a redirect(302) loop and eventually fails.

What I tried:

As mentioned above, I invoked the /actuator/gateway/routes end point and the routing config looks good. I enabled TRACE logging for gateway and I see that the routing is getting matched correctly to service A or B's appspot dns url.

I am not very sure if it is relevant, but I initially did a deployment with network setting specifying port binding

network:
  name: default
  forwarded_ports:
    - 80:8080

I then learned that the binding to 8080 is done be default and removed it.

Any advice will be highly appreciated. Thank you!

Upvotes: 0

Views: 725

Answers (1)

Praveen Dass
Praveen Dass

Reputation: 616

The issue was caused because even though the traffic from browser to the GCP app engine's load balancer is secured (HTTP), the traffic from the load balancer to the instances are http as they are internal traffic.

From this point, the gateway forwards the request to the downstream api with X-Forwarded-Proto as HTTP (rather than HTTPS), then dowsteam API, as it rightly should sends a redirect request (302) asking the client to visit the end point with a secured connection (HTTPS). On receiving the 302 status, the client/browser again sends the request and SSL termination happens at the load balancer and the loop goes on.

The fix was to:

  • Set the server.forward-headers-strategy property to NATIVE, to enable the tomcat server to handle the forward headers.

  • Set server.tomcat.redirect-context-root is set to false, to make tomcat server honour the X-Forwarded-* headers before redirecting.

Came across the below mentioned reads which explains this.

Upvotes: 0

Related Questions