swagger2和openapi3(后面坚持v2/v3) 返回报文有部分差异,具体可以看报文,knife4j前端目前看支持v3有点问题,因为v3没有basePath这个字段了,而knife4j 去读取的basePath,因此调试时候,会出现没有basePath的问题,导致404.
因为不会前端,我目前解决方式修改后端返回的报文,在v3的json返回内容上,加入basePath字段。
目前我的做法是在 gateway加了一个过滤器,将/v3/api-docs的请求返回的报文进行拦截,通过修改response的内容 在v3的返回json上加上basePath属性,来解决这个问题。
/**
* @author Duan Ran
* @date 2022/2/25
*/
@Slf4j
@Component
public class SwaggerGlobalFilter implements GlobalFilter,Ordered {
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path=exchange.getRequest().getPath().toString();
if (!path.endsWith("/v3/api-docs")){
return chain.filter(exchange);
}
String[] pathArray=path.split("/");
System.out.println(pathArray);
String basePath=pathArray[1];
ServerHttpResponse originalResponse = exchange.getResponse();
// 定义新的消息头
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getResponse().getHeaders());
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = Flux.from(body);
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
List<String> list = new ArrayList<String>();
dataBuffers.forEach(dataBuffer -> {
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
DataBufferUtils.release(dataBuffer);
try {
list.add(new String(content, "utf-8"));
} catch (IOException e) {
e.printStackTrace();
}
});
String s = listToString(list);
int length = s.getBytes().length;
headers.setContentLength(length);
JSONObject jsonObject=JSONUtil.parseObj(s);
// jsonObject.set("host","localhost:6400");
jsonObject.set("basePath",basePath);
s=jsonObject.toString();
return bufferFactory().wrap(s.getBytes());
}));
}
return super.writeWith(body);
};
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(super.getHeaders());
//由于修改了请求体的body,导致content-length长度不确定,因此使用分块编码
httpHeaders.remove(HttpHeaders.CONTENT_LENGTH);
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
return httpHeaders;
}
private String listToString(List<String> list){
StringBuilder stringBuilder=new StringBuilder();
for (String s:list){
stringBuilder.append(s);
}
return stringBuilder.toString();
}
};
// replace response with decorator
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
@Override
public int getOrder() {
return -2;
}
}
filter的order 需要-2,-1 是nettywriteresponse。