En los últimos diez años, el término API REST ha levantado una gran expectación en la comunidad de desarrolladores de todo el mundo.

Pero como desarrolladores, ¿estamos utilizando las mejores herramientas y buenas prácticas para abordar desarrollos de APIs REST?

En el desarrollo de aplicaciones, con una capa frontal que acceden a servicios back, es fundamental aislar el desarrollo del API del desarrollo de los clientes (móvil, web...) que lo utilizan.

Existen lenguajes de especificación y modelado de APIs, como RAML, API Blueprint o Swagger, que nos permiten definir conjuntamente un contrato de comunicación entre el consumidor y el API y generar un prototipo para que, desde ese momento, los equipos que producen el servicio y los que lo consumen puedan trabajar en paralelo y de forma independiente.

En este post vamos a ver un ejemplo práctico de definición, prototipado y uso de este prototipo en un API REST.

Definiendo el API

Comenzamos definiendo nuestro API, en este caso concreto, supongamos un servicio que expondrá endpoints para añadir, eliminar, editar o consultar diferentes productos. Para hacer este servicio RESTful, vamos a definir los métodos POST, PUT, GET y DELETE para la entidad Product para dar soporte a la funcionalidad deseada.

Para este ejemplo vamos a utilizar Swagger 2.0 como lenguaje de definición y modelado de nuestro API. Para ello, accederemos al editor online que proporciona Swagger. Comenzamos introduciendo los datos generales de nuestra API, tales como descripción, baseURL, versión, tipo de contenido que producirá nuestra API… etc:


"swagger": "2.0",
  "info": {
     "title": "Meetup API Demo",
     "description": "Product REST Services",
     "version": "0.1.0"
  },
  "schemes": [
    "http"
],
"basePath": "/rest/1_0",
"produces": [
  "application/json"
],

Tras esto, definimos nuestro modelo de Producto y el formato de los mensajes de error que devolverán nuestros servicios:


"definitions": {
     "Product": {
       "properties": {
           "id": {
              "type": "integer",
              "description":"Product ID"
           },
           "name": {
             "type": "string",
             "description":"Product name",
             "maxLength":64
           },
           "description": {
             "type": "string",
             "description":"Product description",
             "maxLength":4
           },
           "eanCode": {
             "type": "string",
             "description":"Product EAN code"
           }
      },
      "required":["id","name"]
    },
    "Error": {
      "properties": {
        "code": {
          "type": "integer",
          "example" : "005001",
          "format": "int32",
          "description":"Error code"
        },
        "message": {
         "type": "string",
         "example": "Product not found",
         "description":"Error message"
        }
      }
    }
  }

Una vez finalizada la definición del modelo y errores que devolveremos, el siguiente paso es definir los endpoints y métodos http que nuestro API expondrá, por ejemplo, un servicio para filtrar productos por código EAN o descripción sería algo así:


"paths": {
    "/products": {
      "get": {
        "summary": "Product listing",
        "parameters": [
          {
            "name": "eanCode",
            "in": "query",
            "description": "EAN Code",
            "type": "string",
            "required": false
          },
          {
            "name": "description",
            "in": "query",
            "description": "Description",
            "type": "string",
            "required": false
          }
        ],
        "tags": [
           "products"
        ],
        "responses": {
          "200": {
            "description": "Product listing",
            "schema": {
              "$ref": "#/definitions/Product"
            }
          },
          "400": {
            "description": "Bad request",
            "schema": {
              "$ref": "#/definitions/Error"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
            "$ref": "#/definitions/Error"
            }
          },
          "403": {
            "description": "Forbidden",
            "schema": {
            "$ref": "#/definitions/Error"
            }
          },
          "404": {
            "description": "Not found",
            "schema": {
            "$ref": "#/definitions/Error"
            }
          },
          "405": {
            "description": "Method not allowed",
            "schema": {
            "$ref": "#/definitions/Error"
            }
          }
        }
      },

Como se puede ver en la preview que el editor tiene en la parte derecha, este código generaría el siguiente endpoint:

apirest2

Una vez terminamos de definir los endpoints con sus parámetros de entrada, respuestas, etc., descargamos el fichero que hemos generado en el menú File -> Download YAML (o JSON, según prefieras) a nuestro disco:

apirest3

Prototipando el API

Ya con el fichero de definición (YAML o JSON) en nuestro disco duro, podemos pasar a prototipar estos endpoints. En este ejemplo he utilizado una herramienta online que permite el prototipado a partir de diferentes formatos de entrada (JSON, YAML, Apiary, WSDL… etc.):

apirest

Tras elegir el formato de entrada, seleccionamos el fichero que nos hemos descargado en el paso anterior y lo cargamos, lo que nos generará los siguientes endpoints ya prototipados y disponibles para ser usados:

apirest5

Esta herramienta, además de permitirnos prototipar nuestra API con un solo clic, ofrece la posibilidad de poder cambiar el comportamiento de nuestros servicios para devolver una respuesta customizada:

apirest6

Como vemos en la imagen, podemos definir el comportamiento de la respuesta para que devuelva un código 200 y el siguiente JSON de salida:


[{
   "id": 0,
   "name": "Product name",
   "description": "Product description",
   "eanCode": "EAN code"
}, {
   "id": 1,
   "name": "Product name",
   "description": "Product description",
   "eanCode": "EAN code"
}]

Utilizando el prototipo

Una vez hemos conseguido prototipar estos servicios, con cualquier cliente REST (en este ejemplo he elegido Postman) podemos acceder a ellos y comprobar que, efectivamente, se encuentran disponibles para ser utilizados.

apirest7

¡Esto es todo! Ya tenemos nuestra API definida, prototipada y lista para ser utilizada y desarrollada. Ahora es tu turno, ¿te animas a probar esta forma de desarrollar APIs REST y contarnos tu experiencia? Si encuentras alguna otra herramienta que pueda ser de utilidad, estaremos encantados de que la compartas con nosotros.

¿Necesitas más?

Además, puedes seguir profundizando en el tema con este post en el que te contamos cómo ha sido nuestra experiencia montando un API-Rest totalmente con arquitectura ServerLess. Y también puedes continuar aprendiendo sobre APIs en nuestra sección dedicada a esta categoría.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete