Saltar a contenido

JSON over POST

Nota

Esta es una traducción imcompleta y muy personal del artículo JSON over POST: A simple alternative to REST, gRPC and GraphQL de François Wouts.

Un poco de contexto

¿Qué pasaría si todos sus endpoints de la API, utilizaran exclusivamente POST con cargas útiles(body request) JSON en lugar de intentar seguir REST?

Un enfoque que rara vez he visto discutido, tal vez porque los defensores de REST lo considerarían una herejía, es construir una API JSON que rompa deliberadamente con los principios de REST: JSON over POST.

Como funciona

Cada endpoint utiliza el método HTTP POST.

Cada endpoint tiene una ruta asociada que describe claramente lo que hace, sin ningún parámetro de ruta dinámico. Por ejemplo:

  • /users/get
  • /users/list
  • /users/update

Los datos de la solicitud siempre se pasan en el cuerpo de la solicitud como JSON. Nunca se utilizan parámetros de consulta o ruta.

Al igual que gRPC y GraphQL, esto rompe los mecanismos basados en HTTP como el almacenamiento en caché de peticiones GET (puesto que ya no hay peticiones GET 😄). Sin embargo, puede simplificar significativamente las implementaciones tanto del lado del servidor como del lado del cliente.

A tener en cuenta

Al crear un nuevo módulo en Callisto (comando crud) solo se utiliza POST

Un endpoint se define ahora exclusivamente como una ruta fija, un esquema de cuerpo de petición y un esquema de cuerpo de respuesta. No tenemos que preocuparnos de métodos HTTP, ruta o parámetros de consulta, etc...

Nota

Cada endpoint equivale a una función que toma un único parámetro estructurado (el cuerpo de la petición). Ya no es REST, ¡pero definitivamente es RPC!

Ejemplos

Importante

esta es una caracteristica avanzada que se utiliza en Callisto, te recomendamos utilzar el comando crud.

definimos nuestro router

from fastapi import APIRouter, FastAPI
...

app = FastAPI()

locales_router = APIRouter(
    prefix="/locales",
    tags=["locales"],
    dependencies=[Depends(validate_auth_session)],
)

creamos los endpoints para el router locales_router

from fastapi import APIRouter, Depends, Request
from app.common.http.response import response
...


@locales_router.post("/search")
async def locales_search(request: Request, body: LocalesSearchDto, ):
    return response(200, HTTPStatus.SUCCESS)


@locales_router.post("/create")
async def locales_create(request: Request, body: LocalesCreateDto):
    return response(201, HTTPStatus.CREATED)


@locales_router.post("/update")
async def locales_update(request: Request, body: LocalesUpdateDto):
    return response(200, HTTPStatus.UPDATED)


@locales_router.post("/delete")
async def locales_delete(request: Request, body: DefaultDeleteDto):
    return response(200, HTTPStatus.SUCCESS)

Nota

hasta aquí, nada nuevo bajo el sol, pero... si te fijas bien... todos los routes son POST 🔥

agregamos nuestro nuevo router a FastAPI

1
2
3
4
from fastapi import FastAPI
...

app.include_router(locales_router)

CRUD usando JSON over POST

Callisto proporciona un generador que automágicamente crea todo el código boilerplate para ayudarnos a evitar hacer todo esto de forma manual (y puede que propenso a errores), y hacer la experiencia del desarrollador mucho más simple.

  • ejecutamos el comando crud, utilizando Poetry... 🥁
$ poetry exec crud
  • definir el nombre del módulo

    CRUD modules for Callisto 🦄
    ? Escribe un nombre para el módulo: locales
    

  • definir el tipo de router a utilizar: JSON Over Post (api_router)

    1
    2
    3
    4
    ? Selecciona el tipo de módulo: (Use arrow keys)
       Default CRUD (APIRouter)
     » JSON Over Post
       Ninguno (Salir)
    

  • definir el tipo de ORM

    1
    2
    3
    4
    ? Deseas utilizar un ORM? (Use arrow keys)
     » MongoDB
       Firestore
       Ninguno (sin ORM)
    

  • listo!

    ? Listo? (y/N) Y
    

Importante

Cuando el BackEnd inicie, intentará ubicar un archivo llamado urls.py en la carpeta app/modules/ y el nombre del módulo que estás creando, ejemplo:

1
2
3
4
5
6
/app
├── modules
│   ├── locales
│   │   ├── __init__.py
│   │   ├── urls.py
│   ├── __init__.py

Romper con los dogmas técnicos

Todos hemos oído durante años que REST es la forma "correcta" de implementar una API. GraphQL y gRPC han traído alternativas, pero... ¿qué pasa si quieres simplicidad pura? considera JSON over POST.

Lectura recomendada