Esta es una buena y una pregunta difícil. El tema del diseño de URI es al mismo tiempo la parte más destacada de una API REST y , por lo tanto, un compromiso potencialmente a largo plazo hacia los usuarios de esa API .
Dado que la evolución de una aplicación y, en menor medida, su API es una realidad y que es incluso similar a la evolución de un producto aparentemente complejo como un lenguaje de programación, el diseño de URI debería tener menos restricciones naturales y debería preservarse tiempo extraordinario . Cuanto más larga sea la vida útil de la aplicación y la API, mayor será el compromiso con los usuarios de la aplicación y la API.
Por otro lado, otro hecho de la vida es que es difícil prever todos los recursos y sus aspectos que se consumirían a través de la API. Afortunadamente, no es necesario diseñar toda la API que se utilizará hasta Apocalypse . Es suficiente definir correctamente todos los puntos finales de recursos y el esquema de direccionamiento de cada recurso y instancia de recurso.
Con el tiempo, es posible que deba agregar nuevos recursos y nuevos atributos a cada recurso en particular, pero el método que siguen los usuarios de API para acceder a recursos en particular no debería cambiar una vez que un esquema de direccionamiento de recursos se haga público y, por lo tanto, final.
Este método se aplica a la semántica de verbos HTTP (p. Ej., PUT siempre debe actualizarse / reemplazarse) y los códigos de estado HTTP admitidos en versiones API anteriores (deben continuar funcionando para que los clientes API que han trabajado sin intervención humana puedan continuar trabajando) como eso).
Además, dado que la incorporación de la versión API en el URI interrumpiría el concepto de hipermedia como el motor del estado de la aplicación (indicado en la tesis doctoral de Roy T. Fieldings) al tener una dirección de recursos / URI que cambiaría con el tiempo, concluiría que API las versiones no deben mantenerse en los URI de recursos durante mucho tiempo, lo que significa que los URI de recursos de los que los usuarios de API pueden depender deben ser enlaces permanentes .
Claro, es posible incrustar la versión API en el URI base, pero solo para usos razonables y restringidos, como la depuración de un cliente API que funciona con la nueva versión API. Dichas API versionadas deberían tener un tiempo limitado y estar disponibles solo para grupos limitados de usuarios de API (como durante las versiones beta cerradas). De lo contrario, te comprometes donde no deberías.
Un par de reflexiones sobre el mantenimiento de versiones de API que tienen fecha de vencimiento. Todas las plataformas / lenguajes de programación comúnmente utilizados para implementar servicios web (Java, .NET, PHP, Perl, Rails, etc.) permiten vincular fácilmente los puntos finales del servicio web a un URI base. De esta manera, es fácil reunir y mantener una colección de archivos / clases / métodos separados en diferentes versiones de API .
Desde el punto de vista de los usuarios de API, también es más fácil trabajar y vincularse a una versión de API en particular cuando es obvio, pero solo por un tiempo limitado, es decir, durante el desarrollo.
Desde el punto de vista del mantenedor de API, es más fácil mantener diferentes versiones de API en paralelo mediante el uso de sistemas de control de fuente que trabajan principalmente en archivos como la unidad más pequeña de versiones (código fuente).
Sin embargo, con las versiones de API claramente visibles en URI, hay una advertencia: también se podría objetar este enfoque ya que el historial de API se vuelve visible / aparente en el diseño de URI y, por lo tanto, es propenso a cambios en el tiempo que van en contra de las pautas de REST. ¡Estoy de acuerdo!
La forma de sortear esta objeción razonable es implementar la última versión de API bajo el URI base de API sin versión. En este caso, los desarrolladores de clientes API pueden elegir:
desarrollarse contra el último (comprometiéndose a mantener la aplicación protegiéndola de eventuales cambios de API que podrían dañar su cliente API mal diseñado ).
vincularse a una versión específica de la API (que se hace evidente) pero solo por un tiempo limitado
Por ejemplo, si API v3.0 es la última versión de API, los siguientes dos deberían ser alias (es decir, comportarse de manera idéntica a todas las solicitudes de API):
http: // shonzilla / api / clients / 1234
http: // shonzilla / api /v3.0 / / 1234
http: // shonzilla / api / v3 / clients / 1234
Además, los clientes de API que todavía tratan de punto a la antigua API deben ser informados a utilizar la última versión de la API anterior, si la versión de la API que están usando es obsoleto o no soportado más . Entonces, acceda a cualquiera de los URI obsoletos como estos:
http: // shonzilla / api /v2.2 / clients / 1234
http: // shonzilla / api /v2.0 / clients / 1234
http: // shonzilla / api / v2 / clients / 1234
http: // shonzilla / api /v1.1 / clients / 1234
http: // shonzilla / api / v1 / clients / 1234
debería devolver cualquiera de los 30 códigos de estado HTTP que indican la redirección que se utiliza junto con el Location
encabezado HTTP que redirige a la versión adecuada del URI de recursos que sigue siendo este:
http: // shonzilla / api / clients / 1234
Hay al menos dos códigos de estado HTTP de redireccionamiento que son apropiados para escenarios de versiones de API:
301 Se movió permanentemente, lo que indica que el recurso con un URI solicitado se mueve permanentemente a otro URI (que debería ser un enlace permanente de instancia de recurso que no contiene información de versión de API). Este código de estado se puede usar para indicar una versión API obsoleta / no compatible, informando al cliente API que un URI de recurso versionado ha sido reemplazado por un enlace permanente de recursos .
302 Se encontró que indica que el recurso solicitado se encuentra temporalmente en otra ubicación, mientras que el URI solicitado aún puede ser compatible. Este código de estado puede ser útil cuando los URI sin versión no están disponibles temporalmente y se debe repetir una solicitud utilizando la dirección de redireccionamiento (por ejemplo, apuntando al URI con la versión APi incrustada) y queremos decirles a los clientes que sigan usándolo (es decir, el enlaces permanentes).
Se pueden encontrar otros escenarios en el capítulo Redirección 3xx de la especificación HTTP 1.1
410 Gone
, ya que una redirección podría indicar que la nueva ubicación es compatible cuando no lo es. Si la API es simplemente obsoleta pero todavía existe, unWarning
Encabezado HTTP en la Respuesta podría ser una opción.La URL NO debe contener las versiones. La versión no tiene nada que ver con la "idea" del recurso que está solicitando. Debe intentar pensar en la URL como una ruta hacia el concepto que desea, no cómo desea que se devuelva el elemento. La versión dicta la representación del objeto, no el concepto del objeto. Como han dicho otros carteles, debe especificar el formato (incluida la versión) en el encabezado de la solicitud.
Si observa la solicitud HTTP completa de las URL que tienen versiones, se ve así:
El encabezado contiene la línea que contiene la representación que está solicitando ("Aceptar: aplicación / xml"). Ahí es donde debería ir la versión. Todo el mundo parece pasar por alto el hecho de que es posible que desee lo mismo en diferentes formatos y que el cliente pueda pedir lo que quiere. En el ejemplo anterior, el cliente solicita CUALQUIER representación XML del recurso, no realmente la representación real de lo que quiere. El servidor podría, en teoría, devolver algo completamente ajeno a la solicitud siempre que fuera XML y tendría que analizarse para darse cuenta de que está equivocado.
Una mejor manera es:
Además, digamos que los clientes piensan que el XML es demasiado detallado y ahora quieren JSON en su lugar. En los otros ejemplos, tendría que tener una nueva URL para el mismo cliente, por lo que terminaría con:
(o algo similar). Cuando, de hecho, cada solicitud HTTP contiene el formato que está buscando:
Con este método, tiene mucha más libertad en el diseño y se está adhiriendo a la idea original de REST. Puede cambiar las versiones sin interrumpir a los clientes, o cambiar gradualmente los clientes a medida que cambian las API. Si elige dejar de admitir una representación, puede responder a las solicitudes con un código de estado HTTP o códigos personalizados. El cliente también puede verificar que la respuesta esté en el formato correcto y validar el XML.
Hay muchas otras ventajas y discuto algunas de ellas aquí en mi blog: http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html
Un último ejemplo para mostrar cómo poner la versión en la URL es malo. Supongamos que desea alguna información dentro del objeto, y ha versionado sus diversos objetos (los clientes son v3.0, los pedidos son v2.0 y el objeto shipto es v4.2). Aquí está la URL desagradable que debe proporcionar en el cliente:
fuente
-x
ya que está obsoleto por RFC6648 .Nos pareció práctico y útil poner la versión en la URL. Facilita saber lo que estás usando de un vistazo. Hacemos alias / foo to / foo / (últimas versiones) para facilitar su uso, URL más cortas / más limpias, etc., como sugiere la respuesta aceptada.
Mantener la compatibilidad con versiones anteriores para siempre suele ser costoso y / o muy difícil. Preferimos dar aviso avanzado de desuso, redireccionamientos como los sugeridos aquí, documentos y otros mecanismos.
fuente
Estoy de acuerdo en que versionar la representación de recursos sigue mejor el enfoque REST ... pero, un gran problema con los tipos MIME personalizados (o los tipos MIME que agregan un parámetro de versión) es el escaso soporte para escribir en los encabezados Aceptar y Tipo de contenido en HTML y JavaScript
Por ejemplo, no es posible IMO POSTAR con los siguientes encabezados en formularios HTML5, para crear un recurso:
Esto es porque el HTML5
enctype
atributo es una enumeración, por lo tanto, otra cosa que no sea la habitualapplication/x-www-formurlencoded
,multipart/form-data
ytext/plain
no son válidos.... ni tampoco estoy seguro de que sea compatible con todos los navegadores en HTML4 (que tiene un atributo de tipo de letra más laxo, pero sería un problema de implementación del navegador en cuanto a si se reenvió el tipo MIME)
Debido a esto, ahora siento que la forma más adecuada para la versión es a través del URI, pero acepto que no es la forma "correcta".
fuente
Pon tu versión en el URI. Una versión de una API no siempre admitirá los tipos de otra, por lo que el argumento de que los recursos simplemente se migran de una versión a otra es simplemente erróneo. No es lo mismo que cambiar el formato de XML a JSON. Es posible que los tipos no existan o que hayan cambiado semánticamente.
Las versiones son parte de la dirección del recurso. Estás enrutando de una API a otra. No es RESTful ocultar el direccionamiento en el encabezado.
fuente
Hay algunos lugares donde puede realizar el control de versiones en una API REST:
Como se señaló, en la URI. Esto puede ser manejable e incluso estéticamente agradable si los redireccionamientos y similares se usan bien.
En el encabezado Acepta: la versión está en el tipo de archivo. Como 'mp3' vs 'mp4'. Esto también funcionará, aunque IMO funciona un poco menos bien que ...
En el recurso mismo. Muchos formatos de archivo tienen sus números de versión incrustados en ellos, generalmente en el encabezado; esto permite que el software más nuevo 'simplemente funcione' al comprender todas las versiones existentes del tipo de archivo, mientras que el software más antiguo puede despejar si se especifica una versión no admitida (más nueva). En el contexto de una API REST, significa que sus URI nunca tienen que cambiar, solo su respuesta a la versión particular de los datos que recibió.
Puedo ver razones para usar los tres enfoques:
fuente
El control de versiones de su API REST es análogo al control de versiones de cualquier otra API. Se pueden realizar cambios menores, los cambios importantes pueden requerir una API completamente nueva. Lo más fácil para ti es comenzar desde cero cada vez, que es cuando poner la versión en la URL tiene más sentido. Si desea facilitarle la vida al cliente, intente mantener la compatibilidad con versiones anteriores, lo que puede hacer con desaprobación (redirección permanente), recursos en varias versiones, etc. Esto es más complicado y requiere más esfuerzo. Pero también es lo que REST fomenta en "Los URI geniales no cambian".
Al final es como cualquier otro diseño de API. Considere el esfuerzo contra la conveniencia del cliente. Considere la posibilidad de adoptar versiones semánticas para su API, lo que deja en claro a sus clientes cuán compatible es su nueva versión con versiones anteriores.
fuente