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:
POSTPer a operacions de creacióPUTPer a operacions de substitucióPATCHPer a operacions d’actualitzacióDELETEPer a operacions d’esborramentGETPer 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:
patharguments, com/persona/{idPersona}queryarguments, com/persona?m=bbodyarguments, com objectes JSON
Cadascuna, combinada amb un endpoint i un verb HTTP implica diferents accions.
pathper a lectures basades enclauscom l’ID d’una personaqueryper a definir els paràmetres de cerca o per a determinar aspectes de les operacions de lecturabodyper 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:
rpersones relacionades (parents, germans, etc.)einformació econòmicacinformació de contactes (com email, telèfon, adreces postals, etc.)ginformació 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:
fIndica el filtre: edat igual o més gran de 50mEl model a obtenir contindrà (a més de les propietats bàsiques) les persones relacionades i les dades de contactepPàgina primera (comença en 1)sMida de la pàgina és 25 (sper 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.