I've run into the same issue and I didn't find a clean solution because there hasn't integration between Swagger
and Webflux
yet.
On the other hand, I succeed to set up a minimal configuration to create a proxy for swagger.
First you need to create a controller exposing Swagger
API and ressources :
@Controller
public class SwaggerController {
private final JsonSerializer jsonSerializer;
private final SwaggerResourcesProvider swaggerResources;
@Autowired
public SwaggerController(JsonSerializer jsonSerializer, SwaggerResourcesProvider swaggerResources) {
this.jsonSerializer = jsonSerializer;
this.swaggerResources = swaggerResources;
}
@RequestMapping({"/swagger-resources/configuration/security"})
@ResponseBody
public ResponseEntity<SecurityConfiguration> securityConfiguration() {
return ResponseEntity.ok(SecurityConfigurationBuilder.builder().build());
}
@RequestMapping({"/swagger-resources/configuration/ui"})
@ResponseBody
public ResponseEntity<UiConfiguration> uiConfiguration() {
return ResponseEntity.ok(UiConfigurationBuilder.builder().build());
}
@RequestMapping({"/swagger-resources"})
@ResponseBody
public ResponseEntity<List<SwaggerResource>> swaggerResources() {
return ResponseEntity.ok(this.swaggerResources.get());
}
@RequestMapping(
value = {"/v2/api-docs"},
method = {RequestMethod.GET},
produces = {"application/json", "application/hal+json"}
)
@ResponseBody
public ResponseEntity<Json> getDocumentation() {
Swagger swagger = new Swagger();
return ResponseEntity.ok(this.jsonSerializer.toJson(swagger));
}
}
Next you need a swagger configuration to create Swagger ressources from your microservices :
package com.stackoverflow.gateway.config;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import springfox.documentation.spring.web.json.JacksonModuleRegistrar;
import springfox.documentation.spring.web.json.JsonSerializer;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@Configuration
public class SwaggerConfig {
private final GatewayProperties properties;
public SwaggerConfig(GatewayProperties properties) {
this.properties = properties;
}
@Bean
public JsonSerializer jsonSerializer(List<JacksonModuleRegistrar> moduleRegistrars) {
return new JsonSerializer(moduleRegistrars);
}
@Primary
@Bean
@Lazy
public SwaggerResourcesProvider swaggerResourcesProvider() {
return () -> properties.getRoutes().stream()
.map(route -> createResource(route.getId(), getRouteLocation(route), "2.0"))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
// You will certainly need to edit this
private String getRouteLocation(RouteDefinition route) {
return Optional.ofNullable(route.getPredicates().get(0).getArgs().values().toArray()[0])
.map(String::valueOf)
.map(s -> s.replace("*", ""))
.orElse(null);
}
private SwaggerResource createResource(String name, String location, String version) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location + "/v2/api-docs");
swaggerResource.setSwaggerVersion(version);
return swaggerResource;
}
}
I think this solution will not work if you use a Service Discovery server but for my case I don't need to because I have a config for spring.cloud.gateway.routes
:
- id: api-client
uri: lb://client
predicates:
- Path=/api/client/**
This can easily adapted to fetch service location from Eureka or Consul.
Let me know if it works. And if someone found another alternative I'm interested.