MXX
MXX

Reputation: 588

Cannot see swagger doc and swagger-ui.html in spring boot project, 404 error

I tried to see swagger doc on "localhost:8080/v2/api-docs" and "localhost:8080/swagger-ui.html", but still failed. The project has been successfully built and run on "localhost:8080/v2/apis/***".

After run the app on local, the active profile was local.

enter image description here

SwaggerConfig

@Profile({"local", "local_kuh", "develop"})
@Configuration
@EnableSwagger2
public class SwaggerConfig {

    private ApiInfo apiInfo() {

        String description = "[DESCRIPTION]";

        return new ApiInfoBuilder()
                .title("Rest API Server")
                .description(description)
                .build();
    }

    private ApiKey apiKey() {
        return new ApiKey("apiKey", "Authorization", "header");
    }

    @Bean
    public SecurityConfiguration security() {
    return SecurityConfigurationBuilder.builder().scopeSeparator(",")
        .additionalQueryStringParams(null)
        .useBasicAuthenticationWithAccessCodeGrant(false).build();
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder().securityReferences(defaultAuth())
        .forPaths(PathSelectors.any()).build();
    }

    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Collections.singletonList(new SecurityReference("apiKey", authorizationScopes));
    }

    @Bean
    public Docket commonApi() {
        ParameterBuilder aParameterBuilder = new ParameterBuilder();
        aParameterBuilder.name("Authorization")
                .description("Access Tocken")
                .modelRef(new ModelRef("string"))
                .parameterType("header")
                .required(false)
                .build();

        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("v2")
                .apiInfo(this.apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("net.infobank.moyamo.controllers"))
                .build()
                .securitySchemes(Collections.singletonList(apiKey()))
                .securityContexts(Collections.singletonList(securityContext()))
                .useDefaultResponseMessages(false);
    }

}
...
        <!-- springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

        <!-- springfox-swager-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
...
dependencies {
...
    implementation 'io.springfox:springfox-swagger-ui:2.9.2'
    implementation 'io.springfox:springfox-swagger2:2.9.2'
...
}

WebSecurityConfig

@Configuration
@AllArgsConstructor
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final BCryptPasswordEncoder bCryptPasswordEncoder;
    private final DataSource datasource;
    private final RestAuthenticationEntryPoint restAuthenticationEntryPoint;
    private final TokenAuthorizationFilter tokenAuthorizationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)

            .and()
            .addFilterBefore(tokenAuthorizationFilter, UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
            .antMatchers("/v2/auth/**").permitAll()
            .antMatchers("/v2/notices/**").permitAll()
            .antMatchers("/v2/policies/**").permitAll()
            .antMatchers(HttpMethod.OPTIONS, "/v1/gambles", "/v1/gambles/**", "/v2/rankings").permitAll()
            .antMatchers(HttpMethod.GET, "/v2/rankings").permitAll()

            .antMatchers("/postings").permitAll()
            .antMatchers("/static/**").permitAll()
            .antMatchers("/docs/**").permitAll()
            .antMatchers("/actuator/**").permitAll()
            .antMatchers("/api/**").permitAll()
            .antMatchers("/v2/shops").permitAll()

            .antMatchers("/v2/api-docs", "/v2/logs", "/swagger-resources/**", "/swagger-ui.html", "/webjars/**", "/swagger/**").permitAll() //swagger
            .antMatchers("/**").authenticated()
            .anyRequest().authenticated()

            .and()
            .exceptionHandling()
            .authenticationEntryPoint(restAuthenticationEntryPoint);

    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(datasource).passwordEncoder(bCryptPasswordEncoder);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

I thought everything was all set for swagger doc/ui. But still get 404 error.

enter image description here

enter image description here

enter image description here

Also I can't see swagger-ui.html.

enter image description here

I think swagger should work without authentication on local profile. But both tries with authorization or not, don't work.

How can I fix this issue? Thank you all, in advance.

Upvotes: 1

Views: 1982

Answers (2)

MXX
MXX

Reputation: 588

I changed the SwaggerConfig.java like below by adding some codes at last.

SwaggerConfig.java

package com.msquare.flabook.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.Collections;
import java.util.List;

@Profile({"local", "local_kuh", "develop"})
@Configuration
@EnableSwagger2
public class SwaggerConfig {

    private ApiInfo apiInfo() {

        String description = "";

        return new ApiInfoBuilder()
                .title("Rest API Server")
                .description(description)
                .build();
    }

    private ApiKey apiKey() {
        return new ApiKey("apiKey", "Authorization", "header");
    }

    @Bean
    public SecurityConfiguration security() {
        return SecurityConfigurationBuilder.builder().scopeSeparator(",")
                .additionalQueryStringParams(null)
                .useBasicAuthenticationWithAccessCodeGrant(false).build();
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder().securityReferences(defaultAuth())
                .forPaths(PathSelectors.any()).build();
    }

    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Collections.singletonList(new SecurityReference("apiKey", authorizationScopes));
    }

    @Bean
    public Docket commonApi() {
        ParameterBuilder aParameterBuilder = new ParameterBuilder();
        aParameterBuilder.name("Authorization")
                .description("Access Tocken")
                .modelRef(new ModelRef("string"))
                .parameterType("header")
                .required(false)
                .build();

        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("v2")
                .apiInfo(this.apiInfo())
                //.tags(new Tag("API", "v2"))
                //.globalOperationParameters(aParameters)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.msquare.flabook.controllers"))
                //.paths(PathSelectors.ant("/v2/auth/**"))

                .build()
                .securitySchemes(Collections.singletonList(apiKey()))
                .securityContexts(Collections.singletonList(securityContext()))
                .useDefaultResponseMessages(false);
    }
/// newly added code
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }

}

And I commented some codes for swagger. "/**" path was invoked before the swagger routing.

CorsController.java

package com.msquare.flabook.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

@RestController
public class CorsController {
    protected void withCors(ServletResponse res) {
        HttpServletResponse response = (HttpServletResponse) res;

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, Authorization");
    }

    @RequestMapping(method = RequestMethod.OPTIONS, path = "")
    public String doOptionsMain() {
        return "";
    }

    // comment for swagger
//    @RequestMapping(method = RequestMethod.OPTIONS, path = "/**")
//    public String doOptions() {
//        return "";
//    }
}

Upvotes: 1

viking
viking

Reputation: 399

Actually now I'm using openapi, but I remember configuration bean for springfox

@Configuration
@EnableSwagger2
public class SwaggerConfiguration {

    @Bean
    public Docket apiDefault() {
        return docketGeneric("default", "/api/.*");
    }

    private Docket docketGeneric(String groupName, String pathsRegex) {
        return new Docket(DocumentationType.SWAGGER_2)
                .useDefaultResponseMessages(false)
                .protocols(Collections.singleton("http"))
                .groupName(groupName)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.regex(pathsRegex))
                .build()
                .forCodeGeneration(true);
    }

Upvotes: 1

Related Questions