SpringCloudGateway修改requestBody导致form-data不支持问题解决

0.修改requestBody旧方法

0.1 使用 ModifyRequestBodyGatewayFilterFactory

@Slf4j
@Component
public class GlobalFilterImpl implements GlobalFilter, Ordered {

    @Autowired
    GatewayComponent gatewayComponent;

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

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String traceId = MDC.get("traceId");
        exchange.getResponse().getHeaders().add("traceId", traceId);
        ModifyRequestBodyGatewayFilterFactory.Config cf = new ModifyRequestBodyGatewayFilterFactory.Config();
        cf.setRewriteFunction(Object.class, Object.class, gatewayComponent.getRewriteFunction());
        GatewayFilter customerFilter = new ModifyRequestBodyGatewayFilterFactory().apply(cf);
        return customerFilter.filter(exchange, chain);
   
    }

}

0.2 GatewayComponent 鉴权业务

@Slf4j
@Component
public class GatewayComponent {

  public RewriteFunction<Object, Object> getRewriteFunction() {
    return (serverWebExchange, body) -> {
      ServerHttpRequest request = serverWebExchange.getRequest();
		//鉴权逻辑
      LinkedHashMap bodyMap = (LinkedHashMap) body;
      RestContext restContext = new RestContext();
      restContext.setTokenUuid(tokenUuid);
      restContext.setUserId(userId);
      restContext.setProjectId(projectId);
      restContext.setCorpId(corpId);
      restContext.setUserType(userType);
      bodyMap.put("restContext", restContext);
      return Mono.just(bodyMap);
    };
  }

}

以上 存在contentType为multipart/form-data时会报错不支持。

1. 优化后的实现

1.1 全局过滤器 不变

@Slf4j
@Component
public class GlobalFilterImpl implements GlobalFilter, Ordered {

    @Autowired
    GatewayComponent gatewayComponent;

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

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String traceId = MDC.get("traceId");
        exchange.getResponse().getHeaders().add("traceId", traceId);
        return chain.filter(exchange);
    }

}

1.2 新增鉴权过滤器

@Slf4j
@Component
public class TokenFilter implements GlobalFilter, Ordered {

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

  @Override
  public Mono<Void> filter(
    ServerWebExchange exchange,
    GatewayFilterChain chain
  ) {
    ServerHttpRequest request = exchange.getRequest();
    MediaType mediaType = exchange.getRequest().getHeaders().getContentType();
    if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)) {
      ServerRequest serverRequest = ServerRequest.create(
        exchange,
        HandlerStrategies.withDefaults().messageReaders()
      );
      Mono<LinkedHashMap> modifiedBody = serverRequest
        .bodyToMono(LinkedHashMap.class)
        .flatMap(
          body -> {
            RestContext restContext = new RestContext();
            restContext.setTokenUuid(tokenUuid);
            restContext.setUserId(userId);
            restContext.setProjectId(projectId);
            restContext.setCorpId(corpId);
            restContext.setUserType(userType);
            body.put("restContext", restContext);
            return Mono.just(body);
          }
        );

      BodyInserter bodyInserter = BodyInserters.fromPublisher(
        modifiedBody,
        LinkedHashMap.class
      );
      HttpHeaders headers = new HttpHeaders();
      headers.putAll(exchange.getRequest().getHeaders());
      headers.remove(HttpHeaders.CONTENT_LENGTH);
      CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(
        exchange,
        headers
      );
      return bodyInserter
        .insert(outputMessage, new BodyInserterContext())
        .then(
          Mono.defer(
            () -> {
              ServerHttpRequest decorator = decorate(
                exchange,
                headers,
                outputMessage
              );
              return chain.filter(exchange.mutate().request(decorator).build());
            }
          )
        );
    }
    return chain.filter(exchange);
  }

  ServerHttpRequestDecorator decorate(
    ServerWebExchange exchange,
    HttpHeaders headers,
    CachedBodyOutputMessage outputMessage
  ) {
    return new ServerHttpRequestDecorator(exchange.getRequest()) {
      @Override
      public HttpHeaders getHeaders() {
        long contentLength = headers.getContentLength();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.putAll(super.getHeaders());
        if (contentLength > 0) {
          httpHeaders.setContentLength(contentLength);
        } else {
          httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
        }
        return httpHeaders;
      }

      @Override
      public Flux<DataBuffer> getBody() {
        return outputMessage.getBody();
      }
    };
  }
}

上一篇:SpringCloud升级之路2020.0.x版-10.使用Log4j2以及一些核心配置


下一篇:Python学习-35.Python中的List Comprehensions(列表解释|列表生成式)