-
-
Notifications
You must be signed in to change notification settings - Fork 504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
change SwaggerIndexTransformer and SwaggerConfig design to ease customization #745
Comments
You can just extend from, one of the following classes depending on your case (webflux or not)
And just declare your new class as a Spring Bean. You will be able to add your additional configuration (CSS, ...) |
it is working indeed. This is why I'm not fond of the inheritance and suggest an interface instead:
|
When you say:
You override the transform i suppose. And this this one of the advantages of the inheritance.
|
@bnasslahsen, The implementation class is: public class MySwaggerIndexTransformer extends SwaggerIndexTransformer implements ResourceTransformer {
private MySwaggerIndexTransformerSupport support;
public MySwaggerIndexTransformer(SwaggerUiConfigProperties swaggerUiConfig, SwaggerUiOAuthProperties swaggerUiOAuthProperties, ObjectMapper objectMapper, MyOptions options) {
super(swaggerUiConfig, swaggerUiOAuthProperties, objectMapper);
support = new MySwaggerIndexTransformerSupport(swaggerUiConfig, swaggerUiOAuthProperties, objectMapper, options);
}
@Override
public Mono<Resource> transform(ServerWebExchange serverWebExchange, Resource resource, ResourceTransformerChain resourceTransformerChain) {
return Mono.just(support.transform(resource, resourceTransformerChain));
}
} This class only delegates to the support class: // extend to use methods from abstract class
public class MySwaggerIndexTransformerSupport extends AbstractSwaggerIndexTransformer {
private final MyOptions options;
public MySwaggerIndexTransformerSupport(SwaggerUiConfigProperties swaggerUiConfig, SwaggerUiOAuthProperties swaggerUiOAuthProperties, ObjectMapper objectMapper, MyOptions options) {
super(swaggerUiConfig, swaggerUiOAuthProperties, objectMapper);
this.options = options;
}
public Resource transform(Resource resource, ResourceTransformerChain resourceTransformerChain) {
try {
return transformNoCheck(resource);
} catch (Exception e) {
throw new SpringDocUIException("Failed to transform Index", e);
}
}
// does not handle exception to ease readability
private Resource transformNoCheck(Resource resource) throws IOException {
// first we execute code from super class (same result as the current SwaggerIndexTransformer)
final AntPathMatcher antPathMatcher = new AntPathMatcher();
boolean isIndexFound = antPathMatcher.match("**/swagger-ui/**/index.html", resource.getURL().toString());
if (isIndexFound) {
String html = readFullyAsString(resource.getInputStream());
if (swaggerUiConfig.isDisableSwaggerDefaultUrl()) {
html = overwriteSwaggerDefaultUrl(html);
}
if (!CollectionUtils.isEmpty(swaggerUiOAuthProperties.getConfigParameters())) {
html = addInitOauth(html);
}
// my methods for customization: add css, js script and change page title
// these methods are not displayed here
html = headAppender.appendToHead(html);
html = overwriteTitle(html);
return new TransformedResource(resource, html.getBytes());
} else {
return resource;
}
} I first replicate the behavior of implementations of When I say I don't use inheritance that means I implement the method inherited from To answer your last question, interface SwaggerIndexPageTransformer extends ResourceTransformer {
// no other method
} With this the condition would be: @Bean
@ConditionalOnMissingBean
SwaggerIndexPageTransformer indexPageTransformer(...) {...} |
Inheritance, is not only about the call of super. There are other advantages / benefits of inheritance (Extensibility indeed). I understand, that additionnally, you are proposing to add two marker(empty) interfaces (one for webflux and another for webmvc). In the existing implementation, if a user wants to add his own, he can simply override SwaggerIndexTransformer, and decide or not to benefit from the other methods in AbstractSwaggerIndexTransformer. This is a visual explanation of the existing implementation. If you can do the same, this will make your proposal much clear, about what are the advantages, the impacts on the springdoc-ui and also what will an application need to do to override with its own implemenation. I have used online.visual-paradigm , but you can use any UML tool you feel confortable with to describe your proposal. |
@bnasslahsen thanks for taking the time to discuss my idea (I'm sure you have plenty on your plate already). I did a similar job with the extensions I propose: If people want to customize only webmvc or webflux (because they use only one) then they could extend the class you offer. I would be tempted to rename the classes and call the interface |
Hi @natrem, I see your point. This makes your enhancement much clear. |
As they say a picture is worth a thousand words. |
Is your feature request related to a problem? Please describe.
When people want to extend the behavior of Swagger UI transformers (
SwaggerIndexTransformer
declared inorg.springdoc.webmvc.ui.SwaggerConfig
andorg.springdoc.webflux.ui.SwaggerConfig
they have to inherit from your specialized classes instead of just using the provided abstract support class (AbstractSwaggerIndexTransformer
).I think that the design could be improved and the signatures used in
SwaggerConfig
classes modified to ease work for reuse.In my case I want to inject css file and js file (used for OIDC) to the document. I created a support class similar to:
And to use it I create a Bean:
Describe the solution you'd like
I have 2 proposals based on this use case.
SwaggerIndexPageTransformer
declared in common module and used inSwaggerConfig
classesThe inconvenience is that it cannot extend
ResourceTransformer
sinceResourceTransformer
exist for servlet and reactive resources. Since transformation only uses the Resource you could declare a reduced signature:Resource transform(Resource resource);
AbstractSwaggerIndexTransformer
to a support class used by composition instead of inheritance to simplify reuseWith this, the specialized behavior would not have to inherit the current
SwaggerIndexTransformer
but 'only' need to implement an interface.Describe alternatives you've considered
SwaggerConfig
classes you could use a named bean:I think this is less readable than the proposed evolution and it also breaks the current contract.
The other possibility I see is to declare the
AbstractSwaggerIndexTransformer
class in signature (instead of the specialized implementationAdditional context
I'm willing to work on this if you agree on these changes.
The text was updated successfully, but these errors were encountered: