Diseño de APIAPI design

Las mayoría de las aplicaciones web modernas exponen interfaces de programación de aplicaciones (API) que los clientes pueden usar para interactuar con la aplicación.Most modern web applications expose APIs that clients can use to interact with the application. Una API web bien diseñada debe ser capaz de admitir:A well-designed web API should aim to support:

  • Independencia de la plataforma.Platform independence. Cualquier cliente debe poder llamar a la API, con independencia de cómo esté implementada internamente.Any client should be able to call the API, regardless of how the API is implemented internally. Para ello, es necesario usar protocolos estándar y contar con un mecanismo por medio del cual el cliente y el servicio web puedan acordar el formato de los datos que se intercambian.This requires using standard protocols, and having a mechanism whereby the client and the web service can agree on the format of the data to exchange.

  • Evolución del servicio.Service evolution. La API web debe poder evolucionar y agregar funcionalidad con independencia de las aplicaciones cliente.The web API should be able to evolve and add functionality independently from client applications. A medida que evoluciona la API, las aplicaciones cliente existentes deben seguir funcionando sin necesidad de modificarlas.As the API evolves, existing client applications should continue to function without modification. Toda la funcionalidad debe poderse detectar, así las aplicaciones cliente puedan usarla completamente.All functionality should be discoverable, so that client applications can fully utilize it.

En esta guía se describen los problemas que se deben tener en cuenta al diseñar una API web.This guidance describes issues that you should consider when designing a web API.

Introducción a RESTIntroduction to REST

En 2000, Roy Fielding propuso la transferencia de estado representacional (REST) como enfoque de arquitectura para el diseño de servicios web.In 2000, Roy Fielding proposed Representational State Transfer (REST) as an architectural approach to designing web services. REST es un estilo de arquitectura para la creación de sistemas distribuidos basados en hipermedia.REST is an architectural style for building distributed systems based on hypermedia. REST es independiente de cualquier protocolo subyacente y no está necesariamente unido a HTTP.REST is independent of any underlying protocol and is not necessarily tied to HTTP. Sin embargo, en las implementaciones más comunes de REST se usa HTTP como protocolo de aplicación, y esta guía se centra en el diseño de API de REST para HTTP.However, most common REST implementations use HTTP as the application protocol, and this guide focuses on designing REST APIs for HTTP.

Una de las principales ventajas de REST sobre HTTP es que usa estándares abiertos y no vincula la implementación de la API o de las aplicaciones cliente con ninguna implementación específica.A primary advantage of REST over HTTP is that it uses open standards, and does not bind the implementation of the API or the client applications any specific implementation. Por ejemplo, se podría escribir un servicio web de REST en ASP.NET, y las aplicaciones cliente pueden usar cualquier lenguaje o conjunto de herramientas que puedan generar solicitudes HTTP y analizar respuestas HTTP.For example, a REST web service could be written in ASP.NET, and client applications can use any language or toolset that can generate HTTP requests and parse HTTP responses.

Estos son algunos de los principios de diseño más importantes de las API de RESTful mediante HTTP:Here are some of the main design principles of RESTful APIs using HTTP:

  • Las API de REST se diseñan en torno a recursos, que son cualquier tipo de objeto, dato o servicio al que puede acceder el cliente.REST APIs are designed around resources, which are any kind of object, data, or service that can be accessed by the client.

  • Un recurso tiene un identificador, que es un URI que identifica de forma única ese recurso.A resource has an identifier, which is a URI that uniquely identifies that resource. Por ejemplo, el URI de un pedido de cliente en particular podría ser:For example, the URI for a particular customer order might be:

    http://adventure-works.com/orders/1
    
  • Los clientes interactúan con un servicio mediante el intercambio de representaciones de recursos.Clients interact with a service by exchanging representations of resources. Muchas API web usan JSON como formato de intercambio.Many web APIs use JSON as the exchange format. Por ejemplo, una solicitud GET al URI mencionado anteriormente podría devolver este cuerpo de respuesta:For example, a GET request to the URI listed above might return this response body:

    {"orderId":1,"orderValue":99.90,"productId":1,"quantity":1}
    
  • Las API de REST usan una interfaz uniforme, que ayuda a desacoplar las implementaciones de clientes y servicios.REST APIs use a uniform interface, which helps to decouple the client and service implementations. En las API REST basadas en HTTP, la interfaz uniforme incluye el uso de verbos HTTP estándar para realizar operaciones en los recursos.For REST APIs built on HTTP, the uniform interface includes using standard HTTP verbs to perform operations on resources. Las operaciones más comunes son GET, POST, PUT, PATCH y DELETE.The most common operations are GET, POST, PUT, PATCH, and DELETE.

  • Las API de REST usan un modelo de solicitud sin estado.REST APIs use a stateless request model. Las solicitudes HTTP deben ser independientes y pueden producirse en cualquier orden, por lo que no es factible conservar la información de estado transitoria entre solicitudes.HTTP requests should be independent and may occur in any order, so keeping transient state information between requests is not feasible. El único lugar donde se almacena la información es en los propios recursos y cada solicitud debe ser una operación atómica.The only place where information is stored is in the resources themselves, and each request should be an atomic operation. Esta restricción permite que los servicios web sean muy escalables, porque no es necesario conservar ninguna afinidad entre clientes y servidores específicos.This constraint enables web services to be highly scalable, because there is no need to retain any affinity between clients and specific servers. Cualquier servidor puede administrar cualquier solicitud de cualquier cliente.Any server can handle any request from any client. Ahora bien, otros factores pueden limitar la escalabilidad.That said, other factors can limit scalability. Por ejemplo, muchos servicios web escriben en un almacén de datos back-end, que puede ser difícil de escalar horizontalmente. (En el artículo Creación de particiones de datos se describen las estrategias para escalar horizontalmente un almacén de datos).For example, many web services write to a backend data store, which may be hard to scale out. (The article Data Partitioning describes strategies to scale out a data store.)

  • Las API de REST se controlan mediante vínculos de hipermedia contenidos en la representación.REST APIs are driven by hypermedia links that are contained in the representation. Por ejemplo, a continuación se muestra una representación JSON de un pedido.For example, the following shows a JSON representation of an order. Contiene vínculos para obtener o actualizar el cliente asociado con el pedido.It contains links to get or update the customer associated with the order.

    {
        "orderID":3,
        "productID":2,
        "quantity":4,
        "orderValue":16.60,
        "links": [
            {"rel":"product","href":"http://adventure-works.com/customers/3", "action":"GET" },
            {"rel":"product","href":"http://adventure-works.com/customers/3", "action":"PUT" } 
        ]
    } 
    

En 2008, Leonard Richardson propuso el siguiente modelo de madurez para las API web:In 2008, Leonard Richardson proposed the following maturity model for web APIs:

  • Nivel 0: definir un URI, y todas las operaciones son solicitudes POST a este URI.Level 0: Define one URI, and all operations are POST requests to this URI.
  • Nivel 1: crear distintos URI para recursos individuales.Level 1: Create separate URIs for individual resources.
  • Nivel 2: usar métodos HTTP para definir operaciones en los recursos.Level 2: Use HTTP methods to define operations on resources.
  • Nivel 3: usar hipermedia (HATEOAS, se describe a continuación).Level 3: Use hypermedia (HATEOAS, described below).

El nivel 3 corresponde a una API verdaderamente RESTful. de acuerdo con la definición del Fielding.Level 3 corresponds to a truly RESTful API according to Fielding's definition. En la práctica, muchas API web publicadas se sitúan más bien alrededor del nivel 2.In practice, many published web APIs fall somewhere around level 2.

Organización de la API en torno a los recursosOrganize the API around resources

Se centran en las entidades empresariales que expone la API web.Focus on the business entities that the web API exposes. Por ejemplo, en un sistema de comercio electrónico, las entidades principales podrían ser clientes y pedidos.For example, in an e-commerce system, the primary entities might be customers and orders. La creación de un pedido se puede lograr mediante el envío de una solicitud HTTP POST que contiene la información del pedido.Creating an order can be achieved by sending an HTTP POST request that contains the order information. La respuesta HTTP indica si el pedido se realizó correctamente o no.The HTTP response indicates whether the order was placed successfully or not. Siempre que sea posible, los URI de recursos deben basarse en nombres (el recurso) y no en verbos (las operaciones en el recurso).When possible, resource URIs should be based on nouns (the resource) and not verbs (the operations on the resource).

http://adventure-works.com/orders // Good

http://adventure-works.com/create-order // Avoid

Además, un recurso no tiene que estar basado en un solo elemento de datos físicos.A resource does not have to be based on a single physical data item. Por ejemplo, un recurso de pedido podría implementarse internamente en forma de varias tablas de una base de datos relacional, pero presentarse al cliente como una única entidad.For example, an order resource might be implemented internally as several tables in a relational database, but presented to the client as a single entity. Evite la creación de API que simplemente reflejen la estructura interna de una base de datos.Avoid creating APIs that simply mirror the internal structure of a database. La finalidad de REST es modelar entidades y las operaciones que una aplicación puede realizar sobre esas entidades.The purpose of REST is to model entities and the operations that an application can perform on those entities. Un cliente no debe exponerse a la implementación interna.A client should not be exposed to the internal implementation.

Las entidades a menudo se agrupan en colecciones (pedidos, clientes).Entities are often grouped together into collections (orders, customers). Una colección es un recurso independiente del elemento de la colección y debe tener su propio URI.A collection is a separate resource from the item within the collection, and should have its own URI. Por ejemplo, el siguiente URI podría representar la colección de pedidos:For example, the following URI might represent the collection of orders:

http://adventure-works.com/orders

Al enviar una solicitud HTTP GET al URI de la colección, se recupera una lista de elementos de la colección.Sending an HTTP GET request to the collection URI retrieves a list of items in the collection. Cada elemento de la colección también tiene su propio URI único.Each item in the collection also has its own unique URI. Una solicitud HTTP GET al URI del elemento devuelve los detalles de ese elemento.An HTTP GET request to the item's URI returns the details of that item.

Adopte una convención de nomenclatura coherente para los URI.Adopt a consistent naming convention in URIs. En general, resulta útil usar nombres plurales que hagan referencia a colecciones.In general, it helps to use plural nouns for URIs that reference collections. Es recomendable organizar los URI de colecciones y elementos en una jerarquía.It's a good practice to organize URIs for collections and items into a hierarchy. Por ejemplo, /customers es la ruta de acceso a la colección de clientes y /customers/5 es la ruta de acceso al cliente con el identificador igual a 5.For example, /customers is the path to the customers collection, and /customers/5 is the path to the customer with ID equal to 5. Este enfoque ayuda a mantener el carácter intuitivo de la API web.This approach helps to keep the web API intuitive. Además, muchas plataformas de API web pueden enrutar solicitudes basadas en rutas de acceso a URI con parámetros, así que podría definir una ruta para la ruta de acceso /customers/{id}.Also, many web API frameworks can route requests based on parameterized URI paths, so you could define a route for the path /customers/{id}.

Considere también las relaciones entre los diferentes tipos de recursos y cómo podría exponer estas asociaciones.Also consider the relationships between different types of resources and how you might expose these associations. Por ejemplo, /customers/5/orders podría representar todos los pedidos del cliente 5.For example, the /customers/5/orders might represent all of the orders for customer 5. También puede ir en la otra dirección y representar la asociación de un pedido con un cliente con un URI como /orders/99/customer.You could also go in the other direction, and represent the association from an order back to a customer with a URI such as /orders/99/customer. Sin embargo, este modelo llevado demasiado lejos puede ser difícil de implementar.However, extending this model too far can become cumbersome to implement. Una solución mejor es proporcionar vínculos navegables a los recursos asociados en el cuerpo del mensaje de respuesta HTTP.A better solution is to provide navigable links to associated resources in the body of the HTTP response message. Este mecanismo se describe con más detalle en la sección Uso del enfoque HATEOAS para permitir la navegación a los recursos relacionados más adelante.This mechanism is described in more detail in the section Using the HATEOAS Approach to Enable Navigation To Related Resources later.

En sistemas más complejos, puede resultar tentador proporcionar identificadores URI que permitan que un cliente navegue por varios niveles de relaciones, como /customers/1/orders/99/products.In more complex systems, it can be tempting to provide URIs that enable a client to navigate through several levels of relationships, such as /customers/1/orders/99/products. Sin embargo, este nivel de complejidad puede ser difícil de mantener y es inflexible si las relaciones entre los recursos cambian en el futuro.However, this level of complexity can be difficult to maintain and is inflexible if the relationships between resources change in the future. En su lugar, intente que los identificadores URI sean relativamente sencillos.Instead, try to keep URIs relatively simple. Una vez que una aplicación tiene una referencia a un recurso, debería ser posible usar esta referencia para buscar los elementos relacionados con ese recurso.Once an application has a reference to a resource, it should be possible to use this reference to find items related to that resource. La consulta anterior se puede reemplazar por el URI /customers/1/orders para buscar todos los pedidos del cliente 1 y, a continuación, por /orders/99/products para buscar los productos de este pedido.The preceding query can be replaced with the URI /customers/1/orders to find all the orders for customer 1, and then /orders/99/products to find the products in this order.

Sugerencia

Evite el uso de URI de recursos más complejos que collection/item/collection.Avoid requiring resource URIs more complex than collection/item/collection.

Otro factor es que todas las solicitudes web imponen una carga en el servidor web.Another factor is that all web requests impose a load on the web server. Cuantas más solicitudes, más grande la carga.The more requests, the bigger the load. Por lo tanto, intente evitar las API web "locuaces" que exponen un gran número de recursos pequeños.Therefore, try to avoid "chatty" web APIs that expose a large number of small resources. Una API de este tipo puede requerir que una aplicación cliente envíe varias solicitudes para encontrar todos los datos que necesita.Such an API may require a client application to send multiple requests to find all of the data that it requires. En su lugar, puede que desee desnormalizar los datos y combinar la información relacionada en recursos más grandes que se puedan recuperar con una única solicitud.Instead, you might want to denormalize the data and combine related information into bigger resources that can be retrieved with a single request. Sin embargo, debe equilibrar este enfoque con la sobrecarga de la captura de datos que el cliente no necesita.However, you need to balance this approach against the overhead of fetching data that the client doesn't need. Recuperar objetos grandes puede aumentar la latencia de una solicitud y generar costos de ancho de banda adicionales.Retrieving large objects can increase the latency of a request and incur additional bandwidth costs. Para más información sobre estos antipatrones de rendimiento, consulte Antipatrón Chatty I/O y Extraneous Fetching.For more information about these performance antipatterns, see Chatty I/O and Extraneous Fetching.

Evite la introducción de dependencias entre la API web y los orígenes de datos subyacentes.Avoid introducing dependencies between the web API and the underlying data sources. Por ejemplo, si los datos están almacenados en una base de datos relacional, la API web no necesita exponer cada una de las tablas como una colección de recursos.For example, if your data is stored in a relational database, the web API doesn't need to expose each table as a collection of resources. De hecho, ese sea probablemente un mal diseño.In fact, that's probably a poor design. En su lugar, considere la API web como una abstracción de la base de datos.Instead, think of the web API as an abstraction of the database. Si es necesario, introduzca una capa de asignación entre la base de datos y la API web.If necessary, introduce a mapping layer between the database and the web API. De este modo, las aplicaciones cliente se aíslan de los cambios en el esquema de base de datos subyacente.That way, client applications are isolated from changes to the underlying database scheme.

Por último, no sería posible asignar cada operación que implementa una API web a un recurso concreto.Finally, it might not be possible to map every operation implemented by a web API to a specific resource. Tales escenarios sin recursos se pueden administrar mediante solicitudes HTTP que invocan una función y devuelven los resultados en forma de un mensaje de respuesta HTTP.You can handle such non-resource scenarios through HTTP requests that invoke a function and return the results as an HTTP response message. Por ejemplo, una API web que implementa operaciones sencillas de tipo calculadora como sumar y restar podría proporcionar identificadores URI que expongan estas operaciones como seudorecursos y usar la cadena de consulta para especificar los parámetros necesarios.For example, a web API that implements simple calculator operations such as add and subtract could provide URIs that expose these operations as pseudo resources and use the query string to specify the parameters required. Por ejemplo, una solicitud GET al URI /add?operand1=99&operand2=1 devolvería un mensaje de respuesta donde el cuerpo contiene el valor 100.For example a GET request to the URI /add?operand1=99&operand2=1 would return a response message with the body containing the value 100. Sin embargo, únicamente use estas formas de URI con moderación.However, only use these forms of URIs sparingly.

Definición de operaciones en términos de métodos HTTPDefine operations in terms of HTTP methods

El protocolo HTTP define una serie de métodos que asignan significado semántico a una solicitud.The HTTP protocol defines a number of methods that assign semantic meaning to a request. Los métodos HTTP comunes que usan la mayoría de las API web RESTful son:The common HTTP methods used by most RESTful web APIs are:

  • GET recupera una representación del recurso en el URI especificado.GET retrieves a representation of the resource at the specified URI. El cuerpo del mensaje de respuesta contiene los detalles del recurso solicitado.The body of the response message contains the details of the requested resource.
  • POST crea un nuevo recurso en el URI especificado.POST creates a new resource at the specified URI. El cuerpo del mensaje de solicitud proporciona los detalles del nuevo recurso.The body of the request message provides the details of the new resource. Tenga en cuenta que POST también puede usarse para desencadenar operaciones que en realidad no crean recursos.Note that POST can also be used to trigger operations that don't actually create resources.
  • PUT crea o sustituye el recurso en el URI especificado.PUT either creates or replaces the resource at the specified URI. El cuerpo del mensaje de solicitud especifica el recurso que se va a crear o actualizar.The body of the request message specifies the resource to be created or updated.
  • PATCH realiza una actualización parcial de un recurso.PATCH performs a partial update of a resource. El cuerpo de la solicitud especifica el conjunto de cambios que se aplican al recurso.The request body specifies the set of changes to apply to the resource.
  • DELETE quita el recurso en el URI especificado.DELETE removes the resource at the specified URI.

El efecto de una solicitud específica debería depender de si el recurso es una colección o un elemento individual.The effect of a specific request should depend on whether the resource is a collection or an individual item. En la tabla siguiente se resumen las convenciones comunes adoptadas por la mayoría de las implementaciones de RESTful usando el ejemplo de comercio electrónico.The following table summarizes the common conventions adopted by most RESTful implementations using the ecommerce example. Tenga en cuenta que no todas estas solicitudes se pueden implementar; depende de cada situación específica.Note that not all of these requests might be implemented; it depends on the specific scenario.

RecursoResource POSTPOST GETGET PUTPUT DELETEDELETE
/customers/customers Crear un nuevo clienteCreate a new customer Recuperar todos los clientesRetrieve all customers Actualización masiva de clientesBulk update of customers Eliminar todos los clientesRemove all customers
/customers/1/customers/1 ErrorError Recuperar los detalles del cliente 1Retrieve the details for customer 1 Actualizar los detalles del cliente 1 si existeUpdate the details of customer 1 if it exists Quitar al cliente 1Remove customer 1
/customers/1/orders/customers/1/orders Crear un nuevo pedido para el cliente 1Create a new order for customer 1 Recuperar todos los pedidos del cliente 1Retrieve all orders for customer 1 Actualización masiva de pedidos del cliente 1Bulk update of orders for customer 1 Recuperar todos los pedidos del cliente 1Remove all orders for customer 1

Las diferencias entre POST, PUT y PATCH pueden resultar confusas.The differences between POST, PUT, and PATCH can be confusing.

  • Una solicitud POST crea un recurso.A POST request creates a resource. El servidor le asigna un URI y devuelve ese URI al cliente.The server assigns a URI for the new resource, and returns that URI to the client. En el modelo REST, con frecuencia se aplican solicitudes POST a colecciones.In the REST model, you frequently apply POST requests to collections. El nuevo recurso se agrega a la colección.The new resource is added to the collection. Una solicitud POST se puede usar también para enviar datos a un recurso existente para su procesamiento, sin que se cree ningún nuevo recurso.A POST request can also be used to submit data for processing to an existing resource, without any new resource being created.

  • Una solicitud PUT crea un recurso o actualiza un recurso existente.A PUT request creates a resource or updates an existing resource. El cliente especifica el URI del recurso.The client specifies the URI for the resource. El cuerpo de la solicitud contiene una representación completa del recurso.The request body contains a complete representation of the resource. Si ya existe un recurso con este URI, se reemplaza.If a resource with this URI already exists, it is replaced. De lo contrario se crea un nuevo recurso, si el servidor así lo admite.Otherwise a new resource is created, if the server supports doing so. Las solicitudes PUT se aplican con más frecuencia a recursos que son elementos individuales, por ejemplo, un cliente especifico, en lugar de colecciones.PUT requests are most frequently applied to resources that are individual items, such as a specific customer, rather than collections. Un servidor puede admitir actualizaciones, pero no la creación mediante PUT,A server might support updates but not creation via PUT. si ello depende de que el cliente pueda asignar un URI de manera significativa a un recurso antes de que exista.Whether to support creation via PUT depends on whether the client can meaningfully assign a URI to a resource before it exists. Si este no es el caso, use POST para crear recursos y PUT o PATCH para actualizarlos.If not, then use POST to create resources and PUT or PATCH to update.

  • Una solicitud PATCH realiza una actualización parcial de un recurso existente.A PATCH request performs a partial update to an existing resource. El cliente especifica el URI del recurso.The client specifies the URI for the resource. El cuerpo de la solicitud especifica un conjunto de cambios para aplicar al recurso.The request body specifies a set of changes to apply to the resource. Este enfoque puede ser más eficaz que el uso de PUT, dado que el cliente solo envía los cambios, no la representación completa del recurso.This can be more efficient than using PUT, because the client only sends the changes, not the entire representation of the resource. Técnicamente PATCH puede crear también un nuevo recurso (mediante la especificación de un conjunto de actualizaciones en un recurso "nulo"), si el servidor así lo admite.Technically PATCH can also create a new resource (by specifying a set of updates to a "null" resource), if the server supports this.

Las solicitudes PUT deben ser idempotentes.PUT requests must be idempotent. Si un cliente envía la misma solicitud PUT varias veces, los resultados siempre deben ser los mismos (el mismo recurso se modificará con los mismos valores).If a client submits the same PUT request multiple times, the results should always be the same (the same resource will be modified with the same values). No se garantiza que las solicitudes POST y PATCH sean idempotentes.POST and PATCH requests are not guaranteed to be idempotent.

Conformidad con la semántica HTTPConform to HTTP semantics

En esta sección se describen algunas consideraciones habituales para diseñar una API que guarde conformidad con la especificación HTTP.This section describes some typical considerations for designing an API that conforms to the HTTP specification. Sin embargo, no se tratan todos los posibles detalles o escenarios.However, it doesn't cover every possible detail or scenario. En caso de duda, consulte las especificaciones HTTP.When in doubt, consult the HTTP specifications.

Tipos de mediosMedia types

Como se mencionó anteriormente, los clientes y servidores intercambian representaciones de recursos.As mentioned earlier, clients and servers exchange representations of resources. Por ejemplo, en una solicitud POST, el cuerpo de la solicitud contiene una representación del recurso que se va a crear.For example, in a POST request, the request body contains a representation of the resource to create. En una solicitud GET, el cuerpo de respuesta contiene una representación del recurso capturado.In a GET request, the response body contains a representation of the fetched resource.

En el protocolo HTTP, los formatos se especifican mediante el uso de tipos de medios, también denominados tipos MIME.In the HTTP protocol, formats are specified through the use of media types, also called MIME types. En el caso de datos no binarios, la mayoría de las API web admiten JSON (tipo de medio = application/json) y posiblemente XML (tipo de medio = application/xml).For non-binary data, most web APIs support JSON (media type = application/json) and possibly XML (media type = application/xml).

El encabezado Content-Type en una solicitud o respuesta especifica el formato de la representación.The Content-Type header in a request or response specifies the format of the representation. Este es un ejemplo de una solicitud POST que incluye datos JSON:Here is an example of a POST request that includes JSON data:

POST http://adventure-works.com/orders HTTP/1.1
Content-Type: application/json; charset=utf-8
Content-Length: 57

{"Id":1,"Name":"Gizmo","Category":"Widgets","Price":1.99}

Si el servidor no admite el tipo de medio, debe devolver el código de estado HTTP 415 (tipo de medio no compatible).If the server doesn't support the media type, it should return HTTP status code 415 (Unsupported Media Type).

Una solicitud de cliente puede incluir un encabezado Accept que contenga una lista de tipos de medios que el cliente aceptará del servidor en el mensaje de respuesta.A client request can include an Accept header that contains a list of media types the client will accept from the server in the response message. Por ejemplo: For example:

GET http://adventure-works.com/orders/2 HTTP/1.1
Accept: application/json

Si el servidor no puede encontrar la correspondencia con ninguno de los tipos de medios enumerados, debe devolver el código de estado HTTP 406 (No aceptable).If the server cannot match any of the media type(s) listed, it should return HTTP status code 406 (Not Acceptable).

Métodos GETGET methods

Normalmente, un método GET correcto devuelve el código de estado HTTP 200 (Correcto).A successful GET method typically returns HTTP status code 200 (OK). Si no se encuentra el recurso, el método debe devolver 404 (No encontrado).If the resource cannot be found, the method should return 404 (Not Found).

Métodos POSTPOST methods

Si un método POST crea un nuevo recurso, devuelve el código de estado HTTP 201 (Creado).If a POST method creates a new resource, it returns HTTP status code 201 (Created). El URI del nuevo recurso se incluye en el encabezado Location de la respuesta.The URI of the new resource is included in the Location header of the response. El cuerpo de respuesta contiene una representación del recurso.The response body contains a representation of the resource.

Si el método realiza algún procesamiento pero no crea un nuevo recurso, puede devolver el código de estado HTTP 200 e incluir el resultado de la operación en el cuerpo de respuesta.If the method does some processing but does not create a new resource, the method can return HTTP status code 200 and include the result of the operation in the response body. O bien, si no hay ningún resultado para devolver, el método puede devolver el código de estado HTTP 204 (Sin contenido) sin cuerpo de respuesta.Alternatively, if there is no result to return, the method can return HTTP status code 204 (No Content) with no response body.

Si el cliente coloca datos no válidos en la solicitud, el servidor debe devolver el código de estado HTTP 400 (Solicitud incorrecta).If the client puts invalid data into the request, the server should return HTTP status code 400 (Bad Request). El cuerpo de respuesta puede contener información adicional sobre el error o un vínculo a un URI que proporciona más detalles.The response body can contain additional information about the error or a link to a URI that provides more details.

Métodos PUTPUT methods

Si un método PUT crea un nuevo recurso, devuelve el código de estado HTTP 201 (Creado), al igual que con un método POST.If a PUT method creates a new resource, it returns HTTP status code 201 (Created), as with a POST method. Si el método actualiza un recurso existente, devuelve 200 (Correcto) o 204 (Sin contenido).If the method updates an existing resource, it returns either 200 (OK) or 204 (No Content). En algunos casos, no será posible actualizar un recurso existente.In some cases, it might not be possible to update an existing resource. En ese caso, considere la posibilidad de devolver el código de estado HTTP 409 (Conflicto).In that case, consider returning HTTP status code 409 (Conflict).

Considere la posibilidad de implementar operaciones HTTP PUT masivas que pueden procesar por lotes las actualizaciones de varios recursos de una colección.Consider implementing bulk HTTP PUT operations that can batch updates to multiple resources in a collection. La solicitud PUT debe especificar el URI de la colección y el cuerpo de solicitud debe especificar los detalles de los recursos que se van a modificar.The PUT request should specify the URI of the collection, and the request body should specify the details of the resources to be modified. Este enfoque puede ayudar a reducir el intercambio de mensajes y mejorar el rendimiento.This approach can help to reduce chattiness and improve performance.

Métodos PATCHPATCH methods

Con una solicitud PATCH, el cliente envía un conjunto de actualizaciones a un recurso existente, en forma de un documento de revisión.With a PATCH request, the client sends a set of updates to an existing resource, in the form of a patch document. El servidor procesa el documento de revisión para realizar la actualización.The server processes the patch document to perform the update. El documento de revisión no describe el recurso completo, solo un conjunto de cambios para aplicar.The patch document doesn't describe the whole resource, only a set of changes to apply. La especificación del método PATCH (RFC 5789) no define un formato determinado de documentos de revisión.The specification for the PATCH method (RFC 5789) doesn't define a particular format for patch documents. El formato debe deducirse del tipo de medio de la solicitud.The format must be inferred from the media type in the request.

JSON es probablemente el formato de datos más común para las API web.JSON is probably the most common data format for web APIs. Hay dos formatos principales de revisión basados en JSON, que se conocen como revisión JSON y revisión de combinación JSON.There are two main JSON-based patch formats, called JSON patch and JSON merge patch.

La revisión de combinación JSON es algo más simple.JSON merge patch is somewhat simpler. El documento de revisión tiene la misma estructura que el recurso original JSON, pero incluye solo el subconjunto de campos que se deben cambiar o agregar.The patch document has the same structure as the original JSON resource, but includes just the subset of fields that should be changed or added. Además, se puede eliminar un campo mediante la especificación de null como valor del campo en el documento de revisión.In addition, a field can be deleted by specifying null for the field value in the patch document. (Eso significa que la revisión de combinación no es adecuada si el recurso original puede tener valores null explícitos).(That means merge patch is not suitable if the original resource can have explicit null values.)

Por ejemplo, suponga que el recurso original tiene la representación JSON siguiente:For example, suppose the original resource has the following JSON representation:

{ 
    "name":"gizmo",
    "category":"widgets",
    "color":"blue",
    "price":10
}

Esta es una posible revisión de combinación JSON para este recurso:Here is a possible JSON merge patch for this resource:

{ 
    "price":12,
    "color":null,
    "size":"small"
}

Esta revisión indica al servidor que actualice el valor de "price", elimine el valor de "color" y agregue un valor para "size".This tells the server to update "price", delete "color", and add "size". "Name" y "category" no se modifican."Name" and "category" are not modified. Para conocer los detalles exactos de la revisión de combinación JSON, consulte RFC 7396.For the exact details of JSON merge patch, see RFC 7396. El tipo de medio para la revisión de combinación JSON es "application/merge-patch + json".The media type for JSON merge patch is "application/merge-patch+json".

La revisión de combinación no es adecuada si el recurso original puede contener valores null explícitos, debido al significado especial de null en el documento de revisión.Merge patch is not suitable if the original resource can contain explicit null values, due to the special meaning of null in the patch document. Además, el documento de revisión no especifica el orden en el que el servidor debe aplicar las actualizaciones.Also, the patch document doesn't specify the order that the server should apply the updates. Eso puede ser o no importante, según los datos y el dominio.That may or may not matter, depending on the data and the domain. La revisión JSON, definida en RFC 6902, es más flexible.JSON patch, defined in RFC 6902, is more flexible. Los cambios se especifican como una secuencia de operaciones que se aplicarán.It specifies the changes as a sequence of operations to apply. Las operaciones incluyen agregar, quitar, reemplazar, copiar y probar (para validar los valores).Operations include add, remove, replace, copy, and test (to validate values). El tipo de medio para la revisión JSON es "application/json-patch + json".The media type for JSON patch is "application/json-patch+json".

Estas son algunas condiciones de error habituales que podrían producirse al procesar una solicitud PATCH, junto con el código de estado HTTP adecuado.Here are some typical error conditions that might be encountered when processing a PATCH request, along with the appropriate HTTP status code.

Condición de errorError condition Código de estado HTTPHTTP status code
No se admite el formato de documento de revisión.The patch document format isn't supported. 415 (Tipo de medio no compatible)415 (Unsupported Media Type)
El documento de revisión tiene un formato incorrecto.Malformed patch document. 400 (Solicitud incorrecta)400 (Bad Request)
El documento de revisión es válido, pero los cambios no se pueden aplicar al recurso en su estado actual.The patch document is valid, but the changes can't be applied to the resource in its current state. 409 (Conflicto)409 (Conflict)

Métodos DELETEDELETE methods

Si la operación de eliminación es correcta, el servidor web debe responder con el código de estado HTTP 204, que indica que el proceso se ha administrado correctamente, pero que el cuerpo de respuesta no contiene información adicional.If the delete operation is successful, the web server should respond with HTTP status code 204, indicating that the process has been successfully handled, but that the response body contains no further information. Si el recurso no existe, el servidor web puede devolver HTTP 404 (No encontrado).If the resource doesn't exist, the web server can return HTTP 404 (Not Found).

Operaciones asincrónicasAsynchronous operations

En ocasiones, una operación POST, PUT, PATCH o DELETE podría requerir procesamiento que tarda algún tiempo en completarse.Sometimes a POST, PUT, PATCH, or DELETE operation might require processing that takes awhile to complete. Si espera a que finalice antes de enviar una respuesta al cliente, podría producirse una latencia inaceptable.If you wait for completion before sending a response to the client, it may cause unacceptable latency. En este caso, considere la posibilidad de realizar la operación asincrónica.If so, consider making the operation asynchronous. Se devuelve el código de estado HTTP 202 (Aceptado) para indicar que se aceptó la solicitud para el procesamiento, pero no se ha completado.Return HTTP status code 202 (Accepted) to indicate the request was accepted for processing but is not completed.

Debe exponer un punto de conexión que devuelva el estado de una solicitud asincrónica, así el cliente puede supervisar el estado mediante el sondeo del punto de conexión de estado.You should expose an endpoint that returns the status of an asynchronous request, so the client can monitor the status by polling the status endpoint. Incluya el URI del punto de conexión de estado en el encabezado Location de la respuesta 202.Include the URI of the status endpoint in the Location header of the 202 response. Por ejemplo: For example:

HTTP/1.1 202 Accepted
Location: /api/status/12345

Si el cliente envía una solicitud GET a este punto de conexión, la respuesta debe contener el estado actual de la solicitud.If the client sends a GET request to this endpoint, the response should contain the current status of the request. Opcionalmente, también puede incluir un tiempo de finalización estimado o un vínculo para cancelar la operación.Optionally, it could also include an estimated time to completion or a link to cancel the operation.

HTTP/1.1 200 OK
Content-Type: application/json

{
    "status":"In progress",
    "link": { "rel":"cancel", "method":"delete", "href":"/api/status/12345" }
}

Si la operación asincrónica crea un nuevo recurso, el punto de conexión de estado debe devolver el código de estado 303 (ver Otros) una vez completada la operación.If the asynchronous operation creates a new resource, the status endpoint should return status code 303 (See Other) after the operation completes. En la respuesta 303, se incluye un encabezado Location que proporciona el URI del nuevo recurso:In the 303 response, include a Location header that gives the URI of the new resource:

HTTP/1.1 303 See Other
Location: /api/orders/12345

Para más información, consulte Asynchronous operations in REST (Operaciones asincrónicas en REST).For more information, see Asynchronous operations in REST.

Filtrado y paginación de los datosFilter and paginate data

Exponer una colección de recursos con un único URI puede dar lugar a que las aplicaciones capturen grandes cantidades de datos cuando solo se requiere un subconjunto de la información.Exposing a collection of resources through a single URI can lead to applications fetching large amounts of data when only a subset of the information is required. Por ejemplo, suponga que una aplicación cliente necesita encontrar todos los pedidos con un costo cercano a un valor específico.For example, suppose a client application needs to find all orders with a cost over a specific value. Se podrían recuperar todos los pedidos del URI /orders y, a continuación, filtrar estos pedidos en el lado cliente.It might retrieve all orders from the /orders URI and then filter these orders on the client side. Es obvio que este proceso es muy ineficaz.Clearly this process is highly inefficient. Se malgasta ancho de banda de red y potencia de procesamiento en el servidor que hospeda la API web.It wastes network bandwidth and processing power on the server hosting the web API.

En su lugar, la API puede permitir que pase un filtro en la cadena de consulta del URI, como /orders?minCost=n.Instead, the API can allow passing a filter in the query string of the URI, such as /orders?minCost=n. La API web es responsable entonces de analizar y administrar el parámetro minCost en la cadena de consulta y de devolver los resultados filtrados en el lado servidor.The web API is then responsible for parsing and handling the minCost parameter in the query string and returning the filtered results on the sever side.

Las solicitudes GET sobre recursos de la colección pueden devolver posiblemente un gran número de elementos.GET requests over collection resources can potentially return a large number of items. Debe diseñar una API que limite la cantidad de datos devueltos en una única solicitud.You should design a web API to limit the amount of data returned by any single request. Considere la posibilidad de admitir cadenas de consulta que especifiquen el número máximo de elementos que se van a recuperar y un desplazamiento inicial en la colección.Consider supporting query strings that specify the maximum number of items to retrieve and a starting offset into the collection. Por ejemplo: For example:

/orders?limit=25&offset=50

Considere también la posibilidad de imponer un límite superior sobre el número de elementos devueltos, para ayudar a evitar ataques por denegación de servicio.Also consider imposing an upper limit on the number of items returned, to help prevent Denial of Service attacks. Para ayudar a las aplicaciones cliente, las solicitudes GET que devuelven datos paginados deben incluir también alguna forma de metadatos que indiquen el número total de recursos disponibles en la colección.To assist client applications, GET requests that return paginated data should also include some form of metadata that indicate the total number of resources available in the collection. También puede considerar otras estrategias de paginación inteligente; para obtener más información, consulte Notas para el diseño de API: paginación inteligenteYou might also consider other intelligent paging strategies; for more information, see API Design Notes: Smart Paging

Puede seguir una estrategia parecida para ordenar los datos que se capturan y proporcionar un parámetro de clasificación que tome un nombre de campo como valor, por ejemplo /orders?sort=ProductID.You can use a similar strategy to sort data as it is fetched, by providing a sort parameter that takes a field name as the value, such as /orders?sort=ProductID. Sin embargo, este enfoque puede tener un efecto negativo sobre el almacenamiento en caché, dado que los parámetros de la cadena de consulta forman parte del identificador de recursos que se usa en muchas implementaciones de caché como llave a los datos en caché.However, this approach can have a negative effect on caching, because query string parameters form part of the resource identifier used by many cache implementations as the key to cached data.

Puede ampliar este enfoque para limitar los campos devueltos para cada elemento, si cada elemento contiene una gran cantidad de datos.You can extend this approach to limit the fields returned for each item, if each item contains a large amount of data. Por ejemplo, podría usar un parámetro de cadena de consulta que acepte una lista de campos delimitados por coma, como /orders?fields=ProductID,Quantity.For example, you could use a query string parameter that accepts a comma-delimited list of fields, such as /orders?fields=ProductID,Quantity.

Asigne a todos los parámetros opcionales de las cadenas de consulta valores predeterminados.Give all optional parameters in query strings meaningful defaults. Por ejemplo, establezca el parámetro limit en 10 y el parámetro offset en 0 si implementa paginación, establezca el parámetro de ordenación en la clave del recurso si implementa ordenación y establezca el parámetro fields en todos los campos del recurso si admite proyecciones.For example, set the limit parameter to 10 and the offset parameter to 0 if you implement pagination, set the sort parameter to the key of the resource if you implement ordering, and set the fields parameter to all fields in the resource if you support projections.

Compatibilidad con respuestas parciales en recursos binarios de gran tamañoSupport partial responses for large binary resources

Un recurso puede contener campos binarios de gran tamaño, como imágenes o archivos.A resource may contain large binary fields, such as files or images. Para solucionar los problemas ocasionados por conexiones intermitentes y poco confiables y para mejorar los tiempos de respuesta, considere la posibilidad de permitir que estos recursos se recuperen en fragmentos.To overcome problems caused by unreliable and intermittent connections and to improve response times, consider enabling such resources to be retrieved in chunks. Para ello, la API web debe admitir el encabezado Accept-Ranges en solicitudes GET de recursos de gran tamaño.To do this, the web API should support the Accept-Ranges header for GET requests for large resources. Este encabezado indica que la operación GET admite solicitudes parciales.This header indicates that the GET operation supports partial requests. La aplicación cliente puede enviar solicitudes GET que devuelven un subconjunto de un recurso, especificado como un intervalo de bytes.The client application can submit GET requests that return a subset of a resource, specified as a range of bytes.

Además, considere la posibilidad de implementar solicitudes HTTP HEAD para estos recursos.Also, consider implementing HTTP HEAD requests for these resources. Una solicitud HEAD es similar a una solicitud GET, excepto que solo devuelve los encabezados HTTP que describen el recurso, con un cuerpo de mensaje vacío.A HEAD request is similar to a GET request, except that it only returns the HTTP headers that describe the resource, with an empty message body. Una aplicación cliente puede emitir una solicitud HEAD para determinar si se debe capturar un recurso mediante solicitudes GET parciales.A client application can issue a HEAD request to determine whether to fetch a resource by using partial GET requests. Por ejemplo: For example:

HEAD http://adventure-works.com/products/10?fields=productImage HTTP/1.1

Este es un ejemplo de un mensaje de respuesta:Here is an example response message:

HTTP/1.1 200 OK

Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 4580

El encabezado Content-Length proporciona el tamaño total del recurso, y el encabezado Accept-Ranges indica que la operación GET correspondiente admite resultados parciales.The Content-Length header gives the total size of the resource, and the Accept-Ranges header indicates that the corresponding GET operation supports partial results. La aplicación cliente puede usar esta información para recuperar la imagen en fragmentos más pequeños.The client application can use this information to retrieve the image in smaller chunks. La primera solicitud captura los primeros 2500 bytes mediante el encabezado Range:The first request fetches the first 2500 bytes by using the Range header:

GET http://adventure-works.com/products/10?fields=productImage HTTP/1.1
Range: bytes=0-2499

El mensaje de respuesta indica que es una respuesta parcial al devolver el código de estado HTTP 206.The response message indicates that this is a partial response by returning HTTP status code 206. El encabezado Content-Length especifica el número real de bytes devuelto en el cuerpo del mensaje (no el tamaño del recurso) y el encabezado Content-Range indica qué parte del recurso es (bytes 0-2499 de 4580):The Content-Length header specifies the actual number of bytes returned in the message body (not the size of the resource), and the Content-Range header indicates which part of the resource this is (bytes 0-2499 out of 4580):

HTTP/1.1 206 Partial Content

Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 2500
Content-Range: bytes 0-2499/4580

[...]

Una solicitud posterior desde la aplicación cliente puede recuperar el resto del recurso.A subsequent request from the client application can retrieve the remainder of the resource.

Uno de los principales propósitos que se esconden detrás de REST es que debe ser posible navegar por todo el conjunto de recursos sin necesidad de conocer el esquema de URI.One of the primary motivations behind REST is that it should be possible to navigate the entire set of resources without requiring prior knowledge of the URI scheme. Cada solicitud HTTP GET debe devolver la información necesaria para encontrar los recursos relacionados directamente con el objeto solicitado mediante los hipervínculos que se incluyen en la respuesta, y también se le debe proporcionar información que describa las operaciones disponibles en cada uno de estos recursos.Each HTTP GET request should return the information necessary to find the resources related directly to the requested object through hyperlinks included in the response, and it should also be provided with information that describes the operations available on each of these resources. Este principio se conoce como HATEOAS, del inglés Hypertext as the Engine of Application State (Hipertexto como motor del estado de la aplicación).This principle is known as HATEOAS, or Hypertext as the Engine of Application State. El sistema es realmente una máquina de estado finito, y la respuesta a cada solicitud contiene la información necesaria para pasar de un estado a otro; ninguna otra información debería ser necesaria.The system is effectively a finite state machine, and the response to each request contains the information necessary to move from one state to another; no other information should be necessary.

Nota

Actualmente no hay ninguna norma o especificación que define cómo modelar el principio HATEOAS.Currently there are no standards or specifications that define how to model the HATEOAS principle. Los ejemplos mostrados en esta sección muestran una posible solución.The examples shown in this section illustrate one possible solution.

Por ejemplo, para administrar la relación entre un pedido y un cliente, la representación de un pedido podría incluir vínculos que identifican las operaciones disponibles para el cliente del pedido.For example, to handle the relationship between an order and a customer, the representation of an order could include links that identify the available operations for the customer of the order. Esta sería una posible representación:Here is a possible representation:

{
  "orderID":3,
  "productID":2,
  "quantity":4,
  "orderValue":16.60,
  "links":[
    {
      "rel":"customer",
      "href":"http://adventure-works.com/customers/3", 
      "action":"GET",
      "types":["text/xml","application/json"] 
    },
    {
      "rel":"customer",
      "href":"http://adventure-works.com/customers/3", 
      "action":"PUT",
      "types":["application/x-www-form-urlencoded"]
    },
    {
      "rel":"customer",
      "href":"http://adventure-works.com/customers/3",
      "action":"DELETE",
      "types":[]
    },
    {
      "rel":"self",
      "href":"http://adventure-works.com/orders/3", 
      "action":"GET",
      "types":["text/xml","application/json"]
    },
    {
      "rel":"self",
      "href":"http://adventure-works.com/orders/3", 
      "action":"PUT",
      "types":["application/x-www-form-urlencoded"]
    },
    {
      "rel":"self",
      "href":"http://adventure-works.com/orders/3", 
      "action":"DELETE",
      "types":[]
    }]
}

En este ejemplo, la matriz links tiene un conjunto de vínculos.In this example, the links array has a set of links. Cada vínculo representa una operación en una entidad relacionada.Each link represents an operation on a related entity. Los datos de cada vínculo incluyen la relación ("customer"), el URI (http://adventure-works.com/customers/3), el método HTTP y el tipo MIME admitido.The data for each link includes the relationship ("customer"), the URI (http://adventure-works.com/customers/3), the HTTP method, and the supported MIME types. Esta es toda la información que necesita una aplicación cliente para invocar la operación.This is all the information that a client application needs to be able to invoke the operation.

La matriz links también incluye información con una referencia a sí misma sobre el recurso propiamente dicho que se ha recuperado.The links array also includes self-referencing information about the resource itself that has been retrieved. Este tiene la relación self.These have the relationship self.

El conjunto de vínculos que se devuelve puede cambiar, según el estado del recurso.The set of links that are returned may change, depending on the state of the resource. A esto nos referimos cuando decimos que el hipertexto es el "motor de estado de aplicación".This is what is meant by hypertext being the "engine of application state."

Control de versiones de una API web RESTfulVersioning a RESTful web API

Es muy poco probable que una API web permanezca estática.It is highly unlikely that a web API will remain static. Conforme los requisitos empresariales cambian, se pueden agregar nuevas colecciones de recursos, las relaciones entre los recursos pueden cambiar y la estructura de los datos de los recursos puede rectificarse.As business requirements change new collections of resources may be added, the relationships between resources might change, and the structure of the data in resources might be amended. Si bien la actualización de una API para controlar los requisitos nuevos o diferentes es un proceso relativamente sencillo, debe tener en cuenta los efectos que tendrán dichos cambios en las aplicaciones cliente que utilizan la API web.While updating a web API to handle new or differing requirements is a relatively straightforward process, you must consider the effects that such changes will have on client applications consuming the web API. El problema es que, aunque el desarrollador que diseña e implementa una API web tiene control total sobre dicha API, el desarrollador carece del mismo grado de control sobre las aplicaciones cliente que podrían crear organizaciones de terceros que operan de forma remota.The issue is that although the developer designing and implementing a web API has full control over that API, the developer does not have the same degree of control over client applications which may be built by third party organizations operating remotely. La premisa principal es permitir que las aplicaciones cliente existentes sigan funcionando sin cambios y al mismo tiempo dejar que las nuevas aplicaciones cliente aprovechen las ventajas de nuevas características y recursos.The primary imperative is to enable existing client applications to continue functioning unchanged while allowing new client applications to take advantage of new features and resources.

El control de versiones permite que una API web indique las características y recursos que expone y que una aplicación cliente pueda enviar solicitudes que se dirijan a una versión específica de una característica o un recurso.Versioning enables a web API to indicate the features and resources that it exposes, and a client application can submit requests that are directed to a specific version of a feature or resource. En las secciones siguientes se describen varios enfoques diferentes, cada uno de los cuales tiene sus propias ventajas y desventajas.The following sections describe several different approaches, each of which has its own benefits and trade-offs.

Sin control de versionesNo versioning

Este es el enfoque más sencillo y puede ser aceptable para algunas API internas.This is the simplest approach, and may be acceptable for some internal APIs. Los grandes cambios podrían representarse como nuevos recursos o nuevos vínculos.Big changes could be represented as new resources or new links. Agregar contenido a recursos existentes puede que no represente un cambio importante dado que las aplicaciones cliente que no esperan ver este contenido simplemente lo ignorarán.Adding content to existing resources might not present a breaking change as client applications that are not expecting to see this content will simply ignore it.

Por ejemplo, una solicitud al URI http://adventure-works.com/customers/3 debe devolver los detalles de un solo cliente que contiene los campos id, name y address esperados por la aplicación cliente:For example, a request to the URI http://adventure-works.com/customers/3 should return the details of a single customer containing id, name, and address fields expected by the client application:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","address":"1 Microsoft Way Redmond WA 98053"}

Nota

Por motivos de simplicidad, las respuestas de ejemplo que se muestran en esta sección no incluyen vínculos HATEOAS.For simplicity, the example responses shown in this section do not include HATEOAS links.

Si el campo DateCreated se agrega al esquema del recurso de cliente, la respuesta tendría el siguiente aspecto:If the DateCreated field is added to the schema of the customer resource, then the response would look like this:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","dateCreated":"2014-09-04T12:11:38.0376089Z","address":"1 Microsoft Way Redmond WA 98053"}

Las aplicaciones cliente existentes pueden seguir funcionando correctamente si son capaces de omitir los campos no reconocidos, pero las nuevas aplicaciones cliente se pueden diseñar para controlar este nuevo campo.Existing client applications might continue functioning correctly if they are capable of ignoring unrecognized fields, while new client applications can be designed to handle this new field. Sin embargo, si se producen cambios más radicales en el esquema de recursos (por ejemplo, se quitan campos y se cambian de nombre) o cambian las relaciones entre los recursos, dichos cambios podrían constituir cambios importantes que impiden que las aplicaciones cliente existentes funcionen correctamente.However, if more radical changes to the schema of resources occur (such as removing or renaming fields) or the relationships between resources change then these may constitute breaking changes that prevent existing client applications from functioning correctly. En estas situaciones es aconsejable uno de los enfoques siguientes.In these situations you should consider one of the following approaches.

Control de versiones de URIURI versioning

Cada vez que modifica la API web o cambia el esquema de recursos, agrega un número de versión al URI para cada recurso.Each time you modify the web API or change the schema of resources, you add a version number to the URI for each resource. Los URI ya existentes deben seguir funcionando como antes y devolver los recursos conforme a su esquema original.The previously existing URIs should continue to operate as before, returning resources that conform to their original schema.

Ampliando el ejemplo anterior, si el campo address se reestructura en campos secundarios que contienen cada uno una parte constituyente de la dirección (como streetAddress, city, state y zipCode), esta versión del recurso podría exponerse a través de un URI que contenga un número de versión, como http://adventure-works.com/v2/customers/3:Extending the previous example, if the address field is restructured into sub-fields containing each constituent part of the address (such as streetAddress, city, state, and zipCode), this version of the resource could be exposed through a URI containing a version number, such as http://adventure-works.com/v2/customers/3:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","dateCreated":"2014-09-04T12:11:38.0376089Z","address":{"streetAddress":"1 Microsoft Way","city":"Redmond","state":"WA","zipCode":98053}}

Este mecanismo de control de versiones es muy sencillo, pero depende del servidor que enruta la solicitud al extremo adecuado.This versioning mechanism is very simple but depends on the server routing the request to the appropriate endpoint. Sin embargo, puede volverse difícil de manejar dado que la API web madura a través de varias iteraciones y el servidor tiene que admitir un número de versiones diferentes.However, it can become unwieldy as the web API matures through several iterations and the server has to support a number of different versions. Además, desde el punto de vista de los más puristas, en todos los casos las aplicaciones cliente capturan los mismos datos (cliente 3), así que el URI no debería ser realmente diferente según la versión.Also, from a purist’s point of view, in all cases the client applications are fetching the same data (customer 3), so the URI should not really be different depending on the version. Este esquema también complica la implementación de HATEOAS ya que todos los vínculos deberán incluir el número de versión en sus URI.This scheme also complicates implementation of HATEOAS as all links will need to include the version number in their URIs.

Control de versiones de cadena de consultaQuery string versioning

En lugar de proporcionar varios URI, puede especificar la versión del recurso mediante un parámetro dentro de la cadena de consulta anexada a la solicitud HTTP, como http://adventure-works.com/customers/3?version=2.Rather than providing multiple URIs, you can specify the version of the resource by using a parameter within the query string appended to the HTTP request, such as http://adventure-works.com/customers/3?version=2. El parámetro de versión debe adoptar de forma predeterminada un valor significativo como 1 si se omite en las aplicaciones cliente más antiguas.The version parameter should default to a meaningful value such as 1 if it is omitted by older client applications.

Este enfoque tiene la ventaja semántica de que el mismo recurso siempre se recupera del mismo URI, pero depende del código que controla la solicitud para analizar la cadena de consulta y enviar la respuesta HTTP adecuada.This approach has the semantic advantage that the same resource is always retrieved from the same URI, but it depends on the code that handles the request to parse the query string and send back the appropriate HTTP response. Este método también presenta tiene las mismas complicaciones para implementar HATEOAS que el mecanismo de control de versiones de URI.This approach also suffers from the same complications for implementing HATEOAS as the URI versioning mechanism.

Nota

Algunos exploradores web y servidores proxy antiguos no almacenan en caché las respuestas de solicitudes que incluyen una cadena de consulta en el URI.Some older web browsers and web proxies will not cache responses for requests that include a query string in the URI. Esto puede tener un impacto negativo en el rendimiento de las aplicaciones web que usan una API web y que se ejecutan en este tipo de explorador web.This can have an adverse impact on performance for web applications that use a web API and that run from within such a web browser.

Control de versiones de encabezadoHeader versioning

En lugar de anexar el número de versión como un parámetro de cadena de consulta, podría implementar un encabezado personalizado que indica la versión del recurso.Rather than appending the version number as a query string parameter, you could implement a custom header that indicates the version of the resource. Este enfoque requiere que la aplicación cliente agregue el encabezado adecuado a las solicitudes, aunque el código que controla la solicitud de cliente puede usar un valor predeterminado (versión 1) si se omite el encabezado de versión.This approach requires that the client application adds the appropriate header to any requests, although the code handling the client request could use a default value (version 1) if the version header is omitted. En los ejemplos siguientes se usa un encabezado personalizado denominado Custom-Header.The following examples utilize a custom header named Custom-Header. El valor de este encabezado indica la versión de la API web.The value of this header indicates the version of web API.

Versión 1:Version 1:

GET http://adventure-works.com/customers/3 HTTP/1.1
Custom-Header: api-version=1
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","address":"1 Microsoft Way Redmond WA 98053"}

Versión 2:Version 2:

GET http://adventure-works.com/customers/3 HTTP/1.1
Custom-Header: api-version=2
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","dateCreated":"2014-09-04T12:11:38.0376089Z","address":{"streetAddress":"1 Microsoft Way","city":"Redmond","state":"WA","zipCode":98053}}

Tenga en cuenta que al igual que en los dos enfoques anteriores, la implementación de HATEOAS requiere que se incluya el encabezado personalizado apropiado en los vínculos.Note that as with the previous two approaches, implementing HATEOAS requires including the appropriate custom header in any links.

Control de versiones del tipo de medioMedia type versioning

Cuando una aplicación cliente envía una solicitud HTTP GET a un servidor web, debe prever el formato del contenido que puede controlar mediante el uso de un encabezado Accept, como se ha descrito anteriormente en esta guía.When a client application sends an HTTP GET request to a web server it should stipulate the format of the content that it can handle by using an Accept header, as described earlier in this guidance. Con frecuencia, el propósito del encabezado Accept es permitir que la aplicación cliente especifique si el cuerpo de la respuesta debe ser XML, JSON o algún otro formato común que pueda analizar el cliente.Frequently the purpose of the Accept header is to allow the client application to specify whether the body of the response should be XML, JSON, or some other common format that the client can parse. Sin embargo, es posible definir tipos de medios personalizados que incluyan información que permita que la aplicación cliente indique qué versión de un recurso que se espera.However, it is possible to define custom media types that include information enabling the client application to indicate which version of a resource it is expecting. En el ejemplo siguiente se muestra una solicitud que especifica un encabezado Accept con el valor application/vnd.adventure-works.v1+json.The following example shows a request that specifies an Accept header with the value application/vnd.adventure-works.v1+json. El elemento vnd.adventure-works.v1 indica al servidor web que debe devolver la versión 1 del recurso, mientras que el elemento json especifica que el formato del cuerpo de respuesta debe ser JSON:The vnd.adventure-works.v1 element indicates to the web server that it should return version 1 of the resource, while the json element specifies that the format of the response body should be JSON:

GET http://adventure-works.com/customers/3 HTTP/1.1
Accept: application/vnd.adventure-works.v1+json

El código que controla la solicitud es responsable de procesar el encabezado Accept y de respetarlo siempre que sea posible (la aplicación cliente puede especificar varios formatos en el encabezado Accept, en cuyo caso el servidor web puede elegir el formato más adecuado para el cuerpo de respuesta).The code handling the request is responsible for processing the Accept header and honoring it as far as possible (the client application may specify multiple formats in the Accept header, in which case the web server can choose the most appropriate format for the response body). El servidor web confirma el formato de los datos en el cuerpo de respuesta mediante el encabezado Content-Type:The web server confirms the format of the data in the response body by using the Content-Type header:

HTTP/1.1 200 OK
Content-Type: application/vnd.adventure-works.v1+json; charset=utf-8

{"id":3,"name":"Contoso LLC","address":"1 Microsoft Way Redmond WA 98053"}

Si el encabezado Accept no especifica ningún tipo de medio conocido, el servidor web podría generar un mensaje de respuesta HTTP 406 (no aceptable) o devolver un mensaje con un tipo de medio predeterminado.If the Accept header does not specify any known media types, the web server could generate an HTTP 406 (Not Acceptable) response message or return a message with a default media type.

Este enfoque es posiblemente el más puro de los mecanismos de control de versiones y se presta de forma natural a HATEOAS, que puede incluir el tipo MIME de los datos relacionados en los vínculos de recursos.This approach is arguably the purest of the versioning mechanisms and lends itself naturally to HATEOAS, which can include the MIME type of related data in resource links.

Nota

Al seleccionar una estrategia de control de versiones, también debe considerar las implicaciones en el rendimiento, especialmente en el almacenamiento en caché en el servidor web.When you select a versioning strategy, you should also consider the implications on performance, especially caching on the web server. Los esquemas de control de versiones de URI y de control de versiones de cadena de consulta son compatibles con la caché puesto que la misma combinación de URI y cadena de consulta hace referencia siempre a los mismos datos.The URI versioning and Query String versioning schemes are cache-friendly inasmuch as the same URI/query string combination refers to the same data each time.

Los mecanismos de control de versiones de encabezado y de control de versiones de tipo de medio normalmente requieren lógica adicional para examinar los valores del encabezado personalizado o del encabezado Accept.The Header versioning and Media Type versioning mechanisms typically require additional logic to examine the values in the custom header or the Accept header. En un entorno a gran escala, muchos clientes que usan versiones diferentes de una API web pueden producir una cantidad significativa de datos duplicados en una caché del servidor.In a large-scale environment, many clients using different versions of a web API can result in a significant amount of duplicated data in a server-side cache. Este problema puede ser agudo si una aplicación cliente se comunica con un servidor web a través de un proxy que implementa almacenamiento en caché y que solo reenvía una solicitud a dicho servidor si no contiene actualmente una copia de los datos solicitados en su caché.This issue can become acute if a client application communicates with a web server through a proxy that implements caching, and that only forwards a request to the web server if it does not currently hold a copy of the requested data in its cache.

Iniciativa Open APIOpen API Initiative

La iniciativa Open API fue creada por un consorcio de la industria para normalizar las descripciones de las API de REST de los distintos proveedores.The Open API Initiative was created by an industry consortium to standardize REST API descriptions across vendors. Como parte de esta iniciativa, la especificación Swagger 2.0 se cambió a OpenAPI Specification (OAS) y se incluyó en la iniciativa Open API.As part of this initiative, the Swagger 2.0 specification was renamed the OpenAPI Specification (OAS) and brought under the Open API Initiative.

Puede adoptar OpenAPI para sus API web.You may want to adopt OpenAPI for your web APIs. Algunos puntos que se deben tener en cuenta:Some points to consider:

  • OpenAPI Specification incluye un conjunto de directrices bien fundamentadas acerca de cómo se debe diseñar una API de REST.The OpenAPI Specification comes with a set of opinionated guidelines on how a REST API should be designed. Esto presenta ventajas en cuanto a interoperabilidad, pero requiere más cuidado al diseñar las API para que cumplan la especificación.That has advantages for interoperability, but requires more care when designing your API to conform to the specification.
  • OpenAPI promueve un enfoque "el contrato es lo primero", en lugar de un enfoque "la implementación es lo primero".OpenAPI promotes a contract-first approach, rather than an implementation-first approach. Que el contrato sea lo primero, significa que primero se diseña el contrato de la API (la interfaz) y después se escribe el código que implementa el contrato.Contract-first means you design the API contract (the interface) first and then write code that implements the contract.
  • Herramientas como Swagger pueden generar las bibliotecas de cliente o la documentación de los contratos de API.Tools like Swagger can generate client libraries or documentation from API contracts. Por ejemplo, consulte Páginas de ayuda de ASP.NET Core Web API mediante Swagger.For example, see ASP.NET Web API Help Pages using Swagger.

Más informaciónMore information