Cómo NO diseñar APIs

Hola a todos ¿como están? hoy vamos a ver un poco como “no diseñar APIs”, en este caso Api Rest.

Sabemos que el formato de respuesta de nuestro servicio debe mantener un formato limpio claro y mantenible.

Veamos un ejemplo:

{ 
    "checkIn": "20191001", 
    "lastNight": "20191002", 
    "checkOut": "20191003", 
    "roomId": "12345", 
    "propId": "1234", 
    "ownerId": "123", 
    " numAdult ":" 2 ", 
    " numChild ":" 0 ", 
    " offerId ":" 1 ", 
    " voucherCode ":" ", 
    " referer ":" ", 
    " agent ":" ", 
    " ignoreAvail ": false, 
    "propIds": [ 
        1235, 
        1236 
    ], 
    "roomIds": [ 
        12347,
        12348, 
        12349 
    ] 
}

Podremos ver en algunos campos de fecha como checkIn, lastNight y checkOut tienen el formato YYYYMMDD que es amplia mente utilizado en ves de el estándar ISO 8601 (YYYY-MM-DD), lo que podemos ver mal aquí es lastNight y checkOut, es redundante ya que con checkOut podremos obtener cual fue la ultima noche del cliente. Siempre use formatos de codificación de fecha estándar y no pida al usuario de la API que proporcione datos redundantes.

Todos los identificadores, así como los campos numAdultnumChildson numéricos, pero están codificados como cadenas. Recomendaría retornar estos datos como lo que son, números.

" numAdult ": 2, 
" numChild ": 0 

Tenemos los siguientes pares de campos: roomIdroomIds , así como propIdpropIds. No sólo es redundante tener estas propiedades, atributos, también hay un problema de tipo aquí. Tenga en cuenta que roomIdespera una cadena, mientras que roomIdsrequiere una matriz numérica. Esto puede causar confusión, problemas de análisis y significaría que el back-end realiza algunas operaciones en cadenas y otras en números, aunque estamos hablando de los mismos datos.

Por favor, no confunda a los desarrolladores con este tipo de errors y trate de usar un formato estándar, así como prestar atención a la redundancia y los tipos de campo. No se limite a envolver todo en una cadena.

Formato en el cuerpo de la respuesta (response)

Veamos el siguiente ejemplo, tenemos a continuacion una peticion:

{ 
    "checkIn": "20190501", 
    "checkOut": "20190503", 
    "ownerId": "25748", 
    "numAdult": "2", 
    "numChild": "0" 
}

Y la respuesta (response) seria la siguiente:

{ 
    "10328": { 
        "roomId": "10328", 
        "propId": "4478", 
        "roomsavail": "0" 
    }, 
    "13219": { 
        "roomId": "13219", 
        "propId": "5729 ", 
        " roomsavail ":" 0 " 
    }, 
    " 14900 ": { 
        " roomId ":" 14900 ", 
        " propId ":" 6779 ", 
        " roomsavail ": 1 
    }, 
    " checkIn ":" 20190501 ", 
    " lastNight " : "20190502", 
    "checkOut": "20190503",
    "ownerId": 25748, 
    "numAdult": 2 
}

Podremos observar ownerIdy de numAdult en la respuesta están en formato numérico y no cadena como en la petición.

No tenemos una lista de propiedades, en su lugar están como objetos de nivel superior, y es difícil la lectura del mismo, obligando a realizar mas peticiones por cada propiedad.

Una respuesta limpia podria ser la siguiente:

{ 
    "propiedades": [ 
        { 
            "id": 4478, 
            "rooms": [ 
                { 
                    "id": 12328, 
                    "available": false
                 } 
            ] 
        }, 
        { 
            "id": 5729, 
            "rooms": [ 
                { 
                    "id" : 13219, 
                    "disponible": falso
                 } 
            ] 
        }, 
        { 
            "id": 6779, 
            "habitaciones":[ 
                { 
                    "id": 14900, 
                    "disponible":verdadero
                 } 
            ] 
        } 
    ], 
    "checkIn": "2019-05-01", 
    "lastNight": "2019-05-02", 
    "checkOut": "2019-05-03", 
    "ownerId": 25748, 
    "numAdult ": 2 
}

Como si diseñar APIs

A continuación veremos unos tips para poder implementar bien nuestras APIs.

Manejo de errores

El manejo de errores en esta API se implementa de la siguiente manera: todas las solicitudes devuelven un código de respuesta 200 , incluso en caso de error. Esto significa que no hay manera de distinguir entre una respuesta exitosa y otra no exitosa que no sea analizar el cuerpo y verificar la presencia de errorerrorCodecampos. La API solo tiene 6 códigos de error, como se ve a continuación:

Por favor, considere no usar este enfoque de devolver un código de respuesta 200(éxito) cuando algo salió mal, a menos que sea la forma estándar de ir en su marco de API. Hace la vida más fácil si el cliente de la API puede saber por adelantado si analizar o no el cuerpo, y cómo analizarlo (como un objeto de datos u objeto de error). Esto se puede lograr de dos maneras: ya sea tenga un código HTTP para cada uno de los 6 errores posibles arriba en el rango de 400–499 (preferido), o devuelva un 500 en caso de un error para que los clientes al menos sepan Un error antes de comenzar a analizar el cuerpo.

Directrices

A continuación se muestran las “directrices” de uso de la API de la documentación:Tenga en cuenta las siguientes pautas al utilizar la API

1. Las llamadas deben estar diseñadas para enviar y recibir solo los datos mínimos requeridos.

2. Solo se permite una llamada a la API a la vez. Debe esperar a que se complete la primera llamada antes de iniciar la siguiente llamada a la API.

3. Las llamadas múltiples deben espaciarse con un retraso de unos segundos entre cada llamada.

4. Las llamadas a la API deben usarse con moderación y mantenerse al mínimo requerido para un uso comercial razonable.

5. El uso excesivo en un período de 5 minutos hará que su cuenta se bloquee sin previo aviso.

6. Nos reservamos el derecho de des habilitar cualquier acceso que consideremos que hace un uso excesivo de las funciones de la API a nuestra entera discreción y sin previo aviso.

Mientras que los puntos 1, 4 tienen sentido, no puedo estar de acuerdo con que otros lo hagan. Déjame explicarte por qué.

2. En caso de que esté creando una API REST, se supone que no tiene estado, no debería haber ningún estado presente en ningún momento. Esta es una de las razones por las que REST es útil en aplicaciones en la nube. Los componentes sin estado se pueden volver a implementar libremente si algo falla, y se pueden escalar de acuerdo con los cambios de carga. Asegúrese de que al diseñar una API RESTful, sea realmente sin estado y que los desarrolladores no tengan que preocuparse por cosas como “una solicitud a la vez”.

3. Esta es una pauta ambigua y muy extraña. Desafortunadamente, no pude encontrar una razón por la cual el autor haya creado esta “guía”, pero da la sensación de que hay un proceso que se realiza fuera de la solicitud en sí, por lo que hacer llamadas inmediatamente después podría poner al sistema en un estado incorrecto . Además, el hecho de que el autor diga “unos pocos segundos” no proporciona información específica sobre el tiempo real entre las solicitudes.

5 y 6. Nuevamente, no se explica qué es “excesivo” en este caso. ¿Son 10 peticiones por segundo o 1? Además, ciertos sitios web tendrían una gran cantidad de tráfico, y bloquearlos para que no usen la API solo por eso sin ninguna advertencia podría hacer que los desarrolladores se alejen de dicho sistema. Por favor, sea específico al hacer tales pautas y piense en los usuarios al crear reglas como estas.

Documentación

Así es como se ve una documentación de la API:

Los únicos problemas aquí son la legibilidad y la sensación general. La misma documentación podría haberse visto mejor si el autor hubiera usado markdown en lugar del HTML personalizado sin estilo. Por el bien de esta publicación, creé una versión mejor con la ayuda de Dilliger en menos de 2 minutos. Aquí está el resultado:

Por favor, use herramientas para crear documentación API. Para documentos simples, un archivo de rebajas como el de arriba puede ser suficiente, mientras que para documentos más grandes y con más funciones, es mejor usar herramientas como Swagger o Apiary .

Aquí hay un enlace a los documentos API de Beds24 para aquellos que quieran echar un vistazo a ellos mismos.

Seguridad

Mantener nuestras APIs seguras es una muy buena practica, aunque en ocaciones podemos tener algunas APIs sin seguridad, como ser la obtencion de lista de propiedades, habitaciones, autos, etc etc.

En los casos de implementar seguridad se recomienda usar tokens de autenticación, estos token van junto a la petición de la API y si el servidor reconoce el token nos retornara los datos necesarios, en caso contrario obtendremos un error como respuesta.

Para aquellas solicitudes que realmente están autenticadas, tenemos un problema diferente: el token de autenticación debe enviarse como parte del cuerpo de la solicitud como se ve a continuación (de la documentación):

Tener el token de autenticación dentro del cuerpo de la solicitud significa que el servidor deberá analizar primero el cuerpo de la solicitud, extraer la clave, realizar la autenticación y luego decidir qué hacer con la solicitud: ejecutarlo o no. En caso de una autenticación exitosa, no hay sobrecarga ya que el cuerpo habría sido analizado de todos modos. En el caso de que la autenticación fallara, el servidor hizo todo el trabajo descrito anteriormente solo para extraer el token, y dedicó un tiempo de procesamiento precioso. Un mejor enfoque sería enviar un token de autenticación como un encabezado de solicitud. De esta manera, el servidor solo tendría que analizar el cuerpo de la solicitud en caso de una autenticación exitosa. Otra razón para usar un esquema de autenticación estándar como un token de Portador es simplemente porque la mayoría de los desarrolladores están familiarizados con él.

Performance

Como ultimo tip, y no menos importante, tener una respuesta por cada petición de 1 segundo en promedio es algo recomendable. Actualmente no es aceptable que la respuesta a la petición tarde mas de 2 segundos. Lo que nos obliga a nosotros como desarrolladores optimizar al máximo, sin perder calidad, las respuestas desde el back-end.

Bueno espero que sea de su agrado el articulo, desde ya muchas gracias. y hasta pronto.

LEAVE YOUR COMMENTS