Closed gdinant closed 2 years ago
Side note, I tried for the sake of testing to set the server manually in the Docket to see whether that would influence somehow the output but it didn't.
@Bean
public Docket configureControllerPackageAndConvertors() {
return new Docket(DocumentationType.OAS_30).select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.build()
.servers(new Server("http://localhost:9000", "test", "test", List.of(), List.of()));
}
Regarding this I'm a bit confused by how DocumentationBuilder
works.
ApiDocumentationScanner
does the following:
public Documentation scan(DocumentationContext context) {
ApiListingReferenceScanResult result = apiListingReferenceScanner.scan(context);
ApiListingScanningContext listingContext = new ApiListingScanningContext(context,
result.getResourceGroupRequestMappings());
Map<String, List<ApiListing>> apiListings = apiListingScanner.scan(listingContext);
Set<Tag> tags = toTags(apiListings);
tags.addAll(context.getTags());
DocumentationBuilder group = new DocumentationBuilder()
.name(context.getGroupName())
.apiListingsByResourceGroupName(apiListings)
.produces(context.getProduces())
.consumes(context.getConsumes())
.host(context.getHost())
.schemes(context.getProtocols())
.basePath(ROOT)
.extensions(context.getVendorExtentions())
.tags(tags);
Set<ApiListingReference> apiReferenceSet = new TreeSet<>(listingReferencePathComparator());
apiReferenceSet.addAll(apiListingReferences(apiListings, context));
group.resourceListing(r ->
r.apiVersion(context.getApiInfo().getVersion())
.apis(apiReferenceSet.stream()
.sorted(context.getListingReferenceOrdering())
.collect(toList()))
.securitySchemes(context.getSecuritySchemes())
.info(context.getApiInfo())
.servers(context.getServers()));
return group.build();
}
servers
will be added to ResourceListing
but in DocumentationBuilder.build()
the servers will be compiled not from the servers contained in ResourceListing
but from the local attributes servers which isn't settable.
public Documentation build() {
return new Documentation(
this.groupName,
this.basePath,
this.tags,
this.apiListings,
this.resourceListing,
this.produces,
this.consumes,
this.host,
this.schemes,
(Collection)this.servers.values().stream().map(ServerBuilder::build).collect(Collectors.toList()),
this.externalDocumentation,
this.vendorExtensions);
}
So two issues here:
1) Why is the inferred URL isn't working with WebFlux 2) In the event of a bug somewhere, how I can set this value manually?
I also found that after the value of servers is set, there is no change to the front-end, and the host configuration is not reflected in the front-end. It seems that only the basic configuration takes effect.The configuration information is the same as above.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I'd like it fixed :)
The problem in the ApiDocumentationScanner
, mentioned by @gdinant isn't the only issue.
If you add the following workaround:
// Override Springfox bean to correctly set servers
// See https://github.com/springfox/springfox/issues/3810
@Primary
@Component
public static class CustomApiDocumentationScanner extends ApiDocumentationScanner {
public CustomApiDocumentationScanner(
ApiListingReferenceScanner apiListingReferenceScanner,
ApiListingScanner apiListingScanner) {
super(apiListingReferenceScanner, apiListingScanner);
}
@Override
public Documentation scan(DocumentationContext context) {
Documentation documentation = super.scan(context);
documentation.getResourceListing().getServers().forEach(documentation::addServer); // <=== FIX ===
return documentation;
}
}
the servers get set correctly in the Documentation object, but they still aren't returned correctly when requesting /v3/api-docs.
This is because the OpenApiControllerWebMvc.getDocumentation method, which handles requests to /v3/api-docs, and which retrieves the Documentation object, which the above code snippet fixes, also executes the following:
OpenAPI oas = this.mapper.mapDocumentation(documentation);
OpenApiTransformationContext<HttpServletRequest> context = new OpenApiTransformationContext(oas, servletRequest);
List<WebMvcOpenApiTransformationFilter> filters = this.transformations.getPluginsFor(DocumentationType.OAS_30);
WebMvcOpenApiTransformationFilter each;
for(Iterator var8 = filters.iterator(); var8.hasNext(); context = context.next(each.transform(context))) {
each = (WebMvcOpenApiTransformationFilter)var8.next();
}
One of the filters, which it applies on the context is the WebMvcBasePathAndHostnameTransformationFilter
. What this class does is:
public OpenAPI transform(OpenApiTransformationContext<HttpServletRequest> context) {
OpenAPI openApi = context.getSpecification();
context.request().ifPresent((servletRequest) -> {
ForwardedHeaderExtractingRequest filter = new ForwardedHeaderExtractingRequest(servletRequest, new UrlPathHelper());
openApi.servers(Collections.singletonList(SpecGeneration.inferredServer(this.requestPrefix, filter.adjustedRequestURL())));
});
return openApi;
}
It replaces the list of servers in the OpenAPI object (which is the POJO version of the OAS3 spec) with a default value.
This issue is related to #3735.
You can add your own filter, to try to undo the problem. Unfortunately, after the WebMvcBasePathAnedHostnameTransformationFilter
is executed, the openApi object no longer contains the necessary server information.
A workaround is to configure your own filter with the necessary information so that it can set the information. Hardcoding the information would work too.
@Order(0)
@Component
public class ServerSettingOpenApiTransformationFilter implements WebMvcOpenApiTransformationFilter {
public OpenAPI transform(OpenApiTransformationContext<HttpServletRequest> context) {
OpenAPI openApi = context.getSpecification();
io.swagger.v3.oas.models.servers.Server server = new io.swagger.v3.oas.models.servers.Server();
server.setUrl(https://foobar.com);
server.setDescription("Foobar");
openApi.servers(List.of(server));
return openApi;
}
public boolean supports(DocumentationType delimiter) {
return delimiter == DocumentationType.OAS_30;
}
}
Since the WebMvcBasePathAnedHostnameTransformationFilter
is annotated with @Order(-2147483648)
, which is the highest precedence, it will get executed first, and thus allow us to override it's changes. If you omit the @Order(0) annotation, it will work too, since Spring will give unannotated components a lower precedence than annotated ones.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been automatically closed because it has not had recent activity. Please re-open a new issue if this is still an issue.
Hello everyone,
I have been running springfox with traditional Spring applications under tomcat for some time and I'm really happy with it.
Lately I started with webflux applications under netty. The same springfox configuration is applied to both projects, there is one slight difference in the end is that the servers section in the api-docs is missing which led to the swagger-ui being unusable.
Would you have any idea why so? Either I'm missing some settings or if there is really something odd in the setup of webflux apps in springfox. I couldn't find any leads on this topic.
Thanks for your support
[X ] What I'm getting in v3/api-docs
[X ] What I expect