Spring Cloud Gateway 2.0 forward path variable
Asked Answered
P

3

7

How to forward a path variable in Spring Cloud Gateway 2.0?

If we have an microservice that has 2 endpoints: /users and /users/{id} and is running on port 8080, how to forward the request to the endpoint with the id path variable?

The following gateway configuration successfully forwards to the /users end point, but the second route forwards the request to the same /users endpoint of the real service.

@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("users", t -> t.path("/users").uri("http://localhost:8080/users"))
        .route("userById", t -> t.path("/users/**").uri("http://localhost:8080/users/"))
        .build();
}

I'm using spring-cloud-starter-gateway from spring cloud Finchley.BUILD-SNAPSHOT

Putout answered 5/2, 2018 at 21:48 Comment(0)
P
12

A rewritePath filter has to be used:

@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("users", t -> t.path("/users")
                .uri("http://localhost:8080/users"))
            .route("userById", t -> t.path("/users/**")
                .filters(rw -> rw.rewritePath("/users/(?<segment>.*)", "/users/${segment}"))
                .uri("http://localhost:8080/users/"))
        .build();
    }

The YAML version is specified in the documentation:

spring:
  cloud:
    gateway:
      routes:
      - id: rewritepath_route
        uri: http://example.org
        predicates:
        - Path=/foo/**
        filters:
        - RewritePath=/foo/(?<segment>.*), /$\{segment}
Putout answered 28/2, 2018 at 19:31 Comment(1)
I am not sure you're not actually invoking the service directly without running through the gateway, because your gateway path seems to be the same as your service path. Could you try to change the gateway path and see what happens.Nemertean
N
3

After some research, please find below what worked for me. Both methods produce the same result.

Here is my set-up:

  • the gateway is running on http://localhost:8090
  • a base path called /context serves as the entry point of the gateway
  • a service called my-resources running on http://localhost:8091/my-resources. When /my-resources is invoked without parameters, it returns all resources. When it is invoked with a parameters it returns the resource with the corresponding RID (if any)

The gateway is configured so that all path variables (possibly none) transmitted to http://localhost:8090/context/my-resources/ is forwarded to uri http://localhost:8091/my-resources/.

Method 1: using application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: route_id
        predicates:
        - Path=/context/my-resources/**
        filters:
        - RewritePath=/context/my-resources/(?<RID>.*), /my-resources/$\{RID}
        uri: http://localhost:8091

Method 2: using Java like configuration

@Bean
public RouteLocator routes(RouteLocatorBuilder routeBuilder) {
    return routeBuilder.routes()
            .route("route_id",
                    route -> route
                            .path("/context/my-resources/**")
                            .filters(f -> f.rewritePath("/context/my-resources/(?<RID>.*)", "/my-resources/${RID}"))
                            .uri("http://localhost:8091")
            )
            .build();
}
Nemertean answered 15/6, 2018 at 13:1 Comment(0)
A
0

Here's an example of how I was able to make it work using routes for multiple services. In this case, I used the "aplication.properties" file instead of a "yml" file.

spring.cloud.gateway.routes[0].id=service-sample
spring.cloud.gateway.routes[0].uri=lb://service-samp
spring.cloud.gateway.routes[0].predicates[0]=Path=/api/sample/**
spring.cloud.gateway.routes[0].filters[0]=RewritePath=/api/sample/(?<segment>.*), /api/sample/${segment}

spring.cloud.gateway.routes[1].id=service-test-new
spring.cloud.gateway.routes[1].uri=lb://service-test
spring.cloud.gateway.routes[1].predicates[0]=Path=/api/test/**
spring.cloud.gateway.routes[1].filters[0]=RewritePath=/api/test/(?<segment>.*), /api/test/${segment}
Anana answered 24/3, 2023 at 15:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.