Documentar una API, por mucho detalles que incluyas, siempre será insuficiente si no incluyes ejemplos de uso. Y si además son reales, que puedes ejecutar para obtener resultados, sus campos son configurables y todos los detalles técnicos se encuentran a la vista (sin magia), el equipo de desarrollo te hará la ola.
Quienes hemos trabajado con Postman, o softwares similares, sabemos que es una herramienta muy útil para probar APIs. Pero también para dejar ejemplos funcionales de su uso. No obstante, Postman posee limitaciones a largo plazo:
- Si quieres compartir tus ejemplos con muchos compañeros de trabajo, tendrás que pagar una suscripción.
- Tus ejemplos, o documentación interactiva, esta atada a un software de terceros.
- No es fiable a largo plazo, ya que con las diferentes versiones de Postman, los ejemplos pueden dejar de funcionar.
Por ello recomiendo usar algún lenguaje de script, que sea un estándar en la industria y sea fácil de ejecutar en cualquier sistema operativo. Bash con cURL son una combinación explosiva. Y si además añades jq
para formatear la salida JSON, tendrás una herramienta similar a Postman, pero sin sus desventajas.
Por lo tanto, los requisitos mínimos será tener instalado bash
(suele ya estar por defecto en entornos de desarrollo), curl
y jq
.
Get
El siguiente ejemplo es un script en Bash que hace una petición GET.
Los parámetros son en la URL, por lo que se deben codificar. Para ello se ha creado una función urlencode
.
COMPANY_NAME
: Nombre de la empresa.APP_NAME
: Nombre de la aplicación.EMAIL
: Email del usuario.
#!/usr/bin/env bash
set -o errexit
urlencode() {
# urlencode <string>
old_lc_collate=$LC_COLLATE
LC_COLLATE=C
local length="${#1}"
for (( i = 0; i < length; i++ )); do
local c="${1:$i:1}"
case $c in
[a-zA-Z0-9.~_-]) printf '%s' "$c" ;;
*) printf '%%%02X' "'$c" ;;
esac
done
LC_COLLATE=$old_lc_collate
}
# Parameters
COMPANY_NAME=$(urlencode "Foo")
APP_NAME=$(urlencode "Boo")
EMAIL="foo@example.com"
# Endpoint
METHOD='GET'
ENDPOINT="company/${COMPANY_NAME}/app/${APP_NAME}/users/${EMAIL}"
# Request
curl -s -L -X $METHOD -G \
"http://localhost:8000/api/v1/${ENDPOINT}" \
| jq .
Se ha separado el método y el endpoint en variables para que sea más fácil de modificar.
Por último, se ha añadido jq .
para formatear la salida JSON.
Post
Se pretende enviar un JSON en el cuerpo de la petición. Para ello se ha creado una variable BODY
con el JSON a enviar. Se incluye la cabecera Content-Type: application/json
para indicar que el cuerpo de la petición es un JSON.
#!/usr/bin/env bash
# exit on error
set -o errexit
urlencode() {
# urlencode <string>
old_lc_collate=$LC_COLLATE
LC_COLLATE=C
local length="${#1}"
for (( i = 0; i < length; i++ )); do
local c="${1:$i:1}"
case $c in
[a-zA-Z0-9.~_-]) printf '%s' "$c" ;;
*) printf '%%%02X' "'$c" ;;
esac
done
LC_COLLATE=$old_lc_collate
}
# Parameters
COMPANY_NAME=$(urlencode "Foo")
APP_NAME=$(urlencode "Boo")
BODY='{
"email": foo@example.com",
"password": "password",
"firstName": "Foo",
"lastName": "Boo",
"isEnabled": true,
"role": "admin"
}'
# Endpoint
METHOD='POST'
ENDPOINT="company/${COMPANY_NAME}/app/${APP_NAME}/users/"
# Request
curl -s -L -X $METHOD \
"http://localhost:8000/api/v1/${ENDPOINT}" \
--header "Content-Type: application/json" \
--data "$BODY" \
| jq .
El resto del script es similar al anterior.
Mostrando el tiempo de respuesta
Es importante medir el rendimiento de la API, y si puede ser en milisegundos mucho mejor. Para ello podemos incluir una pequeña actualización en el script.
Al inicio guardamos el tiempo actual.
start=$(date +%s%3N)
Y al final del script, volvemos a guardar el tiempo actual y restamos el tiempo inicial.
end=$(date +%s%3N) # Record end time in milliseconds
execution_time=$((end - start)) # Calculate the difference in milliseconds
echo "Execution time: ${execution_time} milliseconds"
Debajo del JSON aparecerá el tiempo de respuesta en milisegundos.
Todo unificado al ejemplo GET quedaría así:
#!/usr/bin/env bash
set -o errexit
start=$(date +%s%3N)
urlencode() {
# urlencode <string>
old_lc_collate=$LC_COLLATE
LC_COLLATE=C
local length="${#1}"
for (( i = 0; i < length; i++ )); do
local c="${1:$i:1}"
case $c in
[a-zA-Z0-9.~_-]) printf '%s' "$c" ;;
*) printf '%%%02X' "'$c" ;;
esac
done
LC_COLLATE=$old_lc_collate
}
# Parameters
COMPANY_NAME=$(urlencode "Foo")
APP_NAME=$(urlencode "Boo")
EMAIL="foo@example.com"
# Endpoint
METHOD='GET'
ENDPOINT="company/${COMPANY_NAME}/app/${APP_NAME}/users/${EMAIL}"
# Request
curl -s -L -X $METHOD -G \
"http://localhost:8000/api/v1/${ENDPOINT}" \
| jq .
end=$(date +%s%3N) # Record end time in milliseconds
execution_time=$((end - start)) # Calculate the difference in milliseconds
echo "Execution time: ${execution_time} milliseconds"
Apuntes finales
El objetivo no es crear una batería de tests para la API, ya hay lenguajes y librerías mucho más potentes para ello (como pytest
con requests
en Python). Nos centraremos en tener ejemplos funcionales, fáciles de compartir (pueden estar en el mismo repositorio de la API), resistentes a lo largo del tiempo y libres de software de terceros. Y nada mejor para ello que usar herramientas Unix.
Puedes llevar elementos repetitivos a ficheros externos que puedes invocar con source
. O incluso crear funciones para cada petición, que reciban los parámetros necesarios. Lo dejo a tu elección. Pero recuerda, la simplicidad es la clave.
Por último, documentar acompañando la API con ejemplos autogenerados (como OpenAPI o Swagger) es una buena práctica. Sin embargo, te estas dejando atrapar por un framework. Recuerda, divide y vencerás.
Por si te interesa, el artículo tiene una continuación: Ejemplo en Markdown de como documentar una API
{{ comments.length }} comentarios