SpringCloud-Gateway对multipart/form-data等其他POST请求类型的body体进行多次打开
本次代码仅在以下版本中测试通过<dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId>
·
本次代码仅在以下版本中测试通过
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> <version>2.1.4.RELEASE</version> </dependency>
这几天在用gateway进行鉴权校验的时候遇到很多坑,以前使用的都是x-www-form-urlencoded这种格式的Body,很容易就可以用gateway打开进行操作,但这次因为涉及到图片上传,所以请求格式变了,打开的过程变得非常曲折。
先是找到了下面这种办法,确实可以打开并获取body里的内容,而且还是非常规则的类型,不需要二次提取,formData即是我们想要的内容,后来在路由之后的controller中发现body里没有数据了,原来gateway只能打开一次。
MediaType mediaType = exchange.getRequest().getHeaders().getContentType();
if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(mediaType)) {
return exchange.getMultipartData().flatMap(formData->{
exchange.getAttributes().put(GateWayFilterDict.FORM_DATA_ATTR,formData);
return chain.filter(exchange.mutate().build());
});
}
后来换成了这个样子,先使用GlobalFilter对body内容进行缓存,之后便可以在方法里进行调用
@Component
public class CacheBodyGlobalFilter implements Ordered, GlobalFilter {
public static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (exchange.getRequest().getHeaders().getContentType() == null) {
return chain.filter(exchange);
} else {
return DataBufferUtils.join(exchange.getRequest().getBody())
.flatMap(dataBuffer -> {
DataBufferUtils.retain(dataBuffer);
Flux<DataBuffer> cachedFlux = Flux
.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
};
exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, cachedFlux);
return chain.filter(exchange.mutate().request(mutatedRequest).build());
});
}
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
public class VerificationFilter implements GatewayFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String bodyContent = resolveBodyFromRequest(exchange.getRequest());
return chain.filter(exchange);
}
public static String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest){
//获取请求体
Flux<DataBuffer> body = serverHttpRequest.getBody();
StringBuilder sb = new StringBuilder();
body.subscribe(buffer -> {
byte[] bytes = new byte[buffer.readableByteCount()];
buffer.read(bytes);
// DataBufferUtils.release(buffer);
String bodyString = new String(bytes, StandardCharsets.UTF_8);
sb.append(bodyString);
});
return formatStr(sb.toString());
}
/**
* 去掉空格,换行和制表符
* @param str
* @return
*/
private static String formatStr(String str){
if (str != null && str.length() > 0) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(str);
return m.replaceAll("");
}
return str;
}
@Override
public int getOrder() {
return 1;
}
}
这里是提取出来的内容,需要根据规则进行二次加工,但不复杂
----------------------------582918735041218588371746Content-Disposition:form-data;name="appKey"4324----------------------------582918735041218588371746Content-Disposition:form-data;name="appSecret"43244----------------------------582918735041218588371746--
更多推荐
已为社区贡献1条内容
所有评论(0)