saverioriotto.it

Integrazione di Swagger 2.0 in un’applicazione REST con Spring Boot

Oggi la maggior parte delle applicazioni web si stanno sviluppando come moduli separati (back-end/front-end). In questo tipo di scenario, dovremmo avere una documentazione adeguata con informazioni, leggibili e facili da usare. In questo tutorial, esamineremo Swagger 2.0 per il servizio REST Spring Boot utilizzando l'implementazione di Springfox.

Integrazione di Swagger 2.0 in un’applicazione REST con Spring Boot

Per descrivere l'implementazione di Swagger, utilizziamo l'applicazione CRUD implementata in precedenti tutorial utilizzando Spring Boot (vedi: API REST Spring Boot con autenticazione JWT e Ruoli). In questo tutorial spiegherò solo l'integrazione di Swagger. Prima di iniziare l’integrazione vediamo cos’è Swagger ed a cosa serve.

Cos’è Swagger

Swagger è una libreria Open Source che ci permette di documentare gli endpoint delle nostre API REST ed è utilizzabile in moltissimi linguaggi quali Node.js, Spring Java e Python.

In particolare Swagger implementa la Specifica OpenAPI (conosciuta originariamente come la Specifica Swagger) la quale è una specifica per file di interfaccia leggibili dalle macchine per descrivere, produrre, consumare e visualizzare servizi web RESTful.

Il framework Swagger comprende una serie di tool Open Source:

Swagger Editor: un editor che ci permette di descrivere le nostre API REST in linguaggio JSON o YAML all’interno del nostro browser ed avere una anteprima real-time della documentazione prodotta;

Swagger UI: una collezione di asset HTML, CSS e Javascript che viene generata automaticamente dalla documentazione della nostra API (che deve essere conforme allo standard OpenAPI);

Swagger Codegen: genera automaticamente stub per la parte client e server a partire dalla specifica OpenAPI.

Integrazione delle dipendenze

Per poter procedere all'integrazione dobbiamo aggiungere le dipendenze Swagger 2.0 relative a Springfox nel pom.xml del nostro progetto.

<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger2</artifactId>
  <version>2.8.0</version>
</dependency>
<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger-ui</artifactId>
  <version>2.8.0</version>
</dependency>

Configurazione di Swagger 2.0

Prima di passare alla configurazione, dobbiamo creare una classe chiamata SwaggerConfiguration.java (puoi usare anche un nome diverso ). Nel caso del nostro tutorial l’ho inserita all'interno del package .swagger. Di seguito l'implementazione e i relativi commenti passo-passo:

@Configuration
@EnableSwagger2 //Dobbiamo abilitare Swagger 2.0 in modo esplicito. Quindi, dobbiamo usare @EnableSwagger2 sulla nostra classe di configurazione
public class SwaggerConfiguration extends WebMvcConfigurationSupport {

    public static final String DEFAULT_GROUP_NAME = "global";
    public static final String AUTHORIZATION_HEADER = "Authorization";

    //Indichiamo l'elenco dei paths che sono protetti da JWT
    public static final String[] DEFAULT_INCLUDE_PATTERN = new String[] {
            "/api/test/admin",
            "/api/test/mod",
            "/api/test/utente",
            "/api/auth/registrazione",
            "/api/libro.*" };
   
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry
                .addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry
                .addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    @Bean
    public Docket productApi() { //La configurazione di Swagger è principalmente incentrata sul bean Docket 
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.saverioriotto.springbootresttutorial")) //package da dove far riferimento per abilitare le API esposte.
                .paths(PathSelectors.any()) //L'utilizzo di any(), renderà disponibile la documentazione per l'intera API tramite Swagger.
                .build()
                .groupName(DEFAULT_GROUP_NAME) //Nome del gruppo di API
                .securityContexts(securityContext()) //Contesto di sicurezza delle API che racchiude gli endpoint protetti.
                .securitySchemes(Lists.newArrayList(apiKey())) //Tipo di chiave utilizzata per le nostre API
                .apiInfo(apiInfo()); //Permette di aggiungere informazioni dettagliate alla nostra documentazione.
    }

    private ApiInfo apiInfo() {
        return new ApiInfo(
                "API REST Springboot-Swagger2",
                "Esempio integrazione di Swagger v2 con API REST Springboot\n\n" +
                        "Credenziali di accesso demo: \n\n" +
                        "Username: test\n" +
                        "Password: test\n",
                "1.0",
                "Terms of service",
                new Contact("Saverio Riotto", "https://blog.saverioriotto.it", "[email protected]"),
                "License of API", "https://blog.saverioriotto.it", Collections.emptyList());
    }

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

    private List securityContext() {

        List securityContext = new ArrayList<>();

        for (String context : DEFAULT_INCLUDE_PATTERN){
            securityContext.add(SecurityContext.builder()
                    .securityReferences(defaultAuth())
                    .forPaths(PathSelectors.regex(context))
                    .build());
        }

        return securityContext;
    }

    List defaultAuth() {
        AuthorizationScope authorizationScope
                = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Lists.newArrayList(
                new SecurityReference("Bearer", authorizationScopes));
    }


Permessi di accesso a Swagger

Nel caso del nostro progetto di partenza, essendo che le API sono protette da JWT, dobbiamo aggiungere i permessi per l’accesso pubblico alle risorse di Swagger. Per fare questo dobbiamo aggiungere alcune informazione sulla classe WebSecurityConfig.java:

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
       //Lista delle risorse Swagger che devono essere raggiungibili senza autenticazione
       String[] SWAGGER_URL_PATHS = new String[] {
               "/swagger-ui.html**",
               "/swagger-resources/**",
               "/v2/api-docs**",
               "/webjars/**"};

       http.cors().and().csrf().disable()
               // .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests().antMatchers("/api/auth/**").permitAll()
                .antMatchers("/api/test/**").permitAll()
                .antMatchers("/api/libro/**").permitAll()
                .antMatchers(SWAGGER_URL_PATHS).permitAll() //Settaggio delle risorse di cui sopra.
               .anyRequest().authenticated();
        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

Avvio dell'applicazione con supporto Swagger 2.0

Abbiamo completato la configurazione di base a livello di codice. Ora possiamo eseguire questo progetto come applicazione Spring Boot. Una volta avviata l'applicazione, possiamo visitare il seguente URL nel browser:

http://localhost:8080/swagger-ui.html

A questo punto dovremmo vedere l'interfaccia di Swagger 2.0 che permette la gestione delle API con relative informazioni.

swagger-ui.PNG (50 KB)

API-DOCS Swagger

La maggior parte delle volte abbiamo bisogno di usare Swagger API-DOCS. È una risposta JSON con diverse coppie chiave-valore. Per ottenere ciò possiamo anche quì visitare il seguente URL nel browser:

http://localhost:8080/v2/api-docs?group=global

Un punto importante è che dovremmo usare un parametro chiamato "group" e questo valore è definito in "groupName" all'interno del metodo getDocket() nella classe SwaggerConfiguration.

swagger-json.PNG (59 KB)

Conclusioni

In questo articolo, abbiamo configurato Swagger 2.0 per generare documentazione di un'API REST di Spring. La lista completa dei parametri e tutto quello di cui hai bisogno per personalizzare la tua configurazione Swagger2, li trovi alla pagina Springfox Docs.

Il codice sorgente completo del tutorial lo trovi su Github.




Commenti
* Obbligatorio