Martin Asenov
Martin Asenov

Reputation: 1298

How to change basePath for Springfox Swagger 2.0

I'm running a service, where Swagger UI is accessible at:

http://serviceURL/swagger-ui.html

However, it is behind a proxy, such as:

http://proxyURL/serviceName

Generated URLs by Swagger UI are looking like:

http://proxyURL/

instead of the actual URL with the serviceName as suffix. As far as I get it, this means manipulating the basePath property. As per documentation:

A swagger API documentation can no longer describe operations on different base paths. In 1.2 and earlier, each resource could have had a separate basePath. In 2.0, the basePath equivalents (schemes+host+basePath) are defined for the whole specification.

@Api(basePath) is deprecated, and it doesn't say what to use and how to use it. How to make the paths generated by Swagger appear properly?

I'm using Spring Boot, Springfox Swagger and annotations.

Upvotes: 35

Views: 29199

Answers (4)

bernie_boy
bernie_boy

Reputation: 27

I added the following config into my application.yaml file:

springdoc:
 swagger-ui:
  configUrl: /pathProvider/v3/api-docs/swagger-config
  disable-swagger-default-url: true
  urls[0]:
   url: /pathProvider/v3/api-docs/mobile-bff
   name: pathName

where pathProvider should be replaced by the PathProvider config in the old swagger 2 yaml...

and also, had do add a server into the OpenAPI object with the same PathProvider name.

@Bean fun springShopOpenAPI(): OpenAPI? { return OpenAPI().addServersItem(Server().url("/pathProvider"))

Upvotes: -1

Eko Prasetyo
Eko Prasetyo

Reputation: 41

Using spring fox 2.9.2, using solution mentioned by other users is not works.

What is not working:

  • Overriding getApplicationBasePath on Docket pathProvider
  • Adding server.servlet.context-path=/serviceName

I don't know why they are not work, but in my project that using Springboot 2.1.6.RELEASE and Spring 5.1.8.RELEASE, the two solution above is being ignored.

So, I am trying another approach: https://github.com/springfox/springfox/issues/2817#issuecomment-517753110

According to the github issue comment, I need to override Springfox json serialize class and thank god this works. Here is the code example:

import io.swagger.models.Swagger;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import springfox.documentation.spring.web.json.JacksonModuleRegistrar;
import springfox.documentation.spring.web.json.Json;
import springfox.documentation.spring.web.json.JsonSerializer;

import java.util.Arrays;
import java.util.List;

import static io.github.jhipster.config.JHipsterConstants.SPRING_PROFILE_PRODUCTION;

@Component
@Primary
public class CustomBasePathSerialize extends JsonSerializer {

    // this injection is optional, if you don't need to
    // add basePath based on active profile, remove this.
    private final Environment env;

    public CustomBasePathSerialize(List<JacksonModuleRegistrar> modules,
                                   Environment env) {
        super(modules);
        this.env = env;
    }

    @Override
    public Json toJson(Object toSerialize) {
        if (toSerialize instanceof Swagger) {
            Swagger swagger = (Swagger) toSerialize;
            String basePath = "/serviceName";
            List<String> profiles = Arrays.asList(env.getActiveProfiles());

            // OPTIONAL: you can change basePath if you have difference path 
            // on any Spring profile, for example prod:
            if (profiles.contains(SPRING_PROFILE_PRODUCTION)) {
                basePath = "/";
            }
            swagger.basePath(basePath);
        }
        return super.toJson(toSerialize);
    }
}

Upvotes: 4

veben
veben

Reputation: 22292

You can edit your SwaggerConfiguration like that:

Take care to replace the package (which need to be the one containing your REST controllers), the host, and the PATH you need

@Configuration
@EnableSwagger2
public class SwaggerConfiguration implements WebMvcConfigurer {

    public static final String PATH = "/serviceName";

    @Bean
    public Docket api() {
        final var package = "com.martin.rest";
        final var host = "localhost:8080";

        return new Docket(DocumentationType.SWAGGER_2)
                .host(host)
                .select()
                .apis(RequestHandlerSelectors.basePackage(package))
                .paths(PathSelectors.any())
                .build();
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        final var apiDocs = "/v2/api-docs";
        final var configUi = "/swagger-resources/configuration/ui";
        final var configSecurity = "/swagger-resources/configuration/security";
        final var resources = "/swagger-resources";

        registry.addRedirectViewController(PATH + apiDocs, apiDocs).setKeepQueryParams(true);
        registry.addRedirectViewController(PATH + resources, resources);
        registry.addRedirectViewController(PATH + configUi, configUi);
        registry.addRedirectViewController(PATH + configSecurity, configSecurity);
        registry.addRedirectViewController(PATH, "/");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(PATH + "/**").addResourceLocations("classpath:/META-INF/resources/");
    }
}

Another solution is by changing the spring-boot URL context-path:

Edit pour application.properties file:

server.servlet.context-path=/serviceName

Or if you have an application.yml file:

server:
  servlet:
    context-path: /serviceName

Warning: It will change the base path of all your web services, not only Swagger

Upvotes: 4

astafev.evgeny
astafev.evgeny

Reputation: 476

@Bean
public Docket newsApi(ServletContext servletContext) {
    return new Docket(DocumentationType.SWAGGER_2).pathProvider(new RelativePathProvider(servletContext) {
        @Override
        public String getApplicationBasePath() {
            return "/serviceName" + super.getApplicationBasePath();
        }
    }).host("proxyURL");
}

Upvotes: 16

Related Questions