sequence

This paper mainly studies the GatewayFilter of Spring Cloud Gateway

GatewayFilter

Spring – the cloud – gateway – core – 2.0.0. RC2 – sources. The jar! /org/springframework/cloud/gateway/filter/GatewayFilter.java

/**
 * Contract for interception-style, chained processing of Web requests that may
 * be used to implement cross-cutting, application-agnostic requirements such
 * as security, timeouts, and others. Specific to a Gateway
 *
 * Copied from WebFilter
 *
 * @author Rossen Stoyanchev
 * @since 5.0
 */
public interface GatewayFilter extends ShortcutConfigurable {

	String NAME_KEY = "name";
	String VALUE_KEY = "value"; /** * Process the Web request and (optionally) delegate to the next * {@code WebFilter} through the given {@link GatewayFilterChain}. * @param exchange the current server exchange * @param chain provides a way to delegate to the next  filter * @return {@code Mono<Void>} to indicate when request processing is complete
	 */
	Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);

}
Copy the code

As noted in the notes, it is mainly used for non-functional requirements like sectioning, such as security, timeout control, and so on. Its direct implementation class for OrderedGatewayFilter, ModifyResponseGatewayFilter, GatewayFilterAdapter

OrderedGatewayFilter

Spring – the cloud – gateway – core – 2.0.0. RC2 – sources. The jar! /org/springframework/cloud/gateway/filter/OrderedGatewayFilter.java

public class OrderedGatewayFilter implements GatewayFilter, Ordered {

	private final GatewayFilter delegate;
	private final int order;

	public OrderedGatewayFilter(GatewayFilter delegate, int order) {
		this.delegate = delegate;
		this.order = order;
	}

	public GatewayFilter getDelegate() {
		return delegate;
	}

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		return this.delegate.filter(exchange, chain);
	}

	@Override
	public int getOrder() {
		return this.order;
	}

	@Override
	public String toString() {
		final StringBuilder sb = new StringBuilder("OrderedGatewayFilter{");
		sb.append("delegate=").append(delegate);
		sb.append(", order=").append(order);
		sb.append('} ');
		returnsb.toString(); }}Copy the code

The Order interface is implemented

ModifyResponseGatewayFilter

Spring – the cloud – gateway – core – 2.0.0. RC2 – sources. The jar! /org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java

	public class ModifyResponseGatewayFilter implements GatewayFilter, Ordered {
		private final Config config;

		public ModifyResponseGatewayFilter(Config config) {
			this.config = config;
		}

		@Override
		@SuppressWarnings("unchecked")
		public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
			ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {
				@Override
				public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {

					ResolvableType inElementType = ResolvableType.forClass(config.getInClass()); ResolvableType outElementType = ResolvableType.forClass(config.getOutClass()); MediaType contentType = exchange.getResponse().getHeaders().getContentType(); Optional<HttpMessageReader<? >> reader = getHttpMessageReader(codecConfigurer,inElementType, contentType); Optional<HttpMessageWriter<? >> writer = getHttpMessageWriter(codecConfigurer, outElementType, null);if(reader.isPresent() && writer.isPresent()) { ResponseAdapter responseAdapter = new ResponseAdapter(body, getDelegate().getHeaders()); Flux<? > modified = reader.get().read(inElementType, responseAdapter, config.getInHints())
								.cast(inElementType.resolve())
								.flatMap(originalBody -> Flux.just(config.rewriteFunction.apply(exchange, originalBody)))
								.cast(outElementType.resolve());

						return getDelegate().writeWith(
								writer.get().write((Publisher)modified, outElementType, null, getDelegate(),
										config.getOutHints())
						);

					}
					// TODO: error? log?

					return getDelegate().writeWith(body);
				}

				@Override
				public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
					returnwriteWith(Flux.from(body) .flatMapSequential(p -> p)); }};return chain.filter(exchange.mutate().response(responseDecorator).build());
		}

		@Override
		public int getOrder() {
			returnNettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1; }}Copy the code

It is used to modify response

GatewayFilterAdapter

Spring – the cloud – gateway – core – 2.0.0. RC2 – sources. The jar! /org/springframework/cloud/gateway/handler/FilteringWebHandler.java

	private static class GatewayFilterAdapter implements GatewayFilter {

		private final GlobalFilter delegate;

		public GatewayFilterAdapter(GlobalFilter delegate) {
			this.delegate = delegate;
		}

		@Override
		public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
			return this.delegate.filter(exchange, chain);
		}

		@Override
		public String toString() {
			final StringBuilder sb = new StringBuilder("GatewayFilterAdapter{");
			sb.append("delegate=").append(delegate);
			sb.append('} ');
			returnsb.toString(); }}Copy the code

The adapter that converts GlobalFilter to GatewayFilter

GatewayFilterFactory

Spring – the cloud – gateway – core – 2.0.0. RC2 – sources. The jar! /org/springframework/cloud/gateway/filter/factory/GatewayFilterFactory.java

@FunctionalInterface
public interface GatewayFilterFactory<C> extends ShortcutConfigurable, Configurable<C> {

	String NAME_KEY = "name";
	String VALUE_KEY = "value";

	// useful for javadsl
	default GatewayFilter apply(Consumer<C> consumer) {
		C config = newConfig();
		consumer.accept(config);
		return apply(config);
	}

	default Class<C> getConfigClass() {
		throw new UnsupportedOperationException("getConfigClass() not implemented");
	}

	@Override
	default C newConfig() {
		throw new UnsupportedOperationException("newConfig() not implemented");
	}

	GatewayFilter apply(C config);

	default String name() {
		//TODO: deal with proxys
		return NameUtils.normalizeFilterFactoryName(getClass());
	}

	@Deprecated
	default ServerHttpRequest.Builder mutate(ServerHttpRequest request) {
		returnrequest.mutate(); }}Copy the code

The Spring Cloud Gateway uses factory mode to generate the GatewayFilter. As you can see, the Apply method is defined to generate the GatewayFilter according to config. The GatewayFilterFactory has several abstract classes, AbstractGatewayFilterFactory, AbstractNameValueGatewayFilterFactory (inherited AbstractGatewayFilterFactory), AbstractChangeReq UestUriGatewayFilterFactory.

AbstractGatewayFilterFactory

Spring – the cloud – gateway – core – 2.0.0. RC2 – sources. The jar! /org/springframework/cloud/gateway/filter/factory/AbstractGatewayFilterFactory.java

public abstract class AbstractGatewayFilterFactory<C> extends AbstractConfigurable<C> implements GatewayFilterFactory<C>  { @SuppressWarnings("unchecked")
	public AbstractGatewayFilterFactory() {
		super((Class<C>) Object.class);
	}

	public AbstractGatewayFilterFactory(Class<C> configClass) {
		super(configClass);
	}

	public static class NameConfig {
		private String name;

		public String getName() {
			return name;
		}

		public void setName(String name) { this.name = name; }}}Copy the code

Its immediate implementation class is as follows:

  • HystrixGatewayFilterFactory
  • ModifyRequestBodyGatewayFilterFactory
  • ModifyResponseBodyGatewayFilterFactory
  • PrefixPathGatewayFilterFactory
  • PreserveHostHeaderGatewayFilterFactory
  • RedirectToGatewayFilterFactory
  • RemoveRequestHeaderGatewayFilterFactory
  • RemoveResponseHeaderGatewayFilterFactory
  • RequestRateLimiterGatewayFilterFactory
  • RetryGatewayFilterFactory
  • RewritePathGatewayFilterFactory
  • SaveSessionGatewayFilterFactory
  • SecureHeadersGatewayFilterFactory
  • SetPathGatewayFilterFactory
  • SetStatusGatewayFilterFactory
  • StripPrefixGatewayFilterFactory

AbstractNameValueGatewayFilterFactory

Spring – the cloud – gateway – core – 2.0.0. RC2 – sources. The jar! /org/springframework/cloud/gateway/filter/factory/AbstractNameValueGatewayFilterFactory.java

public abstract class AbstractNameValueGatewayFilterFactory extends AbstractGatewayFilterFactory<AbstractNameValueGatewayFilterFactory.NameValueConfig> {

	public AbstractNameValueGatewayFilterFactory() {
		super(NameValueConfig.class);
	}

	public List<String> shortcutFieldOrder() {
        return Arrays.asList(GatewayFilter.NAME_KEY, GatewayFilter.VALUE_KEY);
    }


	@Validated
	public static class NameValueConfig {
		@NotEmpty
		protected String name;
		@NotEmpty
		protected String value;

		public String getName() {
			return name;
		}

		public NameValueConfig setName(String name) {
			this.name = name;
			return this;
		}

		public String getValue() {
			return value;
		}

		public NameValueConfig setValue(String value) {
			this.value = value;
			return this;
		}

		@Override
		public String toString() {
			return new ToStringCreator(this)
					.append("name", name)
					.append("value", value) .toString(); }}}Copy the code

The generic limited to AbstractNameValueGatewayFilterFactory NameValueConfig, its implementation class is as follows:

  • AddRequestHeaderGatewayFilterFactory
  • AddRequestParameterGatewayFilterFactory
  • AddResponseHeaderGatewayFilterFactory
  • SetRequestHeaderGatewayFilterFactory
  • SetResponseHeaderGatewayFilterFactory

AbstractChangeRequestUriGatewayFilterFactory

Spring – the cloud – gateway – core – 2.0.0. RC2 – sources. The jar! /org/springframework/cloud/gateway/filter/factory/AbstractChangeRequestUriGatewayFilterFactory.java

/**
 * This filter changes the request uri by
 * {@link #determineRequestUri(ServerWebExchange, T)} logic.
 *
 * @author Toshiaki Maki
 */
public abstract class AbstractChangeRequestUriGatewayFilterFactory<T>
		extends AbstractGatewayFilterFactory<T> {
	private final int order;

	public AbstractChangeRequestUriGatewayFilterFactory(Class<T> clazz, int order) {
		super(clazz);
		this.order = order;
	}

	public AbstractChangeRequestUriGatewayFilterFactory(Class<T> clazz) {
		this(clazz, RouteToRequestUrlFilter.ROUTE_TO_URL_FILTER_ORDER + 1);
	}

	protected abstract Optional<URI> determineRequestUri(ServerWebExchange exchange,
			T config);

	public GatewayFilter apply(T config) {
		return new OrderedGatewayFilter((exchange, chain) -> {
			Optional<URI> uri = this.determineRequestUri(exchange, config);
			uri.ifPresent(u -> {
				Map<String, Object> attributes = exchange.getAttributes();
				attributes.put(GATEWAY_REQUEST_URL_ATTR, u);
			});
			returnchain.filter(exchange); }, this.order); }}Copy the code

Set the new URI via GATEWAY_REQUEST_URL_ATTR, which directly implements the class

  • RequestHeaderToRequestUriGatewayFilterFactory(The URI is set by the value of the header)

GatewayFilterFactory.apply

Spring – the cloud – gateway – core – 2.0.0. RC2 – sources. The jar! /org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java

	private List<GatewayFilter> loadGatewayFilters(String id, List<FilterDefinition> filterDefinitions) {
		List<GatewayFilter> filters = filterDefinitions.stream()
				.map(definition -> {
					GatewayFilterFactory factory = this.gatewayFilterFactories.get(definition.getName());
					if (factory == null) {
                        throw new IllegalArgumentException("Unable to find GatewayFilterFactory with name " + definition.getName());
					}
					Map<String, String> args = definition.getArgs();
					if (logger.isDebugEnabled()) {
						logger.debug("RouteDefinition " + id + " applying filter " + args + " to " + definition.getName());
					}

                    Map<String, Object> properties = factory.shortcutType().normalize(args, factory, this.parser, this.beanFactory);

                    Object configuration = factory.newConfig();

                    ConfigurationUtils.bind(configuration, properties,
                            factory.shortcutFieldPrefix(), definition.getName(), validator);

                    GatewayFilter gatewayFilter = factory.apply(configuration);
                    if(this.publisher ! = null) { this.publisher.publishEvent(new FilterArgsEvent(this, id, properties)); }return gatewayFilter;
				})
				.collect(Collectors.toList());

		ArrayList<GatewayFilter> ordered = new ArrayList<>(filters.size());
		for (int i = 0; i < filters.size(); i++) {
			GatewayFilter gatewayFilter = filters.get(i);
			if (gatewayFilter instanceof Ordered) {
				ordered.add(gatewayFilter);
			}
			else{ ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1)); }}return ordered;
	}
Copy the code

The GatewayFilter for each route is instantiated by factory

summary

The GatewayFilter of Spring Cloud Gateway is mainly produced by GatewayFilterFactory. GatewayFilterFactory has three abstract classes:

  • AbstractGatewayFilterFactory
    • HystrixGatewayFilterFactory
    • ModifyRequestBodyGatewayFilterFactory
    • ModifyResponseBodyGatewayFilterFactory
    • PrefixPathGatewayFilterFactory
    • PreserveHostHeaderGatewayFilterFactory
    • RedirectToGatewayFilterFactory
    • RemoveRequestHeaderGatewayFilterFactory
    • RemoveResponseHeaderGatewayFilterFactory
    • RequestRateLimiterGatewayFilterFactory
    • RetryGatewayFilterFactory
    • RewritePathGatewayFilterFactory
    • SaveSessionGatewayFilterFactory
    • SecureHeadersGatewayFilterFactory
    • SetPathGatewayFilterFactory
    • SetStatusGatewayFilterFactory
    • StripPrefixGatewayFilterFactory
  • AbstractNameValueGatewayFilterFactory (inherited AbstractGatewayFilterFactory)
    • AddRequestHeaderGatewayFilterFactory
    • AddRequestParameterGatewayFilterFactory
    • AddResponseHeaderGatewayFilterFactory
    • SetRequestHeaderGatewayFilterFactory
    • SetResponseHeaderGatewayFilterFactory
  • AbstractChangeRequestUriGatewayFilterFactory
    • RequestHeaderToRequestUriGatewayFilterFactory

doc

  • 112. GatewayFilter Factories
  • Talk about spring. Cloud. Gateway. The default – filters
  • Talk about the spring cloud SecureHeadersGatewayFilter gateway
  • Talk about spring Cloud Gateway’s ForwardedHeadersFilter
  • Talk about Spring Cloud Gateway’s XForward HeadersFilter
  • Talk about the spring cloud RemoveHopByHopHeadersFilter gateway