Talk about the PrefixPath and StripPrefix functions of spring cloud gateway.

  springcloud

Order

This article mainly studies the PrefixPath and StripPrefix functions of spring cloud gateway.

PrefixPathGatewayFilterFactory

spring-cloud-gateway-core-2.0.0.RC2-sources.jar! /org/springframework/cloud/gateway/filter/factory/PrefixPathGatewayFilterFactory.java

public class PrefixPathGatewayFilterFactory extends AbstractGatewayFilterFactory<PrefixPathGatewayFilterFactory.Config> {

    private static final Log log = LogFactory.getLog(PrefixPathGatewayFilterFactory.class);

    public static final String PREFIX_KEY = "prefix";

    public PrefixPathGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(PREFIX_KEY);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {

            boolean alreadyPrefixed = exchange.getAttributeOrDefault(GATEWAY_ALREADY_PREFIXED_ATTR, false);
            if (alreadyPrefixed) {
                return chain.filter(exchange);
            }
            exchange.getAttributes().put(GATEWAY_ALREADY_PREFIXED_ATTR, true);

            ServerHttpRequest req = exchange.getRequest();
            addOriginalRequestUrl(exchange, req.getURI());
            String newPath = config.prefix + req.getURI().getRawPath();

            ServerHttpRequest request = req.mutate()
                    .path(newPath)
                    .build();

            exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI());

            if (log.isTraceEnabled()) {
                log.trace("Prefixed URI with: "+config.prefix+" -> "+request.getURI());
            }

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

    public static class Config {
        private String prefix;

        public String getPrefix() {
            return prefix;
        }

        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }
    }
}

You can see here that the prefix of config is used to construct the newPath, and then the new ServerHttpRequest is constructed.

Example

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: http://example.org
        filters:
        - PrefixPath=/mypath

For example: request /hello, the path finally forwarded to the target service becomes /mypath/hello

StripPrefixGatewayFilterFactory

spring-cloud-gateway-core-2.0.0.RC2-sources.jar! /org/springframework/cloud/gateway/filter/factory/StripPrefixGatewayFilterFactory.java

/**
 * This filter removes the first part of the path, known as the prefix, from the request
 * before sending it downstream
 * @author Ryan Baxter
 */
public class StripPrefixGatewayFilterFactory extends AbstractGatewayFilterFactory<StripPrefixGatewayFilterFactory.Config> {

    public static final String PARTS_KEY = "parts";

    public StripPrefixGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(PARTS_KEY);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) ->  {
            ServerHttpRequest request = exchange.getRequest();
            addOriginalRequestUrl(exchange, request.getURI());
            String path = request.getURI().getRawPath();
            String newPath = "/" + Arrays.stream(StringUtils.tokenizeToStringArray(path, "/"))
                    .skip(config.parts).collect(Collectors.joining("/"));
            ServerHttpRequest newRequest = request.mutate()
                    .path(newPath)
                    .build();

            exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newRequest.getURI());

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

    public static class Config {
        private int parts;

        public int getParts() {
            return parts;
        }

        public void setParts(int parts) {
            this.parts = parts;
        }
    }
}

You can see that parts here specify the number of prefixes to remove, then use skip of stream to remove the corresponding prefixes, and then get newPath to construct newRequest

Example

spring:
  cloud:
    gateway:
      routes:
      - id: nameRoot
        uri: http://nameservice
        predicates:
        - Path=/name/**
        filters:
        - StripPrefix=2

For example, for request /name/bar/foo, after removing the first two prefixes, the final route to the target service is /foo

Summary

PrefixPathGatewayFilterFactory and StripprefixGatewayFilterFactory are a pair of filter factories that process request url prefixes. The former adds prefix and the latter removes prefix.

doc