Una buena API ha de ser versionada: los cambios y las nuevas características son implementadas en las nuevas versiones del API, en vez de estar continuamente modificando sólo una versión. Al contrario que en las aplicaciones Web, en las cuales tienes total control del código de ambas partes lado del cliente y lado del servidor, las APIs están destinadas a ser usadas por los clientes fuera de tu control. Por esta razón, compatibilidad hacia atrás (BC Backward compatibility) de las APIs ha de ser mantenida siempre que sea posible. Si es necesario un cambio que puede romper la BC, debes de introducirla en la nueva versión del API, e incrementar el número de versión. Los clientes que la usan pueden continuar usando la antigua versión de trabajo del API; los nuevos y actualizados clientes pueden obtener la nueva funcionalidad de la nueva versión del API.
Consejo: referirse a Semántica del versionado para más información en el diseño del número de versión del API.
Una manera común de implementar el versionado de la API es embeber el número de versión en las URLs de la API.
Por ejemplo, http://example.com/v1/users
se refiere al punto final /users
de la versión 1 de la API.
Otro método de versionado de la API,
la cual está ganando predominancia recientemente, es poner el número de versión en las cabeceras de la petición HTTP. Esto se suele hacer típicamente a través la cabecera Accept
:
// vía parámetros
Accept: application/json; version=v1
// vía de el tipo de contenido del proveedor
Accept: application/vnd.company.myapp-v1+json
Ambos métodos tienen sus pros y sus contras, y hay gran cantidad de debates sobre cada uno. Debajo puedes ver una estrategia práctica para el versionado de la API que es una mezcla de estos dos métodos:
v1
, v2
).
Naturalmente, las URLs de la API contendrán números de versión mayores.Accept
para determinar el número de la versión menor y escribe código condicional para responder a la menor versión como corresponde.Para cada módulo sirviendo una versión mayor, el módulo debe incluir las clases de recursos y y controladores
que especifican la versión. Para separar mejor la responsabilidad del código, puedes conservar un conjunto común de
clases base de recursos y controladores, y hacer subclases de ellas en cada versión individual del módulo. Dentro de las subclases,
impementa el código concreto como por ejemplo Model::fields()
.
Tu código puede estar organizado como lo que sigue:
api/
common/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
modules/
v1/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
v2/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
La configuración de tu aplicación puede tener este aspecto:
return [
'modules' => [
'v1' => [
'basePath' => '@app/modules/v1',
'controllerNamespace' => 'app\modules\v1\controllers',
],
'v2' => [
'basePath' => '@app/modules/v2',
'controllerNamespace' => 'app\modules\v2\controllers',
],
],
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user', 'v1/post']],
['class' => 'yii\rest\UrlRule', 'controller' => ['v2/user', 'v2/post']],
],
],
],
];
Como consecuencia del código anterior, http://example.com/v1/users
devolverá la lista de usuarios en la versión 1, mientras
http://example.com/v2/users
devolverá la versión 2 de los usuarios.
Gracias a los módulos, el código de las diferentes principales versiones puede ser aislado. Pero los módulos hacen posible reutilizar el código a través de los módulos vía clases base comunes y otros recursos compartidos.
Para tratar con versiones menores, puedes tomar ventaja de la característica de negociación de contenido
provista por el comportamiento (behavior) contentNegotiator. El comportamiento contentNegotiator
definirá la propiedad yii\web\Response::$acceptParams cuando determina qué tipo
de contenido soportar.
Por ejemplo, si una petición es enviada con la cabecera HTTP Accept: application/json; version=v1
,
después de la negociación de contenido, yii\web\Response::$acceptParams contendrá el valor ['version' => 'v1']
.
Basado en la información de versión contenida en acceptParams
, puedes escribir código condicional en lugares
como acciones, clases de recursos, serializadores, etc. para proveer la funcionalidad apropiada.
Dado que por definición las versiones menores requireren mantener la compatibilidad hacia atrás, con suerte no tendrás demasiadas comprobaciones de versión en tu código. De otra manera, probablemente puede ocurrir que necesites crear una versión mayor.
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.