Desarrollo de un Restful API

Diego Guevara
5 min readOct 13, 2016

--

Un api es una interfaz que permite exponer de forma sencilla y modular los recursos de una aplicación para ser reutilizados. En resumen es una interfaz diseñada por desarrolladores para desarrolladores de allí que es tan importante ser claros, usar estándares y documentar.

Esta guía pretende ofrecer algunas directrices y recomendaciones a tener en cuenta en la creación de un api para hacerlo más claros y de fácil integración, independientemente del lenguaje o herramientas de programación.

Nombre de cada recurso

El nombre de cada recurso debe ser entendible y fácil de identificar ya que este debe indicar en una palabra todo lo que nos ofrece.

Al elegir el nombre del recurso es importante preferir nombres sencillos y concretos preferiblemente que definan la entidad.

Por esta razón es una buena practica usar sustantivos en plural en lugar de verbos.

Ejemplo:

El servicio Restful para administrar los usuarios en nuestra aplicación será:

http://app.com/api/v1/users

El servicio Restful para administrar los productos en nuestra aplicación será:

http://app.com/api/v1/products

Métodos CRUD

Por lo genenral necesitamos poder crear, actualizar, consultar y obtener un listado de datos.

Sin Restful tendríamos que crear una ruta para cada método:

http://app.com/api/v1/createUsers
http://app.com/api/v1/getUsers
http://app.com/api/v1/updateUsers
http://app.com/api/v1/deleteUsers

Con Restful, reducimos esto a una sola URL,usando los métodos CRUD de HTTP para cada acción:

http://app.com/api/v1/users

En resumen, solo tendíamos una URL para todas las acciones y la forma de diferenciar cada acción es medinate el método HTTP utilizado.

Ejemplo:

Consultar listado de usuarios:

Método GET

GET: http://app.com/api/v1/users

Consultar detalle de un usuario por ID, en donde 123 es el ID del usuario:

Método GET

GET: http://app.com/api/v1/users/123

Crear un nuevo usuario enviando todo el formulario:

Método POST

POST: http://app.com/api/v1/users

Actualizar el usuario enviando el formulario, en donde 123 es el ID del usuario:

Método PUT

PUT: http://app.com/api/v1/users/123

Eliminar un usuario en donde 123 es el ID del usuario:

Método DELETE

DELETE: http://app.com/api/v1/users/123

Relaciones y Filtros

Es muy fácil confundir una relación con un filtro.

Básicamente una relación se da cuando requerimos una consulta de un recurso que depende de otro recurso.

Un filtro nos permite obtener la información limitada por uno o más criterios como por ejemplo el texto de una búsqueda, o un rango de fechas.

Relación

Usamos una relación en un recurso del api cuando la relación es obligatoria, es decir que no se puede obtener la información sin diferenciarla por la relación.

Un ejemplo sería el listado de capítulos de un libro, en este caso no podemos obtener el listado de capítulos sin identificar el libro, y no sería muy útil obtener un listado de todos los capítulos sin identificar el libro.

http://app.com/api/v1/books/:id/chapters

Como buena práctica se recomienda no usar más de 2 niveles en la URL de un recurso del api ya que cada nivel adiciona complejidad al momento de entender y documentar un api. Cuando requerimos más de 2 niveles se recomienda usar filtros.

Filtros

Los filtros por su parte son opcionales, y permiten limitar la información por criterios más amplios y combinables.

Un ejemplo de esta forma de consulta sería una relación entre estudiantes y cursos en donde por separado podríamos obtener la lista de estudiantes y la lista de cursos.

Si necesitamos consultar los estudiantes registrados en un curso y que están activos podríamos usar algo así:

http://app.com/api/v1/students/?course=10&status=active

Otro ejemplo podría ser obtener un listado de estudiantes matriculados en un rango de fechas:

http://app.com/api/v1/students/?fecha1=20150101&fecha2=20150501

Adicionalmente se puede utilizar filtros para indicar la cantidad de registros a obtener. Por ejemplo en una consulta paginada utilizaríamos los parámetros offset para indicar el máximo de registros y skip para indicar el registro inicial.

http://app.com/api/v1/students/?course=10&status=active&offset=20&skip=10

Versiones del api

Un api es una aplicación como tal, incluso independiente del Frontend, puede ir creciendo y mejorando, de forma independiente y por esto es importante garantizar la compatibilidad con los clientes que consumen los servicios.

La mejor forma de garantizar esto, es utilizando un estándar en la URL que nos indique la versión del api y así poder tener claro que recibe y que responde.

Ejemplo:

http://api.app.com/v1/users
http://api.app.com/v2/users

Respuesta JSON

Aunque podríamos utilizar como respuesta XML o incluso texto plano, es muy recomendado utilizar objetos JSON, ya que es mas liviano y práctico para el procesamiento en el cliente.

Es importante evitar enviar la respuesta json en string, se debe siempre garantizar que el ContentType sea application/json y que la codificación de la respuesta esté en UTF-8, así garantizamos que el fontend va a entender la respuesta y que no vamos a tener problemas con tildes y caracteres especiales.

Otra recomendación importante es siempre usar minúsculas para los nombres de las propiedades del objeto JSON.

Manejo de errores y Encapsulamiento

En toda respuesta es importante informar al cliente lo que ocurrió en el llamado, ya sea que todo estuvo bien o que se presentó algún error.

Se recomienda siempre enviar un código de estado HTTP para indicar si la llamada fué exitosa o se presentó algún incidente.

Adicionalmente, se recomienda encapsular todas las respuestas en un objeto Json estándar que permita informar al cliente con un mensaje mas detallado del suceso.

Por ejemplo, si se presenta un problema de conexión con la base de datos, debemos responder con un código de estado 500, y la respuesta en Json debería indicar que el problema es de conexión a la base de datos.

{ 
status : 500,
message : "No es posible conectar con la base de datos",
content : ""
}

Otro ejemplo, cuando el usuario si tiene credenciales validas pero no tiene acceso a una consulta en particular es importante informar del suceso mediante un código de estado HTTP 401 y adicional la respuesta en Json detallando el incidente.

{ 
status : 401,
message : "El usuario no está autorizado a consultar esta data",
content : ""
}

O en caso de que todo esté bien, y para continuar con el estándar retornamos un código de estado HTTP 200 y la respuesta Json encapsulada:

{ 
status : 200,
message : "",
content : { nombre : "Pedro", apellido : "Perez" }
}

Incluso podríamos crear una serie de códigos internos más específicos dentro de la respuesta de un servicio para informar con mayor detalle, aunque esto no es muy recomendado y solo se debe usar en casos específicos.

Por ejemplo, el cliente no envía toda la información de entrada requerida, entonces respondemos con un código de estado HTTP 412 y la respuesta Json sería:

{ 
status : 801,
message : "Se requiere que se complete todo el formulario",
content : ""
}

Eso es todo por ahora, básicamente el secreto está en que todo lo que se defina sea pensando en la simplicidad y facilidad y siempre se siga el estándar que se define para evitar problemas incompatibilidades más adelante, además es de importancia documentar correctamente nuestro api, para que así aseguremos que el cliente sigue las indicaciones y que no va a tener problemas al hacer uso de uno de los servicios.

--

--

Diego Guevara

I'm a software engineer, JS Dev, creator of Grabitt.co, entrepreneur, photographer 📷 and House music deejay 🎧