如何在 Spring Cloud Gateway 和 addHeader 中获取请求体

How to get request body in Spring Cloud Gateway and addHeader

我计划将一个项目从 Zuul 迁移到 Spring Cloud Gateway。 我有一个“校验和代码”,但我不知道如何迁移它。

在 zuul 代码中我得到了 url 参数和 json 主体,然后我做了一些检查。

HttpServletRequest request = requestContext.getRequest();
Map<String, String[]> parameterMap = getURLParamter(request);
String json = getBody(request);

if(securityCheck(parameterMap, json) == true) {
    requestContext.addZuulRequestHeader("check-success-then-next-filter", "1");
} else {
    requestContext.setResponseBody("{ msg:: check error }");
}

我对 Spring 网关的经验有限,请帮我找到 Spring 网关中的等效代码,

Spring云网关有修改请求体和响应体的过滤器。

ModifyResponseBody
ModifyRequestBody

如规范中所述,要使用这些过滤器,我们需要使用 DSL 方法而不是 YAML 文件来配置路由。所以基本上你会有一个像下面这样的 RouteBuilder -


    @Bean
    public RouteLocator myRoutes(RouteLocatorBuilder builder) {
    
    RouteLocatorBuilder.Builder routeLocator = builder.routes().route(
    p -> {
      p.method("POST").path("/<path>").filters(f->{
         f.modifyRequestBody(String.class, String.class,
                                    (exchange, reqMessage) -> {
                                        try {
                                            log.info(">>> INCOMING REQUEST <<< - {}", reqMessage);
                                            //Get query params
    exchange.getRequest().getQueryParams();
    //In case of any validation errors, throw an exception so that it can be handled by a global exception handler
                                            return Mono.just(reqMessage);
                                        } catch (Exception e) {
                                            log.error("Exception while modifying request body", e);
                                            throw new RuntimeException(e.getMessage());
                                        }
                                    });
      })
    }
    );
    
    }

然后全局异常处理程序可以发回标准响应 -


    public class GlobalExceptionHandler extends AbstractErrorWebExceptionHandler {
       @Override
       protected RouterFunction<ServerResponse> getRoutingFunction (ErrorAttributes errorAttributes) {
       return RouterFunctions.route(RequestPredicates.all(),this::renderErrorResponse);
    }
    
    private Mono<ServerResponse> renderErrorResponse (ServletRequest request) {
      Map<String,Object> errorPropertiesMap = getErrorAttributes (request,ErrorAttributeOptions.defaults());
    String customErrMsg = errorPropertiesMap.get("message") != null ? errorPropertiesMap.get("message").toString() : null;
    
    if(customErrMsg != null) {
      return ServerResponse.status(HttpStatus.BAD_REQUEST).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(errorPropertiesMap.get("message")));
    } else {
    return ServerResponse.status(HttpStatus.BAD_REQUEST).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(errorPropertiesMap));
    }
    }
    }

可以使用 GlobalFilter 修改请求。

public class RequestTransaformationFilter implements GlobalFilter, Ordered {

  @Autowired 
  private ModifyRequestBodyGatewayFilterFactory modifyRequestBodyFilter;
  @Autowired 
  private RequestBodyRewrite requestBodyRewrite;

  @Override
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    return modifyRequestBodyFilter
        .apply(
            new ModifyRequestBodyGatewayFilterFactory.Config()
                .setRewriteFunction(String.class, String.class, requestBodyRewrite))
        .filter(exchange, chain);
  }

 
}

可以配置 RequestRewrite bean 来修改请求:

public class RequestBodyRewrite implements RewriteFunction<String, String> {

  @Override
  public Publisher<String> apply(ServerWebExchange exchange, String body) {
    Gson gson = new Gson();
   
      Map<String, Object> map = gson.fromJson(body, Map.class);
      map.put("NewField", "value");
      return Mono.just(gson.toJson(map, Map.class));
    
  }
}