如何在 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));
}
}
我计划将一个项目从 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));
}
}