Spring Cloud Gateway -- 修改RequestBody和Header
Spring Cloud Gateway -- 修改RequestBody和Head前言读取和修改RequestBody修改Head添加路由前言目前项目有个需求,前端POST请求需要以xml形式传输,后端接口有些返回的是JSON格式有些返回的XML格式并且由于网络架构的需求,需要一个中间平台来处理这些请求。最终觉得利用Spring Cloud Gateway来实现。前端统POST请求统一用AJ..
·
Spring Cloud Gateway -- 修改RequestBody和Header
前言
目前项目有个需求,前端POST请求需要以xml形式传输,后端接口有些返回的是JSON格式有些返回的XML格式并且由于网络架构的需求,需要一个中间平台来处理这些请求。最终觉得利用Spring Cloud Gateway来实现。前端统POST请求统一用AJAX发送请求,中间平台将POST转换成XML形式,并且对相应的如果是xml形式的数据转成成JSON的格式进行返回。
读取和修改RequestBody
读取RequestBody的方法。
本人的一点猜测:这个方法可能是有缺陷的,因为在读取ResponseBody的时候由于后台的返回的数据量很大,好像是分了好几次发送,需要将其拼装在一起之后在做处理(后面的博客会讲到的)。故而猜测这里应该是同样的道理,不过由于请求参数不会很多,所有先不管后面有时间在进行测试。(后面确实发现有问题 —解决办法)
/**
* 获取请求体中的字符串内容
* @param serverHttpRequest
* @return
*/
private 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 sb.toString();
}
对请求的方式进行判断,之后将数据转换成XML形式,并且需要重新传递。
重点
- 无论你修改了什么东西,都是需要new ServerHttpRequestDecorator 这个对象,并且调用你相对应的方法,例如我这边改了body就需要重写getBody这个方法。大家可以具体看看这个ServerHttpRequestDecorator的提供的方法就行了。
- 修改了Body 还需要修改CONTENT_LENGTH(下面会说的)
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest oldRequest= exchange.getRequest();
URI uri = oldRequest.getURI();
if("POST".equalsIgnoreCase(oldRequest.getMethodValue())) {
Object requestBody = resolveBodyFromRequest(oldRequest);
String xml = "";
if(requestBody != null){
xml = resolveBodyToXML(requestBody.toString());
}
//把request重新包装,继续传递
ServerHttpRequest newRequest = null;
try {
byte[] bytes = URLEncoder.encode(xml, "UTF-8").replaceAll("\\+", "%20").getBytes(StandardCharsets.UTF_8);
DataBuffer bodyDataBuffer = stringBuffer(new String(bytes));
Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);
newRequest = oldRequest.mutate().uri(uri).build();
newRequest = new ServerHttpRequestDecorator(newRequest) {
@Override
public Flux<DataBuffer> getBody() {
return bodyFlux;
}
};
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return chain.filter(exchange.mutate().request(newRequest).build());
}else{
return chain.filter(exchange);
}
}
修改Header
和修改Body同理。修改CONTENT_TYPE和CONTENT_LENGTH
我是把同一个代码拆开了,为了看的清楚一些。大家把他们拼起来就好了
// 定义新的消息头
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getRequest().getHeaders());
// 由于修改了传递参数,需要重新设置CONTENT_LENGTH,长度是字节长度,不是字符串长度
int length = bytes.length;
headers.remove(HttpHeaders.CONTENT_LENGTH);
headers.setContentLength(length);
headers.set(HttpHeaders.CONTENT_TYPE, "text/xml");
newRequest = new ServerHttpRequestDecorator(newRequest) {
@Override
public HttpHeaders getHeaders() {
return headers;
}
};
添加路由
这个就比较平常了
@EnableAutoConfiguration
@Configuration
public class ApiLocator {
@Autowired
private RequestFilter requestFilter;
@Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder) {
List list = new ArrayList();
list.add(requestFilter);
RouteLocatorBuilder.Builder routes = builder.routes();
RouteLocatorBuilder.Builder serviceProvider = routes
.route("route3",
r -> r.path(SERVICE)
.filters(f -> {
f.filters(list);
return f;
}).uri(URI));
RouteLocator routeLocator = serviceProvider.build();
return routeLocator;
}
}
更多推荐
已为社区贡献5条内容
所有评论(0)