Creando un API en Net Core - REST API
Tags: csharp, api, dotnet, rest
Published: 2021-02-02 05:01:18

En el [primer artículo](https://dev.to/andreslozadamosto/creando-un-api-en-net-core-5-3jc4-temp-slug-8247256/edit) de la serie vimos que es un **API** y cuales son los tipos que hay. 

En el presente, vamos a enfocarnos sobre que es un **API REST** y como podemos diseñarlas.

# API REST
Durante la última década (y mucho más también) las **API REST** fueron el estándar de facto para desarrollar **APIs**. 

**REST** _(REpresentational State Transfer)_ es un estilo de arquitectura de sistemas distribuidos y no un estándar como lo es **SOAP**. Esta es la razón por la que no existe una guía estandarizada para su implementación; lo que si hay son principios o limitaciones que definen si un **API** es **REST** o no. 

[Roy Fielding](https://roy.gbiv.com/) fue la persona que introdujo este concepto por primera vez en su tesis [“Architectural Styles and the Design of Network-based Software Architectures”](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) donde define las siguientes restricciones que se deben cumplir para que una arquitectura sea considerada **REST**:

- **Arquitectura cliente-servidor** _(client-server architecture)_: dos aplicaciones actuando una como cliente la cual solicita recursos a un servidor el cual devuelve una respuesta ante la solicitud del cliente.
- **Sin estado** _(stateless)_: El servidor no guarda un estado entre diferentes solicitudes (request) de un cliente, o sea, cada solicitud es independiente del resto y debe auto-contener la información suficiente para regenerar el estado en cada request.
- **Cache**: debe ser posible almacenar en un caché la respuesta del servidor y poder devolverla en las subsiguientes peticiones (que requieran el mismo recurso) sin necesidad de que llegue el request al servidor nuevamente.
- **Interfaz uniforme** _(uniform interface)_:  Incluye cuatro aspectos, identificación de recursos, gestión de recursos a través de representaciones, comunicaciones auto-descriptivas e hipermedia como el motor del estado de la aplicación ([HATEOAS](https://es.wikipedia.org/wiki/HATEOAS)).
- **Sistema de capas** _(layered system)_: La solicitud al server puede pasar por diferentes capas donde se puede agregar funcionalidades adicionales como caché, seguridad, balanceo de carga, auditoría, logging, etc.
- **Código bajo demanda** _(code on demand)_: Es un feature opcional y no es necesario que las APIs lo implementen. Esta funcionalidad permite que el server devuelva al cliente código ejecutable

Las **APIs** que implementan **REST** se las conoce como **API RESTful**.

En el último tiempo surgieron especificaciones que intentan darle un marco estandarizado a las **API REST**. Entre ellas [OpenAPI](https://www.openapis.org/) es la más popular. Otra especificación en auge es el [RAML](https://raml.org/).

![Its not restful](https://dev-to-uploads.s3.amazonaws.com/i/2yf9ya3hrvi7cmbbfhpt.jpg)

***

# Diseño de un API REST
Cuando diseñamos un **API REST**, más allá de la implementación propia del lenguaje de programación que utilicemos, debemos tener en cuenta lo siguiente:

- Los principios analizados anteriormente
- Las **API REST** trabajan con _"recursos"_ y no con _"servicios/funciones"_ como en **RPC**/**SOAP** y que cada recurso debe poder accederse por un URI en propio (endpoint)
- Debemos hacer uso correcto de las bondades del protocolo _HTTP_, tales como los verbos (_GET_, _POST_, _PUT_, etc), los códigos de estado (_404_, _500_, _200_, etc) y las cabeceras (_headers_).

Por ejemplo, tomemos el _recurso_ Usuario llamado _Andres_, debe tener asociada una URI _http://domain.com/users/andres_ y para su obtención se utiliza el método _GET_, para su creación _POST_.

Otro ejemplo es la información de una reunión _http://domain.com/meetings/2354_. 

Tanto el recurso _“andres”_ como el recurso _“meeting 2354”_ siempre refieren al mismo recurso y es esperable que ante subsecuentes solicitudes siempre devuelva la misma información (la cual se puede cachear).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/jruswtuc1l60hbntvwig.png)

Ejemplos no validos:
- _http://domain.com/users/getUserByName/andres_
- _http://domain.com/users/updateUser/andres_
- _http://domain.com/users/createUserUser/andres_

## Verbos HTTP (HTTP verbs)
El [protocolo HTTP](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) define un conjunto de acciones a realizar sobre un recurso tales como su creación, su borrado o actualización. 
Estas acciones (HTTP verbs) juegan un rol importante en el constraint de Uniform Interface que vimos anteriormente.

| Verbo HTTP    | Operación     | Descripción |
|:------------- |:------------- |:----------- |
| GET           | Read          | Solicita uno o una colección de recursos |
| POST          | Create        | Crea un recurso con la información enviada en el cuerpo (body) del request |
| PUT           | Update/Replace| Actualiza un recurso preexistente o lo reemplaza. Podría también crearlo |
| PATCH         | Update/Modify | Similar a PUT, se utiliza para actualizar de manera parcial un recurso |
| DELETE        | Delete        | Elimina un recurso |
| HEAD          | Read          | Similar a GET, pero el server solo retorna los encabezados (headers) y no el cuerpo (body) de la respuesta |
| OPTIONS       | ASK           | El servidor retorna el listado de verbos HTTP permitidos para el recurso |
| TRACE         | ALL           | Solicita al servidor que agregue en la respuesta los datos recibidos para depuración |

Los verbos _GET_, _HEAD_, _OPTIONS_ y _TRACE_ son considerados seguros por definición por lo que no deben generar un impacto en el/los recursos indicados en la petición (ni generar por ejemplo transacciones que generen un cambio de estado en el servidor) más allá de agregar logging, update de caché, entre otros recursos aledaños pero nunca sobre el recurso indicado en el URI.

Por otro lado, muchos de estos _verbos HTTP_ tienden a ser idempotentes (aunque no es una restricción si es esperable). Los verbos _PUT_, _DELETE_, _GET_, _HEAD_, _OPTIONS_ y _TRACE_ deben devolver siempre la misma información ante subsecuentes requests. No así para el verbo _POST_ donde cada request igual puede generar efectos secundarios tal vez no deseados.

## Código de estados (HTTP Status codes)
Los datos que retorna el servidor a partir de un request siempre son acompañados por un código de estado de **HTTP** que indica el resultado del request.

**HTTP** define un conjunto predefinidos que se agrupan en:

- **1xx**: los códigos dentro de este rango son informativos
- **2xx**: los encontrados en este rango indican que la solicitud fue exitosa
- **3xx**: este grupo de códigos indican que se debe hacer o hubo una redirección
- **4xx**: los códigos dentro de este grupo indican diferentes errores del cliente
- **5xx**: estos códigos indican que se produjo un error en el servidor

Muchos de estos códigos son devueltos por la infraestructura o por el framework que utilicemos para crear nuestra API, mientras que nosotros como devs vamos a utilizar otros (y en algunos casos los mismos) para indicar que sucedió con la solicitud que estamos tratando.

Los códigos más utilizados son:
- **200** _(OK)_: solicitud exitosa y retorno del recurso
- **201** _(Created)_: recurso creado exitosamente y retorna el URI al recurso
- **401** _(Unauthorized)_: sin autorización para el recurso
- **403** _(Forbidden)_: 
- **404** _(Not Found)_: recurso no encontrado/inexistente
- **409** _(Conflict)_: conflicto en la creación/update del recurso
- **500** _(Internal Server Error)_: error no manejado en el código de la aplicación, por ejemplo una excepción sin un catch.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/okqq15ra2sex0mohbchq.jpg)

No comments sobre esta imagen 🤣

## Encabezados (HTTP Headers)
Los **Headers** es información adicional que se intercambia entre el cliente y el servidor (Request/Response). Por ejemplo:

- Información sobre los datos enviados en el Request/Response
- Información de Autenticación
- Información sobre Caching 
- Información sobre Cookies

Algunos **Headers** tienen dirección cliente al servidor (ej: _Authentication_), otros tienen significado del servidor al cliente (ej: _Location) y por último algunos se utilizan indistintamente (ej: _Content-Length_).

Entre los mas comunes podemos mencionar

| Header        | Descripción |
|:------------- |:----------- |
| Authorization | Método e información para la autenticación en el servidor del recurso |
| Cache-Control | Método de cache para el recurso |
| Accept        | Informa sobre el formato aceptado por el cliente |
| Accept-Language | Lenguaje esperado por el cliente para los datos que recibe del server |
| Cookie        | Cookies recibidas por el server |
| Origin        | Indica desde donde se origino el request |
| Content-Length| Tamaño del payload |
| Content-Type  | Indica el Media Type del payload |


***

Bien ya aprendimos algo sobre las **API REST** es hora de comenzar a meter mano un algo de código, somos devs, no?

Bueno, preparate un 🧉/☕ + 🥐🍩 que en el próximo vamos directo a  tirar magia 💪 

***