SpringCloud gateway request的body验证或修改
2019.11.05更新:后续版本新增了以下过滤器org.springframework.cloud.gateway.filter.headers.RemoveHopByHopHeadersFilter默认会把以下头部移除(暂不了解这做法的目的)- connection- keep-alive- te- transfer-encoding- trailer- prox...
·
2019.11.05更新:
后续版本新增了以下过滤器
org.springframework.cloud.gateway.filter.headers.RemoveHopByHopHeadersFilter
默认会把以下头部移除(暂不了解这做法的目的)
- connection
- keep-alive
- te
- transfer-encoding
- trailer
- proxy-authorization
- proxy-authenticate
- x-application-context
- upgrade
从而导致下面我们重写getHeaders方法时添加的transfer-encoding头部移除,导致无法解析body。
解决办法:
在yml文件中配置自定义的头部移除列表
spring:
cloud:
filter:
remove-hop-by-hop:
headers:
- connection
- keep-alive
- te
- trailer
- proxy-authorization
- proxy-authenticate
- x-application-context
- upgrade
源码可见链接,且可实现动态路由配置:https://github.com/SingleTigger/SpringCloudGateway-Nacos-Demo
--------------------------------------------原文----------------------------------------------------
往往业务中我们需要在网关对请求参数作修改操作(注意以下只针对带有body的请求),springcloud gateway中有提供一个
ModifyRequestBodyGatewayFilterFactory
的filter,看了一下它的实现,需要指定输入类型和输出类型,比较局限。
我就参考它自己实现了一个拦截器
注意:上传文件也带有请求body,需特殊处理。
以下是主要代码
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.support.BodyInserterContext;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
/**
* @author chenws
* @date 2019/12/12 09:33:53
*/
@Component
public class CModifyRequestBodyGatewayFilterFactory extends AbstractGatewayFilterFactory {
private final List<HttpMessageReader<?>> messageReaders;
public CModifyRequestBodyGatewayFilterFactory() {
this.messageReaders = HandlerStrategies.withDefaults().messageReaders();
}
@Override
@SuppressWarnings("unchecked")
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerRequest serverRequest = ServerRequest.create(exchange,
this.messageReaders);
Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
.flatMap(originalBody -> modifyBody()
.apply(exchange,Mono.just(originalBody)));
BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody,
String.class);
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getRequest().getHeaders());
headers.remove(HttpHeaders.CONTENT_LENGTH);
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange,
headers);
return bodyInserter.insert(outputMessage, new BodyInserterContext())
.then(Mono.defer(() -> {
ServerHttpRequest decorator = decorate(exchange, headers,
outputMessage);
return chain.filter(exchange.mutate().request(decorator).build());
}));
};
}
/**
* 修改body
* @return apply 返回Mono<String>,数据是修改后的body
*/
private BiFunction<ServerWebExchange,Mono<String>,Mono<String>> modifyBody(){
return (exchange,json)-> {
AtomicReference<String> result = new AtomicReference<>();
json.subscribe(
value -> {
//value 即为请求body,在此处修改
result.set(value);
System.out.println(result.get());
},
Throwable::printStackTrace
);
return Mono.just(result.get());
};
}
private ServerHttpRequestDecorator decorate(ServerWebExchange exchange, HttpHeaders headers,
CachedBodyOutputMessage outputMessage) {
return new ServerHttpRequestDecorator(exchange.getRequest()) {
@Override
public HttpHeaders getHeaders() {
long contentLength = headers.getContentLength();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(super.getHeaders());
if (contentLength > 0) {
httpHeaders.setContentLength(contentLength);
}
else {
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
}
return httpHeaders;
}
@Override
public Flux<DataBuffer> getBody() {
return outputMessage.getBody();
}
};
}
}
如需转载请标明出处:https://blog.csdn.net/shuoshuo132
更多推荐
已为社区贡献4条内容
所有评论(0)