是否可以在与主应用程序不同的端口上 运行 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.port
和swagger.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
我们使用 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.port
和swagger.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