如何在Swagger中适配Zuul路由与过滤器,修正文档路径偏差问题?
解决Zuul路由导致Swagger文档base-path不匹配的问题
当然可以通过Zuul过滤器来修正这个问题,让Swagger文档的base-path和实际路由完全一致,我之前帮不少开发者处理过类似场景,下面给你两种可行的方案:
一、手动编写Zuul Pre过滤器修正Swagger文档
我们可以编写一个Zuul的PreFilter,在请求到达Swagger文档接口时,动态修改返回的Swagger JSON中的basePath字段,让它和Zuul实际路由后的路径匹配。
过滤器代码示例
@Component public class SwaggerBasePathFilter extends ZuulFilter { private static final String SWAGGER_DOC_PATH = "/v2/api-docs"; private static final String X_FORWARDED_PREFIX = "X-Forwarded-Prefix"; @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 1; } @Override public boolean shouldFilter() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); // 只处理Swagger文档请求 return SWAGGER_DOC_PATH.equals(request.getRequestURI()); } @Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); // 获取Zuul路由后的实际前缀(可以从请求头或Zuul的路由信息中获取) String actualBasePath = request.getHeader(X_FORWARDED_PREFIX); if (actualBasePath == null) { // 如果没有转发头,也可以从Zuul的路由匹配结果中获取 Route route = ctx.getRoute(); if (route != null) { actualBasePath = route.getPrefix(); } } if (actualBasePath != null) { // 拦截响应,修改Swagger的basePath ctx.addZuulResponseHeader("Content-Type", "application/json"); ctx.setResponseBodyFilteringEnabled(true); ctx.getResponse().setCharacterEncoding("UTF-8"); // 通过ResponseBodyWrapper来修改返回的JSON内容 ctx.setResponseWrapper(new SwaggerBasePathResponseWrapper(ctx.getResponse(), actualBasePath)); } return null; } // 自定义响应包装类,修改Swagger JSON的basePath private static class SwaggerBasePathResponseWrapper extends HttpServletResponseWrapper { private final String actualBasePath; private ByteArrayOutputStream byteArrayOutputStream; private PrintWriter printWriter; public SwaggerBasePathResponseWrapper(HttpServletResponse response, String actualBasePath) { super(response); this.actualBasePath = actualBasePath; this.byteArrayOutputStream = new ByteArrayOutputStream(); this.printWriter = new PrintWriter(byteArrayOutputStream); } @Override public PrintWriter getWriter() throws IOException { return printWriter; } @Override public ServletOutputStream getOutputStream() throws IOException { return new ServletOutputStream() { @Override public void write(int b) throws IOException { byteArrayOutputStream.write(b); } @Override public boolean isReady() { return true; } @Override public void setWriteListener(WriteListener writeListener) {} }; } @Override public void flushBuffer() throws IOException { printWriter.flush(); // 读取原始响应内容,替换basePath String swaggerJson = byteArrayOutputStream.toString("UTF-8"); swaggerJson = swaggerJson.replace("\"basePath\":\"/api\"", "\"basePath\":\"" + actualBasePath + "\""); // 写入修改后的内容到响应 getResponse().getOutputStream().write(swaggerJson.getBytes("UTF-8")); byteArrayOutputStream.reset(); } } }
代码说明
- 这个过滤器只会拦截Swagger的文档请求(
/v2/api-docs),避免影响其他接口。 - 通过
X-Forwarded-Prefix请求头或者Zuul的路由信息获取实际的路由前缀,然后动态替换Swagger JSON中的basePath字段。 - 自定义的
HttpServletResponseWrapper用来修改响应内容,确保返回的Swagger文档使用正确的base-path。
二、调整Swagger Docket配置配合过滤器
结合你当前的Docket配置,我们可以让Swagger动态获取Zuul的路由前缀,而不是固定写死/api:
@Bean public Docket swaggerSpringfoxDocket(HttpServletRequest request) { this.log.debug("Starting Swagger"); StopWatch watch = new StopWatch(); watch.start(); // 从请求头或Zuul上下文获取实际basePath String basePath = request.getHeader("X-Forwarded-Prefix"); if (basePath == null) { basePath = "/api"; // 默认值 } Docket docket = new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .forCodeGeneration(false) .select() .paths(regex(basePath + "/.*")) // 动态匹配路径 .build() .pathMapping(basePath); // 设置正确的basePath watch.stop(); this.log.debug("Started Swagger in {} ms", watch.getTotalTimeMillis()); return docket; }
说明
- 这里通过
HttpServletRequest获取Zuul转发的前缀,动态设置Docket的pathMapping和路径匹配规则,让Swagger生成的文档一开始就使用正确的base-path。 - 配合上面的Zuul过滤器,可以双重保障Swagger文档的路径准确性。
额外提示
- 如果你的Zuul是动态增减路由的,建议开启Zuul的路由刷新功能,确保过滤器能实时获取最新的路由信息。
- 测试的时候可以直接访问Swagger UI,检查每个接口的请求路径是否和实际路由一致,比如点击“Try it out”按钮,看请求的URL是否正确。
内容的提问来源于stack exchange,提问作者riddy
相关产品推荐
相关产品推荐

