【问题标题】:How to get request body in Spring Cloud Gateway and addHeader如何在 Spring Cloud Gateway 和 addHeader 中获取请求正文
【发布时间】:2022-01-14 05:30:45
【问题描述】:

我打算将一个项目从 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 Gateway 中的等效代码,

【问题讨论】:

    标签: spring spring-boot spring-webflux project-reactor spring-cloud-gateway


    【解决方案1】:

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

    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));
        }
        }
        }
    
    

    【讨论】:

    • 谢谢你,云你提供了完整的代码吗?我查看了这个文档,发现它非常抽象。我尝试使用 cacheRequestBody 来读取数据。貌似@Bean注入了Spring,但是返回结果怎么处理呢?
    【解决方案2】:

    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));
        
      }
    }
    

    【讨论】:

    • 全局过滤需要声明路由吗?
    猜你喜欢
    • 2018-12-18
    • 2021-10-14
    • 2020-01-14
    • 2020-04-30
    • 2022-10-14
    • 2021-02-02
    • 2020-03-10
    • 2019-03-31
    • 2017-08-14
    相关资源
    最近更新 更多