@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		if (CollectionUtils.isEmpty(trafficStainers)) {
			return chain.filter(exchange);
		}

		// 1. get stained labels from request
		Map<String, String> stainedLabels = getStainedLabels(exchange);

		if (CollectionUtils.isEmpty(stainedLabels)) {
			return chain.filter(exchange);
		}

		// 2. put stained labels to metadata context
		ServerHttpRequest request = exchange.getRequest().mutate().headers((httpHeaders) -> {
			MetadataContext metadataContext = exchange.getAttribute(MetadataConstant.HeaderName.METADATA_CONTEXT);
			if (metadataContext == null) {
				metadataContext = MetadataContextHolder.get();
			}

			Map<String, String> oldTransitiveMetadata = metadataContext.getTransitiveMetadata();

			// append new transitive metadata
			Map<String, String> newTransitiveMetadata = new HashMap<>(oldTransitiveMetadata);
			newTransitiveMetadata.putAll(stainedLabels);

			metadataContext.setTransitiveMetadata(newTransitiveMetadata);
		}).build();

		return chain.filter(exchange.mutate().request(request).build());
	}
@Test
	public void testNoneTrafficStainingImplement() {
		TrafficStainingGatewayFilter filter = new TrafficStainingGatewayFilter(null);

		when(chain.filter(exchange)).thenReturn(Mono.empty());

		filter.filter(exchange, chain);

		verify(chain).filter(exchange);
	}