Tutorial de Swagger UI y publicación de documentación
Swagger UI es una herramienta de visualización de documentación de API basada en la especificación OpenAPI (anteriormente especificación Swagger), que convierte documentos de especificación de API en una interfaz de documentación de API interactiva.
A través de Swagger UI, desarrolladores y usuarios pueden:
- Ver información detallada de la API
- Probar las solicitudes de API directamente en la interfaz
- Ver ejemplos de solicitudes y respuestas
- Conocer las funciones y parámetros de los diferentes endpoints de API
Ventajas de Swagger UI
- Visualización: Proporciona una interfaz de documentación de API clara e intuitiva
- Interactividad: Admite pruebas de API en línea, sin necesidad de herramientas adicionales
- Actualización en tiempo real: Tras los cambios de código, la documentación se actualiza automáticamente
- Estandarización: Basado en la especificación OpenAPI, mantiene la consistencia
- Compatibilidad con múltiples lenguajes: Adecuado para varios lenguajes de programación y frameworks
Integración de Swagger UI
1. Integración en proyectos Spring Boot
Agregar dependencias
Enpom.xmlAgregue las siguientes dependencias:
Ejemplo
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<!-- Springfox Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
O use SpringDoc OpenAPI:
Ejemplo
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.14</version>
</dependency>
Configurar Swagger
Ejemplo
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.controller"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Documentación de API")
.description("Descripción detallada de la API")
.version("1.0.0")
.contact(new Contact("Equipo de desarrollo", "https://example.com", "[email protected]"))
.build();
}
}
Para SpringDoc OpenAPI:
Ejemplo
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.Contact;
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Documentación de API")
.version("1.0.0")
.description("Descripción detallada de la API")
.contact(new Contact()
.name("Equipo de desarrollo")
.email("[email protected]")
.url("https://example.com")));
}
@Bean
public GroupedOpenApi publicApi() {
return GroupedOpenApi.builder()
.group("public-apis")
.pathsToMatch("/api/**")
.build();
}
}
2. Integración en proyectos Node.js Express
Instalar dependencias
npm install swagger-jsdoc swagger-ui-express --save
Configurar Swagger
Ejemplo
const swaggerJsDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');
const app = express();
// Configuración de Swagger
const swaggerOptions = {
definition: {
openapi: '3.0.0',
info: {
title: 'Documentación de API',
version: '1.0.0',
description: 'Descripción detallada de la API',
contact: {
name: 'Equipo de desarrollo',
email: '[email protected]',
url: 'https://example.com'
}
},
servers: [
{
url: 'http://localhost:3000',
description: 'Servidor de desarrollo'
}
]
},
apis: ['./routes/*.js'] // Ruta del archivo de rutas de la API
};
const swaggerDocs = swaggerJsDoc(swaggerOptions);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));
// ... otras rutas y middlewares
app.listen(3000, () => {
console.log('Servidor ejecutándose en http://localhost:3000');
console.log('Documentación de API disponible en http://localhost:3000/api-docs');
});
3. Uso en proyectos Python FastAPI
FastAPI integra Swagger UI por defecto:
Ejemplo
app = FastAPI(
title="Documentación de API",
description="Descripción detallada de la API",
version="1.0.0",
contact={
"name": "Equipo de desarrollo",
"email": "[email protected]",
"url": "https://example.com",
},
)
@app.get("/")
async def root():
return {"message": "Hello World"}
Swagger UI está disponible por defecto en la ruta /docs; puede consultar la documentación visitando http://localhost:8000/docs.
Consulte el contenido detallado en:Documentación interactiva de FastAPI API
Escribir documentación de API
1. Anotaciones de documentación de API en proyectos Spring Boot
Ejemplo
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
@Api(tags = "Gestión de usuarios")
public class UserController {
@ApiOperation(value = "Obtener lista de usuarios", notes = "Obtener toda la información de los usuarios de forma paginada")
@ApiResponses({
@ApiResponse(code = 200, message = "Éxito"),
@ApiResponse(code = 400, message = "Error de parámetros de solicitud"),
@ApiResponse(code = 500, message = "Error interno del servidor")
})
@GetMapping("/")
public Page<User> getUsers(
@ApiParam(value = "Número de página", required = true) @RequestParam int page,
@ApiParam(value = "Registros por página", required = true) @RequestParam int size) {
// Lógica de negocio
return userService.getUsers(page, size);
}
@ApiOperation(value = "Obtener un solo usuario", notes = "Obtener información del usuario por ID")
@GetMapping("/{id}")
public User getUser(
@ApiParam(value = "ID de usuario", required = true) @PathVariable Long id) {
// Lógica de negocio
return userService.getUser(id);
}
@ApiOperation(value = "Crear usuario", notes = "Crear un nuevo usuario")
@PostMapping("/")
public User createUser(
@ApiParam(value = "Información del usuario", required = true) @RequestBody UserDTO userDTO) {
// Lógica de negocio
return userService.createUser(userDTO);
}
}
Para SpringDoc OpenAPI:
Ejemplo
import io.swagger.v3.oas.annotations.media.*;
import io.swagger.v3.oas.annotations.responses.*;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
@Tag(name = "Gestión de usuarios", description = "API relacionada con usuarios")
public class UserController {
@Operation(
summary = "Obtener lista de usuarios",
description = "Obtener toda la información de los usuarios de forma paginada"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Éxito"),
@ApiResponse(responseCode = "400", description = "Error de parámetros de solicitud"),
@ApiResponse(responseCode = "500", description = "Error interno del servidor")
})
@GetMapping("/")
public Page<User> getUsers(
@Parameter(description = "Número de página", required = true) @RequestParam int page,
@Parameter(description = "Registros por página", required = true) @RequestParam int size) {
// Lógica de negocio
return userService.getUsers(page, size);
}
}
2. Comentarios de documentación de API en proyectos Node.js Express
Ejemplo
* @swagger
* /api/users:
* get:
* summary: Obtener lista de usuarios
* description: Obtener toda la información de los usuarios de forma paginada
* tags: [Gestión de usuarios]
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* required: true
* description: Número de página
* - in: query
* name: size
* schema:
* type: integer
* required: true
* description: Registros por página
* responses:
* 200:
* description: Éxito
* content:
* application/json:
* schema:
* type: object
* properties:
* data:
* type: array
* items:
* $ref: '#/components/schemas/User'
* total:
* type: integer
* 400:
* description: Error de parámetros de solicitud
* 500:
* description: Error interno del servidor
*/
router.get('/users', (req, res) => {
// Lógica de negocio
});
/**
* @swagger
* components:
* schemas:
* User:
* type: object
* required:
* - name
* properties:
* id:
* type: integer
* description: ID de usuario
* name:
* type: string
* description: Nombre de usuario
* email:
* type: string
* format: email
* description: Correo electrónico del usuario
*/
3. Documentación de API en proyectos Python FastAPI
Ejemplo
from pydantic import BaseModel
from typing import List, Optional
app = FastAPI(title="API de gestión de usuarios")
class User(BaseModel):
id: int
name: str
email: str
class Config:
schema_extra = {
"example": {
"id": 1,
"name": "Zhang San",
"email": "[email protected]"
}
}
@app.get(
"/api/users/",
summary="Obtener lista de usuarios",
description="Obtener toda la información de los usuarios de forma paginada",
response_model=List[User],
tags=["Gestión de usuarios"]
)
async def get_users(
page: int = Query(..., description="Número de página", ge=1),
size: int = Query(..., description="Registros por página", ge=1, le=100)
):
# Lógica de negocio
return [
{"id": 1, "name": "Zhang San", "email": "[email protected]"},
{"id": 2, "name": "Li Si", "email": "[email protected]"}
]
@app.get(
"/api/users/{user_id}",
summary="Obtener un solo usuario",
description="Obtener información del usuario por ID",
response_model=User,
tags=["Gestión de usuarios"]
)
async def get_user(
user_id: int = Path(..., description="ID de usuario", ge=1)
):
# Lógica de negocio
return {"id": user_id, "name": "Zhang San", "email": "[email protected]"}
Personalizar Swagger UI
1. Configuración personalizada en Spring Boot
Ejemplo
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.controller"))
.paths(PathSelectors.regex("/api/.*"))
.build()
.apiInfo(apiInfo())
.useDefaultResponseMessages(false) // Deshabilitar mensaje de respuesta predeterminado
.globalResponseMessage(RequestMethod.GET, globalResponses()) // Personalizar mensaje de respuesta global
.securitySchemes(Arrays.asList(apiKey())) // Configurar autenticación de seguridad
.securityContexts(Arrays.asList(securityContext())); // Configurar contexto de seguridad
}
private List<ResponseMessage> globalResponses() {
return Arrays.asList(
new ResponseMessageBuilder().code(200).message(Éxito).build(),
new ResponseMessageBuilder().code(400).message(Error en los parámetros de la solicitud).build(),
new ResponseMessageBuilder().code(401).message(No autorizado).build(),
new ResponseMessageBuilder().code(403).message(Acceso prohibido).build(),
new ResponseMessageBuilder().code(500).message(Error interno del servidor).build()
);
}
private ApiKey apiKey() {
return new ApiKey("JWT", "Authorization", "header");
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("/api/.*"))
.build();
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(new SecurityReference("JWT", authorizationScopes));
}
2. Configuración personalizada en Express
Ejemplo
customCss: '.swagger-ui .topbar { display: none }', // CSS personalizado
customSiteTitle: Centro de documentación de API, // Título de la página
customfavIcon: "/favicon.png", // Icono personalizado
swaggerOptions: {
persistAuthorization: true, // Conservar información de autorización
docExpansion: 'none', // Plegar todas las interfaces por defecto
tagsSorter: 'alpha', // Ordenar etiquetas alfabéticamente
operationsSorter: 'alpha', // Ordenar operaciones alfabéticamente
defaultModelsExpandDepth: -1, // Ocultar modelos
filter: true, // Habilitar filtrado
}
};
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs, options));
3. Configuración personalizada en FastAPI
Ejemplo
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.staticfiles import StaticFiles
app = FastAPI(
title=Documentación de la API,
docs_url=None, # Deshabilitar la interfaz de Swagger UI predeterminada
)
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
return get_swagger_ui_html(
openapi_url=app.openapi_url,
title=app.title + - Documentación de API,
oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
swagger_js_url="/static/swagger-ui-bundle.js",
swagger_css_url="/static/swagger-ui.css",
swagger_favicon_url="/static/favicon.png",
swagger_ui_parameters={
"docExpansion": "none",
"defaultModelsExpandDepth": -1,
"filter": True,
}
)
Publicación de documentación
1. Publicación interna
Para uso interno del equipo, se puede acceder directamente a través de la interfaz Swagger UI dentro de la aplicación:
- Spring Boot:
http://your-app-host:port/swagger-ui/index.html - Express:
http://your-app-host:port/api-docs - FastAPI:
http://your-app-host:port/docs
2. Generación de documentación estática
Usar Swagger Codegen para generar documentación estática
# 安装 Swagger Codegen CLI wget https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.35/swagger-codegen-cli-3.0.35.jar -O swagger-codegen-cli.jar # 生成静态 HTML 文档 java -jar swagger-codegen-cli.jar generate -i http://your-app-host:port/v3/api-docs -l html2 -o ./api-docs
Usar Redoc para generar documentación estática
# 安装 redoc-cli npm install -g redoc-cli # 生成静态 HTML 文档 redoc-cli bundle http://your-app-host:port/v3/api-docs -o ./api-docs/index.html
3. Integración en el flujo de CI/CD
Añadir pasos de generación y publicación de documentación en el pipeline de CI/CD:
Ejemplo de pipeline de Jenkins
Ejemplo
agent any
stages {
// ... otras fases de compilación y prueba
stage('Generate API Documentation') {
steps {
sh 'java -jar swagger-codegen-cli.jar generate -i http://your-app-host:port/v3/api-docs -l html2 -o ./api-docs'
}
}
stage('Publish Documentation') {
steps {
// Publicar en el servidor de archivos estáticos Nginx
sh 'rsync -avz --delete ./api-docs/ user@doc-server:/var/www/api-docs/'
// O publicar en almacenamiento de objetos (como AWS S3)
sh 'aws s3 sync ./api-docs/ s3://your-bucket/api-docs/ --delete'
}
}
}
}
Ejemplo de flujo de trabajo de GitHub Actions
Ejemplo
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11'
- name: Build application
run: ./mvnw clean package
- name: Start application
run: |
java -jar target/your-app.jar &
sleep 30# Esperar a que la aplicación se inicie
- name: Generate API Documentation
run: |
wget -q https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.35/swagger-codegen-cli-3.0.35.jar -O swagger-codegen-cli.jar
java -jar swagger-codegen-cli.jar generate -i http://localhost:8080/v3/api-docs -l html2 -o ./api-docs
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@4.1.5
with:
branch: gh-pages
folder: api-docs
4. Uso de plataformas de gestión de documentación de API
Además de implementar por su cuenta, también puede utilizar plataformas profesionales de gestión de documentación de API:
- Swagger Hub: Proporciona servicios de diseño de API y alojamiento de documentación
- Postman: No solo permite probar API, sino también publicar documentación de API
- ReadMe.io: Proporciona gestión integral de documentación de API y portal para desarrolladores
- Stoplight: Proporciona herramientas de diseño, documentación y gobernanza de API
5. Despliegue de Swagger UI con Docker
Ejemplo
# Establecer variables de entorno
ENV SWAGGER_JSON=/swagger/openapi.json
ENV BASE_URL=/api-docs
# Copiar el archivo de especificación OpenAPI
COPY openapi.json /swagger/
# Exponer el puerto
EXPOSE 8080
# Iniciar Swagger UI
CMD ["sh", "/usr/share/nginx/docker-run.sh"]
Construir y ejecutar:
docker build -t my-swagger-ui . docker run -p 8080:8080 my-swagger-ui
Acceder: http://localhost:8080/api-docs
Mejores prácticas
1. Estándares de documentación
- Mantener la claridad y la concisión: La descripción debe ser concisa y específica
- Gestión por grupos: Utilizar etiquetas para agrupar lógicamente las API
- Proporcionar ejemplos: Proporcionar ejemplos para solicitudes y respuestas
- Manejo de errores estandarizado: Unificar el formato de respuesta de error y los códigos de estado
- Control de versiones: Indicar claramente la información de versión de la API en la documentación
2. Configuración de seguridad
- Manejo de información sensible: No exponer información sensible en la documentación
- Configuración de entorno de producción: En el entorno de producción se puede deshabilitar o restringir opcionalmente el acceso a la documentación
- Mecanismo de autenticación: Configurar la autenticación para el acceso a la documentación
Ejemplo
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.enable(!environment.acceptsProfiles(Profiles.of("prod")))
// ... otra configuración
}
3. Pruebas automatizadas
Combine documentación y pruebas para garantizar que el contenido de la documentación coincida con el comportamiento real de la API:
Ejemplo
@Test
public void validateSwaggerDocumentation() {
// Obtener el JSON de Swagger
String swaggerJson = given()
.when()
.get("/v3/api-docs")
.then()
.statusCode(200)
.extract().asString();
// Verificar la documentación de Swagger
OpenAPI openAPI = new OpenAPIParser().readContents(swaggerJson, null, null).getOpenAPI();
assertNotNull(openAPI);
// Verificar si un endpoint específico está en la documentación
assertNotNull(openAPI.getPaths().get("/api/users"));
}
Solución de problemas comunes
1. Swagger UI no se muestra o falla al cargar
- Verificar la versión de las dependencias: Asegurarse de que las versiones de las dependencias sean compatibles
- Verificar la clase de configuración: Asegurarse de que la clase de configuración esté correctamente registrada
- Verificar el mapeo de rutas: Asegurarse de que el mapeo de rutas sea correcto
- Verificar la configuración de CORS: Si hay acceso entre dominios, asegurarse de que la configuración de CORS sea correcta
2. Información de interfaz incompleta
- Verificar las anotaciones: Asegurarse de que todas las anotaciones necesarias se hayan añadido
- Verificar la ruta de escaneo de paquetes: Asegurarse de que la ruta de escaneo incluya todos los controladores
- Verificar las clases de modelo: Asegurarse de que las clases de modelo tengan la descripción correcta
3. Problemas de seguridad en el entorno de producción
Configurar el entorno de producción para deshabilitar o proteger la documentación:
# application-prod.properties springdoc.swagger-ui.enabled=false springdoc.api-docs.enabled=false
O proteger con autenticación básica:
Ejemplo
@Profile("prod")
public class SwaggerSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers("/swagger-ui/**", "/v3/api-docs/**")
.and()
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
Resumen
Swagger UI es una potente herramienta de documentación de API. Con una configuración y uso correctos, puede mejorar en gran medida la usabilidad de la API y la eficiencia del desarrollo. Este tutorial presenta los conceptos básicos de Swagger UI, métodos de integración, redacción de documentación, configuración personalizada, publicación de documentación y mejores prácticas, con la esperanza de que sea útil para su trabajo de documentación de API.
Recuerde los siguientes puntos clave:
- Elija el método de integración de Swagger adecuado para la pila tecnológica del proyecto
- Diseñe y escriba cuidadosamente las anotaciones o comentarios de la documentación de API
- Personalice la interfaz de Swagger UI según sea necesario
- Seleccione el método adecuado de publicación de documentación
- Siga las mejores prácticas para garantizar la precisión y seguridad de la documentación
Mediante un uso adecuado de Swagger UI, puede proporcionar a su API una documentación profesional e interactiva, facilitando la comprensión y el uso de su API.
Otras extensiones