API REST? De debó?

09 d’oct. 2026

El problema

Fa uns mesos, em vaig fer càrrec d’un microservei per a desenvolupar noves característiques.

El primer que vaig fer va ser revisar el codi.

Suposadament, aquest microservei gestiona i serveix un recurs anomenat persona per mitjà d’un API REST.

I vaig trobar això:

/personas/datosPersona, /personas/datosPersonaBasica, /personas/datosCrearPersona, /personas/datosPersonaModificarIdentificaciones, /personas/datosPersonaBuscar

De debò? Aquesta és la suposada primera versió de l’API REST. També em vaig trobar això altre:

/personas/informarPersona, /personas/informarPersonaBasica, /personas/informarNuevaPersona, /personas/informarBuscaPersona, /personas/informarModificarPersona

Aquests endpoints són la segona versió de l’API REST.

Tots aquests endpoints utilitzen el verb HTTP POST.

Això és de bojos. El recurs és persona però pels noms dels endpoints, sembla que hi ha un munt de recursos: datosPersona, datosPersonaBasica, datosCrearPersona, datosPersonaModificarIdentificaciones, datosPersonaBuscar, etc.

Els endpoints han d’anomenar-se segons el recurs que representen:

/persona

Sí, estic d’acord, no existeix pas cap estàndard d’API REST definit per la IETF, però existeix un estàndard de facto i un consens general dels patrons que s’han d’aplicar per a cada cas d’ús que els microserveis han de seguir.

El verb HTTP és important

Tots els endpoints mostrats abans, comparteixen una característica comuna, el verb HTTP usat és sempre el mateix: POST

Això és un error, ja que el verb HTTP està lligat a un significat concret:

  • POST Per a operacions de creació
  • PUT Per a operacions de substitució
  • PATCH Per a operacions d’actualització
  • DELETE Per a operacions d’esborrament
  • GET Per a operacions de lectura o de cerca

Per tant, un POST a un endpoint /persona significa la creació d’un nou recurs persona. Un GET a un endpoint /persona significa una lectura o una cerca, depèn dels paràmetres.

Paràmetres

Hi ha diverses maneres d’indicar paràmetres a un endpoint:

  • path arguments, com /persona/{idPersona}
  • query arguments, com /persona?m=b
  • body arguments, com objectes JSON

Cadascuna, combinada amb un endpoint i un verb HTTP implica diferents accions.

  • path per a lectures basades en claus com l’ID d’una persona
  • query per a definir els paràmetres de cerca o per a determinar aspectes de les operacions de lectura
  • body per a indicar les dades en operacions de creació, substitució i actualització

Models dinàmics per a lectura i cerca

En alguns casos, sobretot si el model és molt pesant, l’usuari pot voler reduir el nombre de propietats del model a obtenir.

Això es pot aconseguir amb paràmetres query que especifiquin quines parts del model es vol obtenir.

Aquestes parts han de ser predefinides i documentades al REST API.

En qualsevol cas, ha d’existir un grup de propietats bàsiques que sempre s’obtenen, per exemple l’ID.

Per a reduir al màxim la mida de la petició HTTP, el paràmetre i els arguments han de ser reduïts a la mínima expressió. Jo m’estimo més utilitzar un paràmetre query anomenat m, per model.

Els valors d’aquest paràmetre seran lletres que estaran associades a un conjunt de propietats del model.

Aquests valors de l’argument poden combinar-se per tal que l’usuari pugui determinar totes les parts del model que desitja obtenir.

Per exemple, en el cas del recurs persona:

  • r persones relacionades (parents, germans, etc.)
  • e informació econòmica
  • c informació de contactes (com email, telèfon, adreces postals, etc.)
  • g informació de gestions

Per tant, si l’usuari vol obtenir les persones relacionades i les dades de contacte, la crida HTTP serà:

GET /persona/<idPersona>?m=rc

En els casos de cerca, s’haurà de combinar el paràmetre de model amb els paràmetres de cerca:

GET /persona?f="e=>50"&m=rc&p=1&s=25

Aquesta crida s’ha d’interpretar com:

  • f Indica el filtre: edat igual o més gran de 50
  • m El model a obtenir contindrà (a més de les propietats bàsiques) les persones relacionades i les dades de contacte
  • p Pàgina primera (comença en 1)
  • s Mida de la pàgina és 25 (s per la paraula Anglesa «size»)

Versionatge del REST API

Aquesta és una part essencial de REST API. De la mateixa manera que el programari té versió, el REST API que implementa també ha de tenir versió.

Hi ha sistemes diferents per a establir la versió:

  • Versionatge amb el path
  • Versionatge amb un header HTTP específic
  • Versionatge amb el Media Type
  • Versionatge amb paràmetres query

El versionatge amb el path es fa afegint un prefix amb la versió:

/api/v1/persona

Personalment, jo m’estimo més el mètode de header HTTP específic. Jo utilitzo un header anomenat x-api-version.

Així, el mateix endpoint serveix les dues versions de l’API.

Per tant, els endpoints per a la mateixa operació de les dues versions: /personas/datosPersona i /personas/informarPersona haurien d’usar el mateix endpoint: /persona i la diferència la marcaria únicament el header.

Ara bé, com s’ha d’indicar la versió? Hi existeix el costum generalitzat d’usar una lletra be baixa i un nombre: v1. Podem utilitzar, també, només el nombre. En qualsevol cas, el nombre ha de coincidir amb la versió major del programari que l’implementa (recordeu-vos de la gestió semàntica de la versió).

Distribució de versions

Com podem fer coexistir dues versions del mateix REST API? Bé, això depèn de la manera en què està implementat:

  • Dues instàncies diferents del mateix serveix per a diferents versions (1 i 2).
  • La mateixa instància implementa les dues versions.

La solució depèn de l’entorn d’execució. Si el sistema d’orquestració suporta l’execució de dues instàncies diferents associades amb el mateix servei, amb opció per a filtrar l’encaminament segons el contingut del header HTTP (o segons el path), aquesta seria la millor opció, ja que el codi seria net i fàcil de mantenir.

Si no, l’única solució seria implementar les dues versions al mateix codi, però aquest mètode requereix un disseny, codificació, gestió i manteniment molt curós.