我打算将一个项目从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 Cloud gateway 有过滤器来修改请求正文和响应正文。
正如规范中提到的,为了使用这些过滤器,我们需要使用 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));
}
}
通过 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。应该可以做任何你期望的格式。