自研网关系统已开源,求star 项目地址
网关一般都会有一个swagger聚合功能,方便于你测试文档接口。 但网上的例子,如https://doc.xiaominfo.com/solution/ui-front-gateway.html#%E6%96%87%E6%A1%A3%E8%81%9A%E5%90%88%E4%B8%9A%E5%8A%A1%E7%BC%96%E7%A0%81. 这些例子都能解决swagger聚合的问题,但问题是他只支持一个项目,但我网关肯定会有多个项目,这个怎么处理呢。 其实这个原理一样,但说起来也是有几个技术难点的.
@Component
public class SwaggerFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
//获取工程编码
String projectCode= RequestHelper.getRequestProjectCode(exchange.getRequest());
if (StringUtils.isNotEmpty(projectCode)&&projectCode.endsWith(GatewayConstant.STARMARK_SWAGGER)) {
if (exchange.getRequest().getURI().getPath().contains(projectCode + "/doc.html")) {
return chain.filter(exchange.mutate().request(exchange.getRequest().mutate().path("/doc.html").build()).build());
} else if (exchange.getRequest().getURI().getPath().contains(projectCode + "/webjars/")) {
return chain.filter(exchange.mutate().request(exchange.getRequest().mutate().path(exchange.getRequest().getURI().getPath().replace("/" + projectCode, "")).build()).build());
}
}
return chain.filter(exchange);
}
}
通过过滤器,将请求转向根请求 2.支持多项目的配置,每个请求都含项目编码,知道属于哪个项目.
@Controller
@RequestMapping()
public class SwaggerHandler {
@Autowired(required = false)
private SecurityConfiguration securityConfiguration;
@Autowired(required = false)
private UiConfiguration uiConfiguration;
private final SwaggerProvider swaggerResources;
@Autowired
public SwaggerHandler(SwaggerProvider swaggerResources) {
this.swaggerResources = swaggerResources;
}
@GetMapping("/{projectCode}/swagger-resources/configuration/security")
@ResponseBody
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration(@PathVariable("projectCode") String projectCode) {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/{projectCode}/swagger-resources/configuration/ui")
@ResponseBody
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration(){
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/{projectCode}/swagger-resources")
@ResponseBody
public Mono<ResponseEntity> swaggerResources(@PathVariable("projectCode") String projectCode) {
return Mono.just((new ResponseEntity<>(swaggerResources.get(projectCode), HttpStatus.OK)));
}
}
@Component
@Primary
@AllArgsConstructor
public class SwaggerProvider {
@Autowired
private IRouteService routeService;
public List<SwaggerResource> get(String projectCode) {
//获取真正的projectCode
String innerProjectCode = projectCode.replace(GatewayConstant.STARMARK_SWAGGER, "");
List<GatewayAppDto> appDtos = routeService.getGatewayApps(innerProjectCode);
List<SwaggerResource> resources = appDtos.stream().map(this::swaggerResource).collect(Collectors.toList());
return resources;
}
private SwaggerResource swaggerResource(GatewayAppDto gatewayAppVo) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(gatewayAppVo.getAppName());
swaggerResource.setLocation("/v2/api-docs?swagger_code="+gatewayAppVo.getAppCode());
swaggerResource.setSwaggerVersion("2.0");
return swaggerResource;
}
}
这样,我返回的每个接口地址都含有一个子模块参数swagger_code 3.解决swagger_code参数带来的不显示文档的问题 现在其实已经能显示swagger聚合文档,但发现显示不全,文档接口全没有了。 经排查,是接口/v2/api-docs不允许有任何参数。 解决办法时,网关转发时,使用RemoveRequestParameter把该参数swagger_code去掉 示例如下:
private List<FilterDefinition> createSwaggerFilterDefinition() {
List<FilterDefinition> filterDefinitions=new ArrayList<>();
{
Map<String, String> args = new HashMap<>();
args.put("name", "swagger_code");
FilterDefinition filterDefinition = new FilterDefinition();
filterDefinition.setName("RemoveRequestParameter");
filterDefinition.setArgs(args);
filterDefinitions.add(filterDefinition);
}
filterDefinitions.add(createFilterDefinition("1"));
return filterDefinitions;
}
至此,多项目的网关聚合功能已完成.
image.png
具体代码大家可以去我的开源项目中看,欢迎提ISSUE及需求。 因为只有一个人,也欢迎大家参与进来.
下期需求计划: 网关配置转发后,可能有些接口出问题,临时不允许访问,或升级时转发到另一地址,需要做url的下架,转发功能