skip to Main Content

I have a spring gateway in a microservice architecture.

When request reaches gateway it has to behave in below mentioned way

  1. creates a session and sets attributes.
  2. saves session in redis.
  3. Route the request to Microservice B
  4. Microservice B recieves the sessionId and fetches the
    attributes from session.

While trying to implement this, (2nd point) which is saving the sessionId is happening after the microservices B is called and returns its response (point 4). (i.e point 2 happens after point 4).

But, expected is sessionId to be saved in redis before the request is routed to application B.

Gateway Application

application.yml

server:
  port: 4000
spring:
  cloud:
    gateway:
      routes:
      - id: demo-app1
        uri: http://localhost:4001/demo-app1
        predicates:
        - Path=/demo-app1/**
        filters:
        - SaveSession
        - CustomSessionHandle
        - name: Retry
          args:
            retries: 2
            statuses: BAD_GATEWAY
            methods: GET,POST
            backoff:
              firstBackoff: 10ms
              maxBackoff: 50ms
              factor: 2
              basedOnPreviousValue: false

  session:
    store-type: redis             # Defines where the session is stored JVM or redis
    redis:
      flush-mode: immediate      #Tells spring to flush the session data immediately into redis
  redis:
    host: 127.0.0.1
    port: 6379

@Component
public class CustomRequestFilter implements GatewayFilter, Ordered {

    @Override
    public int getOrder() {
        return -1;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Map<String, Object> sessionMap = new HashMap<>();
        sessionMap.put("param", "Hi, I am the value from cloud gateway");    

        return exchange.getSession().doOnNext(webSession -> webSession.getAttributes().putAll(sessionMap))).then(chain.filter(
                exchange));
    }

   
}

@Component
public class CustomSessionHandle extends AbstractGatewayFilterFactory<Object> {

    @Override
    public GatewayFilter apply(Object config) {
        return new CustomRequestFilter();
    }

}

POM File –> using spring boot 2.3.9

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.zalando</groupId>
            <artifactId>logbook-spring-boot-starter</artifactId>
            <version>${logbook-spring-boot-starter}</version>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

2

Answers


  1. You can mention the order of filter using @order annotation

    Login or Signup to reply.
  2. try this: 
    
    @Component
    @Slf4j
    public class CustomWebFilter implements WebFilter, Ordered {
        @Value("${ss.apigateway.context.path}")
        private String contextPath;
    
        @Override
        public Mono<Void> filter(ServerWebExchange serverWebExchange,
                                 WebFilterChain webFilterChain) {
            String path = serverWebExchange.getRequest().getURI().getPath().
                    replace(contextPath, "");
    
            log.debug("Old Path: '{}', Modified Path: '{}'",
                    serverWebExchange.getRequest().getURI().getPath(), path);
    
            ServerHttpRequest updatedHttpRequest = serverWebExchange.getRequest().mutate().path(path).build();
            return webFilterChain.filter(serverWebExchange.mutate().request(updatedHttpRequest).build());
        }
    
        @Override
        public int getOrder() {
            return Ordered.HIGHEST_PRECEDENCE;
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search