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

问题描述 投票:0回答:3

我打算将一个项目从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 gateway 的经验有限,请帮我找到 Spring Gateway 中的等效代码,

spring spring-boot spring-webflux project-reactor spring-cloud-gateway
3个回答
4
投票

Spring Cloud gateway 有过滤器来修改请求正文和响应正文。

修改ResponseBody
修改请求正文

正如规范中提到的,为了使用这些过滤器,我们需要使用 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));
        }
    }
}

1
投票

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

0
投票

通过 Spring-Cloud-Gateway v4 的最新添加,您可以利用 CacheRequestBody 更简单地访问请求正文,而不会阻塞操作。

在您的 application.yml 中

spring:
  cloud:
    gateway:
      routes:
        - id: my-id
          uri: https://my-host.com
          predicates:
            - Path=/path/**
          filters:
            - name: CacheRequestBody
              args:
                bodyClass: org.springframework.util.MultiValueMap

在您的过滤器或应用方法中,您现在可以使用以下方式访问您的身体:

MultiValueMap<String, String> formData = exchange.getAttribute(ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR);

对于我的情况,我期望收到 x-www-form-urlencoded,所以我的 bodyClass 和 form 是 MultiValueMap。应该可以做任何你期望的格式。

© www.soinside.com 2019 - 2024. All rights reserved.