Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Cloud Gateway : How to pass params to custom filter

I have a custom filter defined in my application.yml. I need to take some more parameters from that filter definition in YAML, so that I can perform a logic inside my custom filter. I have multiple such routes defined wherein the filter parameters differs. The problem I am facing is, not able to read the values specified in YAML file.

application.yml ---

spring:
  cloud:
    gateway:
      routes:
      - id: test_route
        uri: https://api.rangon.pi
        predicates:
        - Path=/api/staticdata/rattlefeed*
        filters:
        - AddRequestHeader=X-Y-Host, rangon
        - TestGatewayFilter=admin, XY8382, basic

//Is there any way to get "admin, XY8382, basic" in my custom filter class

My filter class

@Component
public class TestGatewayFilter implements 
   GatewayFilterFactory<TestGatewayFilter.Config> {

     @Override
     public GatewayFilter apply(Config config) {
         // grab configuration from Config object

         return (exchange, chain) -> {
             Route r = (Route) exchange.getAttributes().get(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);

             Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
            // ServerWebExchange route =
            // exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
            // List<GatewayFilter> list = r.getFilters();

            GatewayFilter gwf = r.getFilters().get(r.getFilters().size() - 1);

            Builder builder = exchange.getRequest().mutate();
            // use builder to manipulate the request

            return chain.filter(exchange.mutate().build());
        };
    }

    public Config newConfig() {

        Config c = new Config();
        return c;
    }

    public static class Config {
        // Put the configuration properties for your filter here

    }

} 
like image 319
Pluto Avatar asked Nov 25 '18 07:11

Pluto


1 Answers

There are two ways to define params for your filters in your configuration file, in this example I'm going to use an application.yml

First of all, you can use the args keyword to define a key-value list of arguments:

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: https://myapi.com
          filters:
            - name: TestLoggingFilter
              args:
                value: ThisIsATest

And the second form, you can use inline args:

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: https://myapi.com
          filters:
            - TestLoggingFilter=ThisIsATest

If you want to use inline args make sure to override the shortcutFieldOrder method in your filter with an array containing the name of the params you want to receive, this array is also used to define the order of the params.

The following is an example of a simple filter that works with any of the previous definitions, as this example override shortcutFieldOrder as well:

package com.es.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;

@Component
public class TestLoggingFilter implements GatewayFilterFactory<TestLoggingFilter.Config> {

    private static final Logger LOG = LoggerFactory.getLogger(TestLoggingFilter.class);

    private static final String VALUE = "value";

    @Override
    public Config newConfig() {
        return new Config();
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList(VALUE);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            LOG.info("Filter enabled with value: " + config.value);
            return chain.filter(exchange);
        };
    }

    public static class Config {

        private String value;

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }
}
like image 174
ELavicount Avatar answered Sep 26 '22 06:09

ELavicount