- Groups already configured in the test service
- configure gateway
- Adding dependencies to pom
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
- Injection Routing to SwaggerResource
@Component @Primary public class SwaggerProvider implements SwaggerResourcesProvider { public static final String API_URI = "/v2/api-docs"; private RouteLocator routeLocator; private GatewayProperties gatewayProperties; @Override public List<SwaggerResource> get() { List<SwaggerResource> resources = new ArrayList<>(); List<String> routes = new ArrayList<>(); //Remove route from gateway routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); //Combining route-path (Path) configuration with route filtering, only valid route nodes are obtained. gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())) .forEach(routeDefinition -> routeDefinition.getPredicates().stream() .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName())) .forEach(predicateDefinition -> { // FIXME has limited capabilities and can't think of a better way to integrate the grouping of individual services String name = routeDefinition.getId(); // Name is the service name if ("test".equals(name)) { String location = predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0") .replace("/**", API_URI); resources.add(swaggerResource(name + "/test1", location + "?group=test1")); resources.add(swaggerResource(name + "/test2", location + "?group=test2")); return; } resources.add(swaggerResource(name, predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0") .replace("/**", API_URI))); })); return resources; } private SwaggerResource swaggerResource(String name, String location) { SwaggerResource swaggerResource = new SwaggerResource(); swaggerResource.setName(name); swaggerResource.setLocation(location); swaggerResource.setSwaggerVersion("2.0"); return swaggerResource; } @Autowired public SwaggerProvider(RouteLocator routeLocator, GatewayProperties gatewayProperties) { this.routeLocator = routeLocator; this.gatewayProperties = gatewayProperties; }
- Provide Swagger External Interface
@RestController @RequestMapping("/swagger-resources") public class SwaggerController { @Autowired(required = false) private SecurityConfiguration securityConfiguration; @Autowired(required = false) private UiConfiguration uiConfiguration; private final SwaggerResourcesProvider swaggerResources; @GetMapping("/configuration/security") public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() { return Mono.just(new ResponseEntity<>( Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK)); } @GetMapping("/configuration/ui") public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() { return Mono.just(new ResponseEntity<>( Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); } @GetMapping public Mono<ResponseEntity> swaggerResources() { return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); } @Autowired public SwaggerController(SwaggerResourcesProvider swaggerResources) { this.swaggerResources = swaggerResources; } }
- Swagger Path Conversion
With the above configuration, the document can be referenced and displayed, but using Swagger's try it out function, it can be found that the path is the path after route cutting, such as:
The path in the Swagger document is:
Host Name: Port: The mapping path is missing a service routing prefix because the display handler has been processed by the Strip Prefix Gateway FilterFactory filter, and the original routing prefix has been filtered out!- Solution 1: Manually maintain a prefix through Swagger's host configuration
return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .host("Host name: port: service prefix") //Note the hostname here: the port is the address and port of the gateway .select() .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) .paths(PathSelectors.any()) .build() .globalOperationParameters(parameterList);
- Solution 2: Add X-Forwarded-Prefix
Configure appction.yml@Component public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory { private static final String HEADER_NAME = "X-Forwarded-Prefix"; @Override public GatewayFilter apply(Object config) { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest(); String path = request.getURI().getPath(); if (!StringUtils.endsWithIgnoreCase(path, SwaggerProvider.API_URI)) { return chain.filter(exchange); } String basePath = path.substring(0, path.lastIndexOf(SwaggerProvider.API_URI)); ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build(); ServerWebExchange newExchange = exchange.mutate().request(newRequest).build(); return chain.filter(newExchange); }; } }
- id: test uri: lb://test predicates: - Path=/test/** filters: - SwaggerHeaderFilter - StripPrefix=1
- Solution 1: Manually maintain a prefix through Swagger's host configuration
- Adding dependencies to pom
- Nginx configuration
- Nginx configuration file
# Configure login with username and password location /swagger-ui.html { auth_basic "test"; # Relative path: the location of htpasswd on the machine: / usr/local/nginx/conf/htpasswd auth_basic_user_file htpasswd; # Absolute path: the location of htpasswd on the machine: / tmp/htpasswd # auth_basic_user_file /tmp/htpasswd; proxy_pass http://zxjl/swagger-ui.html; } location /swagger-resources { proxy_pass http://zxjl/swagger-resources; } location /webjars { proxy_pass http://zxjl/webjars; }
- Create htpasswd
# Format: Username: Password, note that the password is encrypted using crypt admin:PbSRr7orsxaso
- Nginx configuration file
Reference resources: Spring Cloud Gateway aggregates swagger documents
nginx configuration instructions auth_basic, auth_basic_user_file and related knowledge