is it possible to consider the zuul filter (manual or automatic) to show in the swagger?
The issue is the following:
we have a microservice which is the single point of entry for our application and which holds all swagger documentation. in fact it works as a fasade, so it routes the request to the corresponding microservices inside our application. Unfortunately, zuul sometimes it adds something to the route or removes something. therefore the swagger documentation is incorrect, as the base-path is slightly different.
is there any possiblity to influence this?
swagger docket is used with simple lookup:
#Bean
public Docket swaggerSpringfoxDocket() {
this.log.debug("Starting Swagger");
StopWatch watch = new StopWatch();
watch.start();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.forCodeGeneration(false)
.select()
.paths(regex("/api/.*"))
.build();
watch.stop();
this.log.debug("Started Swagger in {} ms", watch.getTotalTimeMillis());
return docket;
}
Related
I want to ignore the swagger URL's based on active profiles in spring boot application. I found #ApiIgnore and #Hidden, but they hide API irrespective of profile. Here, I want to hide some API's only for PROD but not other profile(i.e., DEV, UAT, etc.,). Is there a way I can achieve this. Please suggest
They are multiple way of doing this, one simple approach (but not elegant at all) is to actually create multiple Docket's for different profiles.
Example:
#Configuration
public class SpringFoxConfig {
#Bean
#Profile("dev")
public Docket getDocketForDev() {
final Set<String> produces = new HashSet<String>();
produces.add(MediaType.APPLICATION_JSON_VALUE);
produces.add(MediaType.APPLICATION_XML_VALUE);
return new Docket(DocumentationType.OAS_30)
.apiInfo(new ApiInfoBuilder()
.title("Note API")
.description("A CRUD API to demonstrate Springfox 3 integration")
.version("0.0.1")
.license("MIT")
.licenseUrl("https://opensource.org/licenses/MIT")
.build())
.produces(produces).consumes(produces)
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.build();
}
#Bean
#Profile("prod")
public Docket getDocketForProd() {
final Set<String> produces = new HashSet<String>();
produces.add(MediaType.APPLICATION_JSON_VALUE);
produces.add(MediaType.APPLICATION_XML_VALUE);
return new Docket(DocumentationType.OAS_30)
.apiInfo(new ApiInfoBuilder()
.title("Note API")
.description("A CRUD API to demonstrate Springfox 3 integration")
.version("0.0.1")
.license("MIT")
.licenseUrl("https://opensource.org/licenses/MIT")
.build())
.produces(produces).consumes(produces)
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.build();
}
}
Now after you have multiple docket's per environment you can play with this line of code:
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
and display endpoints based on your conditions per environment.
Using swagger3.0.0.
I have this working code that displays the authorize button and headers for every endpoint, but I'd like to disable them when I'm on a different profile. Instead of creating an entirely new configuration I wanted to handle it when I create my docket.
#Bean
public Docket d(){
Docket dock = new Docket(DocumentationType.OAS_30);
docket
.select()
.apis(RequestHandlerSelectors.basePackage("myapp.test.api"))
.build()
.apiInformation(apiinfo())
//enabling authorize button and setting globally across all endpoints
.securitySchemes(Collections.singletonList(authenticationScheme))
.securityContexts(Collections.singletonList(securityContext()));
return docket;
}
The below code is what I'm attempting to do. I thought I could simply get the activeProfile from env and check but I'm getting an error where activeProfiles is null. Is it because of how spring-boot is initialized?
Cannot invoke "org.springframework.core.env.Environment.getActiveProfiles()" because "this.env" is null
#Autowired
Environment env;
boolean x = Arrays.stream(env.getActiveProfiles()).anyMatch("this_profile"::contains);
#Bean
public Docket d(){
Docket dock = new Docket(DocumentationType.OAS_30);
docket
.select()
.apis(RequestHandlerSelectors.basePackage("myapp.test.api"))
.build()
.apiInformation(apiinfo());
if(x){
docket
//enabling authorize button and setting globally across all endpoints
.securitySchemes(Collections.singletonList(authenticationScheme))
.securityContexts(Collections.singletonList(securityContext()));
}
return docket;
}
Try to inline the x variable as if I remember correctly #Autowired won't inject the Environment class by the time you hit the definition of your x variable as it is now.
if(Arrays.stream(env.getActiveProfiles()).anyMatch("this_profile"::contains);){
docket
//enabling authorize button and setting globally across all endpoints
.securitySchemes(Collections.singletonList(authenticationScheme))
.securityContexts(Collections.singletonList(securityContext()));
}
I am trying to change the base path of swagger codumentation. Currently I have
#RequestMapping(path = "/api/resourceName/v1")
and swagger config
return new Docket(DocumentationType.SWAGGER_2).
select()
.apis(RequestHandlerSelectors.basePackage("com.company"))
.paths(PathSelectors.ant("/api/**"))
.build()
.apiInfo(apiInfo());
This is giving swagger base path as "basePath": "/"
I want to add base path as "basePath": "/api" so I followed diff threads like this How to change basePath for Springfox Swagger 2.0 and added
return new Docket(DocumentationType.SWAGGER_2).
select()
.apis(RequestHandlerSelectors.basePackage("com.company"))
.paths(PathSelectors.ant("/api/**"))
.build()
.apiInfo(apiInfo())
.pathProvider(new RelativePathProvider(servletContext) {
#Override
public String getApplicationBasePath() {
return "/api";
}
});
now the base path is changed to "basePath": "/api" and I updated my path mapping to #RequestMapping(path = "/resourceName/v1") as base has been added.
When I send the request from swagger, the request is going to /api/resourceName/v1 but the service returns 404.
When I send the request through postman for /resourceName.v1 then it works.
So the api is registred as /resourceName/v1 and the base is just added by swagger on top of it and will not work if the request sent throguh swagger UI
Then I added server.servlet-path=/api to application.properties to register basepath in the request mapping and now swagger shows the base path as /api without needing additional configuration.
But the problem is now swagger documentation is available at http://localhost:8080/api/swagger-ui.html instead of http://localhost:8080/swagger-ui.html. As we have all our other services doc at http://host/swagger-ui.html this is not useful.
Is there any way to add the base and still access the doc at http://host/swagger-ui.html and api's works as expected fro swagger and postman
Yes, you can add base path for all swagger requests. I used following config for this purpose:
#Configuration
#EnableSwagger2
public class SpringFoxConfig {
#Bean
public Docket api() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
docket.pathMapping("api");
return docket;
}
}
Hope this helps.
There is way to change the api-doc base path using properties defined in application.properties file.
The properties are:
springfox.documentation.openApi.v3.path=/external/api/app/v3/api-docs
springfox.documentation.swaggerv2.path=/external/api/app/v2/api-docs
This can help you to change the path.
When configuring a Docket we have to specify the base package where to look for api endpoints. Is it possible to add manually an endpoint which is not mapped to any controller?
I have a legacy application which is a simple Zuul server but it has a swagger-ui, the goal is to specifiy endpoints that are proxied by zuul?
#Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.globalOperationParameters(getHeaders()).select()
.apis(RequestHandlerSelectors.basePackage("package.controllers"))
.additionalApis(Method.PUT, "/my/manual/endpoint") // This does not exist
.paths(PathSelectors.any())
.build();
}
Thanks
I'm working on Spring Boot application and i use Swagger for the documentation.
I have adding Spring Boot Actuator on my application, but now i want to add the new services creating by actuator (/health /metrics ..) on my swagger documentation.
I don't find how configure Actuator and Swagger.
You can configure in Swagger which paths you want to be added to the documentation :
#Bean
public Docket appApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
...
}
will display all available endpoints.
.paths(PathSelectors.any("/mypath/**")) will limit only to endpoints exposed in mypath.
In order to display spring-boot-actuator endpoints in springdoc-openapi, simply add the following property:
springdoc.show-actuator=true
Update: 26-04-2017, updated implemention. Credits to Andy Brown for the tip.
Due to our coding convention, we don't have a specific prefix for our endpoints, so I was looking for a solution to exclude the actuator endpoints, rather than to include my own paths.
I've came up with the following config to only exclude the actuator endpoints.
This way, I don't have to update the config once I add new endpoints nor do I have to prefix my own endpoints to distinguish them from the actuator endpoints.
/**
* This enables swagger. See http://localhost:8080/v2/api-docs for the swagger.json output!
* #param actuatorEndpointHandlerMapping this endpoint handler mapping contains all the endpoints provided by the
* spring actuator. We will iterate over all the endpoints and exclude them from the swagger documentation.
* #return the docket.
*/
#Autowired
#Bean
public Docket swaggerSpringMvcPlugin(final EndpointHandlerMapping actuatorEndpointHandlerMapping) {
ApiSelectorBuilder builder = new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false)
.apiInfo(apiInfo())
.securitySchemes(securitySchemes())
.select();
// Ignore the spring-boot-actuator endpoints:
Set<MvcEndpoint> endpoints = actuatorEndpointHandlerMapping.getEndpoints();
endpoints.forEach(endpoint -> {
String path = endpoint.getPath();
log.debug("excluded path for swagger {}", path);
builder.paths(Predicates.not(PathSelectors.regex(path + ".*")));
});
return builder.build();
}
ApiSelectorBuilder builder = new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false)
.apiInfo(apiInfo())
.securitySchemes(securitySchemes())
.select()
.apis(RequestHandlerSelectors.any())
.paths(Predicates.not(PathSelectors.regex("/actuator.*")))
.build();
Hi, You can exclude path on regex and you can chain them.
Move the actuator endpoints into a context path through your application.properties file.
management.context-path=/manage
Then you can exclude that path from swagger
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(Predicates.not(PathSelectors.regex("/manage.*")))
.build();
}
You might want to exclude the error controller too
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(Predicates.not(PathSelectors.regex("(/manage.*|/error)")))
.build();
}
Alternatives:
a) Exclude path with a NOT in the Regex?
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.regex("^((?!/error).)*")) // exclude Basic Error Controller
.build();
}
b) or chain and negate a Predicate:
PathSelectors.any()
.and(PathSelectors.regex("/error").negate())
.and(PathSelectors.regex("/manage.*").negate());