是否可以在与主应用程序不同的端口上 运行 SpringFox' swagger 和 swagger-ui?

Is it possible to run SpringFox' swagger and swagger-ui on a different port than the main application?

我们使用 SpringBoot 和 SpringFox 使用 @EnableSwagger2 公开 swagger-ui.html API 文档(我们不需要它来自动化客户端代码,就像文档和测试 ui).

是否可以 运行 在与主应用程序不同的端口(例如 spring 启动 management/monitoring 端口)下与所有 swagger 相关的端点?

我研究了一下,但没有找到 swagger's/springfox' 配置的方法。有 spring 的方法吗?

我不这么认为。当您设置 Spring 引导管理端口 (management.server.port) 时,第二个应用程序服务器开始为执行器提供服务。据我所知,不可能(除了自定义执行器端点)在该服务器上发布内容。
您的用例到底是什么?您要阻止在生产环境中或未经身份验证的用户访问 Swagger 吗?

是的,有一种 Spring 方法可以做到这一点:

第 1 步。添加额外的 Tomcat 连接器

要向嵌入式服务器添加端口,需要配置额外的连接器。 我们将通过提供自定义 WebServerFactoryCustomizer 来实现:

@Component
public class TomcatContainerCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    @Value("${swagger.port}")
    private int swaggerPort;

    @Override
    public void customize(TomcatServletWebServerFactory factory) {

        Connector swaggerConnector = new Connector();
        swaggerConnector.setPort(swaggerPort);
        factory.addAdditionalTomcatConnectors(swaggerConnector);
    }
}

现在 Tomcat 在两个端口上侦听,但它在这两个端口上提供相同的内容。我们需要对其进行过滤。

步骤 2. 添加过滤器

使用 FilterRegistrationBean 添加 servlet 过滤器非常简单。 它可以在任何地方创建,我直接将它添加到 TomcatContainerCustomizer.

@Component
public class TomcatContainerCustomizer  implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    @Value("${swagger.port}")
    private int swaggerPort;

    @Value("${swagger.paths}")
    private List<String> swaggerPaths;

    @Override
    public void customize(TomcatServletWebServerFactory factory) {

        Connector swaggerConnector = new Connector();
        swaggerConnector.setPort(swaggerPort);
        factory.addAdditionalTomcatConnectors(swaggerConnector);
    }

    @Bean
    public FilterRegistrationBean<SwaggerFilter> swaggerFilterRegistrationBean() {

        FilterRegistrationBean<SwaggerFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new SwaggerFilter());
        filterRegistrationBean.setOrder(-100);
        filterRegistrationBean.setName("SwaggerFilter");

        return filterRegistrationBean;
    }

    private class SwaggerFilter extends OncePerRequestFilter {

        private AntPathMatcher pathMatcher = new AntPathMatcher();

        @Override
        protected void doFilterInternal(HttpServletRequest httpServletRequest,
                                        HttpServletResponse httpServletResponse,
                                        FilterChain filterChain) throws ServletException, IOException {

            boolean isSwaggerPath = swaggerPaths.stream()
                    .anyMatch(path -> pathMatcher.match(path, httpServletRequest.getServletPath()));
            boolean isSwaggerPort = httpServletRequest.getLocalPort() == swaggerPort;

            if(isSwaggerPath == isSwaggerPort) {
                filterChain.doFilter(httpServletRequest, httpServletResponse);
            } else {
                httpServletResponse.sendError(404);
            }
        }
    }
}

属性swagger.portswagger.paths配置在application.yaml:

server.port: 8080
swagger:
  port: 8088
  paths: |
    /swagger-ui.html,
    /webjars/springfox-swagger-ui/**/*,
    /swagger-resources,
    /swagger-resources/**/*,
    /v2/api-docs

到目前为止一切顺利:swagger-ui 在端口 8088 上提供服务,我们的 api 在 8080 上提供服务。 但是有一个问题:当我们尝试从 swagger-ui 连接到 api 时, 请求被发送到 8088 而不是 8080。

步骤 3. 调整 SpringFox 配置。

Swagger 假定 api 与 swagger-ui 在同一端口上运行。 我们需要明确指定端口:

@Value("${server.port}")
private int serverPort;

@Bean
public Docket docket() {
    return new Docket(DocumentationType.SWAGGER_2)
            .host("localhost:" + serverPort);
}

最后一个问题:由于 ui 与 api 在不同的端口上运行, 这些请求被认为是跨源的。我们需要解锁它们。 可以在全球范围内完成:

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**/*").allowedOrigins("http://localhost:" + swaggerPort);
        }
    };
}

或通过向控制器添加注释:

@CrossOrigin(origins = "http://localhost:${swagger.port}")

使用的版本:SpringBoot 2.2.2.RELEASE,springfox-swagger2 2.9.2

有关工作示例,请参阅 https://github.com/mafor/swagger-ui-port