8
votes

I'm trying to change base access url for API documentation. The url is "http://localhost:8080/swagger-ui.html". I want to get something like "http://localhost:8080/myapi/swagger-ui.html".

I use Springfox 2.8.0 Swagger, Java 8, Spring Boot 2.0 The swagger configuration is:

@Configuration
@EnableSwagger2
public class SwaggerConfiguration {

    @Bean
    public Docket api(ServletContext servletContext) {
        return new Docket(DocumentationType.SWAGGER_2)
                .pathProvider(new RelativePathProvider(servletContext) {
                    @Override
                    public String getApplicationBasePath() {
                        return "/myapi";
                    }
                })
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(Predicates.not(PathSelectors.regex("/error")))
                .build()
                .useDefaultResponseMessages(false);
    }
}

Custom path provider had to help, but I still get access to api documentation by using url "http://localhost:8080/swagger-ui.html". If I use url "http://localhost:8080/myapi/swagger-ui.html", I get 404 error. Look at the screenshot below.

enter image description here

5
did you ever manage to fix this issue, i am having the same problemmh377

5 Answers

3
votes

For those who use Springfox Swagger 3.0.0

Here's the working configuration for changing base url for docs:

springfox:
  documentation:
    swaggerUi:
      baseUrl: /documentation
    openApi:
      v3:
        path: /documentation/v3/api-docs
    swagger:
      v2:
        path: /documentation/v2/api-docs
2
votes

https://github.com/springfox/springfox/issues/2250 - as they said you can configure redirect to your own path

2
votes

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 = "/myapi";

    @Bean
    public Docket api() {
        final var package = "com.julia.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=/myapi

Or if you have an application.yml file:

server:
  servlet:
    context-path: /myapi

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

1
votes

I also have faced this problem and tried many possible resolutions, and nothings didn't help really. In my case, I can't use any resource redirect as swagger must be accessible as locally as on google cloud by match path /api-docs/**. and on google cloud any resource redirection will be denied in my case. All resources must be loading also from this path

here is my solution:
springfox-swagger2 and springfox-swagger-ui of version 2.9.2

@EnableSwagger2
@Configuration
public class SwaggerCommonConfig implements WebMvcConfigurer {
    public static final String PATH = "/api-docs";

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addRedirectViewController(PATH, "/");
    }

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

and as springfox don't have any possibilities to do it by another way, in my case, we just will create simple controller that will be translating resource requests from our custom path to standard springfox. (it's not very elegant part but as it is :))

@RestController
@RequestMapping(SwaggerGatewayCommonConfig.PATH)
@RequiredArgsConstructor
public class SwaggerController {
    private final RestTemplate restTemplate;
    private final static String V2_API_DOCS = "/v2/api-docs";
    private final static String SWAGGER_RESOURCES_CONFIGURATION_UI = "/swagger-resources/configuration/ui";
    private final static String SWAGGER_RESOURCES_CONFIGURATION_SECURITY = "/swagger-resources/configuration/security";
    private final static String SWAGGER_RESOURCES = "/swagger-resources";
    private final static Pattern pattern = Pattern.compile("http[s]*://([^/]+)", Pattern.CASE_INSENSITIVE);

    @Value("${server.port}")
    private String port;

    @GetMapping(V2_API_DOCS)
    @SuppressWarnings("unchecked")
    public Map<String, Object> getV2ApiDocs(HttpServletRequest request) {
        Matcher matcher = pattern.matcher(request.getRequestURL().toString());
        matcher.find();

        Map<String, Object> resp = (Map<String, Object>) restTemplate.getForObject(toLocalSwaggerUrl(V2_API_DOCS), Map.class);
        //we have to replace standard host, to requested host. as swagger UI make api requests from this host
        resp.put("host", matcher.group(1));

        return resp;
    }

    @GetMapping(SWAGGER_RESOURCES_CONFIGURATION_UI)
    public Object getSwaggerResourcesConfigurationUi() {
        return restTemplate.getForObject(toLocalSwaggerUrl(SWAGGER_RESOURCES_CONFIGURATION_UI), Object.class);
    }

    @GetMapping(SWAGGER_RESOURCES_CONFIGURATION_SECURITY)
    public Object getSwaggerResourcesConfigurationSecurity() {
        return restTemplate.getForObject(toLocalSwaggerUrl(SWAGGER_RESOURCES_CONFIGURATION_SECURITY), Object.class);
    }

    @GetMapping(SWAGGER_RESOURCES)
    public Object getSwaggerResources() {
        return restTemplate.getForObject(toLocalSwaggerUrl(SWAGGER_RESOURCES), Object.class);
    }

    private String toLocalSwaggerUrl(String path) {
        return "http://localhost:" + port + path;
    }
}

I hope it will save time to somebody faced it also =) Good luck

0
votes

Swagger base access url is constructed from your base application path.So if you change your base application path , you will get the desired behavior.But also all your apis will be changed to that path. You can find how to change it here How to set base url for rest in spring boot? .

What you did was too change how swagger call other apis from your application, not to change his base url. There are some tricks to change the swagger base url without changing application base path (moving manually all swagger resources), but i do not recommend that.