Skip to content

Commit

Permalink
GH-5 Swagger goups support
Browse files Browse the repository at this point in the history
adding basic support for swagger groups
  • Loading branch information
lex-em committed Mar 22, 2019
1 parent 8e22f88 commit f8c8565
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package ru.reliabletech.zuul.swagger.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
Expand All @@ -20,7 +20,7 @@ public class ZuulSwaggerController {
private SwaggerService swaggerService;

@GetMapping("/api-docs")
public JsonNode getApiDocs(@RequestParam("route") String route) {
return swaggerService.getSwaggerDoc(route);
public ObjectNode getApiDocs(@RequestParam("route") String route, @RequestParam(name = "group", required = false) String group) {
return swaggerService.getSwaggerDoc(route, group);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class ServiceInfo {

private String swaggerUri;

private String swaggerResourcesUri;

private String protocol = "";

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
public class ServicesSwaggerInfo {

public static final String DEFAULT_SWAGGER_API_URL = "v2/api-docs";
public static final String DEFAULT_SWAGGER_RESOURCES_URL = "swagger-resources";
public static final String PROTOCOL_DEFAULT = "http://";

private String prefix;

private String defaultSwaggerUrl = DEFAULT_SWAGGER_API_URL;
private String defaultSwaggerResourcesUrl = DEFAULT_SWAGGER_RESOURCES_URL;

private String defaultProtocol = PROTOCOL_DEFAULT;

Expand All @@ -39,6 +41,12 @@ public String getSwaggerUrl(String route) {
.orElse(defaultSwaggerUrl);
}

public String getSwaggerResourcesUrl(String route) {
return Optional.ofNullable(routes.get(route))
.map(ServiceInfo::getSwaggerResourcesUri)
.orElse(defaultSwaggerResourcesUrl);
}

public String getDefaultProtocol(String route) {
return Optional.ofNullable(routes.get(route))
.map(ServiceInfo::getProtocol)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import ru.reliabletech.zuul.swagger.exception.NotFoundException;
import ru.reliabletech.zuul.swagger.props.ServicesSwaggerInfo;
import springfox.documentation.swagger.web.SwaggerResource;

import java.util.List;

/**
* General implementation
Expand All @@ -25,8 +32,8 @@ public class GenericSwaggerService implements SwaggerService {
private RouteService routeService;

@Override
public ObjectNode getSwaggerDoc(String route) {
ObjectNode swaggerDocumentation = getOriginalSwaggerDoc(route);
public ObjectNode getSwaggerDoc(String route, String group) {
ObjectNode swaggerDocumentation = getOriginalSwaggerDoc(route, group);
swaggerDocumentation.set("host", new TextNode(""));
String path = new StringBuilder().append(servicesSwaggerInfo.getPrefix())
.append("/")
Expand All @@ -38,12 +45,33 @@ public ObjectNode getSwaggerDoc(String route) {
}

@Override
public ObjectNode getOriginalSwaggerDoc(String route) {
public List<SwaggerResource> getSwaggerResources(String route) {
String serviceUrl = servicesSwaggerInfo.getServiceUrl(route)
.orElseGet(() -> servicesSwaggerInfo.getDefaultProtocol() + route);
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(serviceUrl)
.path(servicesSwaggerInfo.getSwaggerResourcesUrl(route));
String url = uriBuilder.build().toUriString();
try {
return restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, new ParameterizedTypeReference<List<SwaggerResource>>(){})
.getBody();
} catch (IllegalStateException e) {
if (e.getMessage() == null || !e.getMessage().startsWith("No instances available for")) {
throw e;
}
throw new NotFoundException();
}
}

@Override
public ObjectNode getOriginalSwaggerDoc(String route, String group) {
String serviceUrl = servicesSwaggerInfo.getServiceUrl(route)
.orElseGet(() -> servicesSwaggerInfo.getDefaultProtocol() + route);
String url = String.format("%s/%s",
serviceUrl,
servicesSwaggerInfo.getSwaggerUrl(route));
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(serviceUrl)
.path(servicesSwaggerInfo.getSwaggerUrl(route));
if (group != null) {
uriBuilder.queryParam("group", group);
}
String url = uriBuilder.build().toUriString();
try {
return restTemplate.getForObject(url, ObjectNode.class);
} catch (IllegalStateException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package ru.reliabletech.zuul.swagger.service;

import com.fasterxml.jackson.databind.node.ObjectNode;
import springfox.documentation.swagger.web.SwaggerResource;

import java.util.List;

/**
* Service for operations over connected services swagger documentations
Expand All @@ -14,27 +17,26 @@ public interface SwaggerService {
* Obtain original documentation of service, represented by route
*
* @param route
* @param group
* @return
*/
ObjectNode getOriginalSwaggerDoc(String route);
ObjectNode getOriginalSwaggerDoc(String route, String group);

/**
* Obtain modified for proxy's swagger-ui documentation of service, represented by route
*
* @param route
* @param group
* @return
*/
ObjectNode getSwaggerDoc(String route);
ObjectNode getSwaggerDoc(String route, String group);

/**
* Obtain swagger documentation version for service, represented by route
* Requesting swagger resources list from route
*
* @param route
* @return
*/
default String getSwaggerVersion(String route) {
ObjectNode swaggerDocumentation = getOriginalSwaggerDoc(route);
return swaggerDocumentation == null ? "" : swaggerDocumentation.get("swagger").asText();
}
List<SwaggerResource> getSwaggerResources(String route);

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriComponentsBuilder;
import ru.reliabletech.zuul.swagger.props.ServicesSwaggerInfo;
import ru.reliabletech.zuul.swagger.service.SwaggerService;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
Expand All @@ -36,24 +40,39 @@ public class ZuulSwaggerResourceProvider implements SwaggerResourcesProvider {
@Override
public List<SwaggerResource> get() {
return Stream.concat(discoveryClient.getServices().stream(), servicesSwaggerInfo.getRouteNames().stream())
.map(this::generateSwaggerDocumentationResource)
.distinct()
.flatMap(this::generateSwaggerDocumentationResource)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}

private SwaggerResource generateSwaggerDocumentationResource(String route) {
String swaggerVersion;
private Stream<SwaggerResource> generateSwaggerDocumentationResource(String route) {
try {
swaggerVersion = swaggerService.getSwaggerVersion(route);
return swaggerService.getSwaggerResources(route)
.stream()// TODO groups should be filtered
.map(swaggerResource -> {
MultiValueMap<String, String> queryParams = UriComponentsBuilder.fromUriString(swaggerResource.getUrl())
.build()
.getQueryParams();
UriComponentsBuilder swaggerDocRouteBuilder = UriComponentsBuilder.fromPath("/api-docs")
.queryParam("route", route);
String routeName = route;
if (queryParams.containsKey("group")) {
String group = queryParams.getFirst("group");
swaggerDocRouteBuilder.queryParam("group", group);
routeName = route + "-" + group;
}
String swaggerVersion = swaggerResource.getSwaggerVersion();
SwaggerResource pluginSwaggerResource = new SwaggerResource();
pluginSwaggerResource.setName(routeName);
pluginSwaggerResource.setUrl(swaggerDocRouteBuilder.build().toUriString());
pluginSwaggerResource.setSwaggerVersion(swaggerVersion);
return pluginSwaggerResource;
});
} catch (Exception e) {
log.error(String.format("Some error during obtain swagger documentation for route %s", route), e);
return null;
return Stream.empty();
}
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(route);
swaggerResource.setLocation("/api-docs?route=" + route);
swaggerResource.setSwaggerVersion(swaggerVersion);
return swaggerResource;
}

}

0 comments on commit f8c8565

Please sign in to comment.