0% encontró este documento útil (0 votos)
55 vistas

Implementación de API Web

Este documento proporciona orientación sobre cómo implementar correctamente una API web. Describe consideraciones clave como hacer que las solicitudes sean idempotentes, evitar efectos secundarios no relacionados, seguir las especificaciones HTTP y proporcionar enlaces HATEOAS para permitir la navegación. También cubre temas como la negociación de contenido, el manejo de excepciones y el procesamiento por lotes.

Cargado por

Martin Ojeda
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
55 vistas

Implementación de API Web

Este documento proporciona orientación sobre cómo implementar correctamente una API web. Describe consideraciones clave como hacer que las solicitudes sean idempotentes, evitar efectos secundarios no relacionados, seguir las especificaciones HTTP y proporcionar enlaces HATEOAS para permitir la navegación. También cubre temas como la negociación de contenido, el manejo de excepciones y el procesamiento por lotes.

Cargado por

Martin Ojeda
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 39

Implementación de API web

Artículo

02/04/2022

46 minutos para leer

21 colaboradores

Una API web RESTful cuidadosamente diseñada define los recursos, las relaciones y los esquemas
de navegación a los que pueden acceder las aplicaciones cliente. Cuando implemente e
implemente una API web, debe considerar los requisitos físicos del entorno que aloja la API web y
la forma en que se construye la API web en lugar de la estructura lógica de los datos. Esta guía se
centra en las mejores prácticas para implementar una API web y publicarla para que esté
disponible para las aplicaciones cliente. Para obtener información detallada sobre el diseño de API
web, consulte Diseño de API web .

Solicitudes de procesamiento

Considere los siguientes puntos cuando implemente el código para manejar las solicitudes.

Las acciones GET, PUT, DELETE, HEAD y PATCH deben ser idempotentes

El código que implementa estas solicitudes no debería imponer ningún efecto secundario. La
misma solicitud repetida sobre el mismo recurso debería dar como resultado el mismo estado. Por
ejemplo, enviar varias solicitudes DELETE al mismo URI debería tener el mismo efecto, aunque el
código de estado HTTP en los mensajes de respuesta puede ser diferente. La primera solicitud
DELETE puede devolver el código de estado 204 (Sin contenido), mientras que una solicitud
DELETE posterior puede devolver el código de estado 404 (No encontrado).

Nota

El artículo Patrones de idempotencia en el blog de Jonathan Oliver proporciona una descripción


general de la idempotencia y cómo se relaciona con las operaciones de administración de datos.

Las acciones POST que crean nuevos recursos no deberían tener efectos secundarios no
relacionados
Si una solicitud POST está destinada a crear un nuevo recurso, los efectos de la solicitud deben
limitarse al nuevo recurso (y posiblemente a cualquier recurso directamente relacionado si hay
algún tipo de vínculo involucrado). Por ejemplo, en un sistema de comercio electrónico, una
solicitud POST que crea un nuevo pedido para un cliente también puede modificar los niveles de
inventario y generar información de facturación, pero no debe modificar información que no esté
directamente relacionada con el pedido ni tener otros efectos secundarios en el estado general del
sistema.

Evite implementar operaciones POST, PUT y DELETE conversacionales

Admite solicitudes POST, PUT y DELETE sobre colecciones de recursos. Una solicitud POST puede
contener los detalles de varios recursos nuevos y agregarlos a la misma colección, una solicitud
PUT puede reemplazar todo el conjunto de recursos de una colección y una solicitud DELETE
puede eliminar una colección completa.

La compatibilidad con OData incluida en ASP.NET Web API 2 brinda la capacidad de procesar
solicitudes por lotes. Una aplicación cliente puede empaquetar varias solicitudes de API web y
enviarlas al servidor en una sola solicitud HTTP y recibir una única respuesta HTTP que contiene las
respuestas a cada solicitud. Para obtener más información, Introducción a la compatibilidad con
lotes en Web API y Web API OData .

Siga la especificación HTTP al enviar una respuesta

Una API web debe devolver mensajes que contengan el código de estado HTTP correcto para
permitir que el cliente determine cómo manejar el resultado, los encabezados HTTP apropiados
para que el cliente comprenda la naturaleza del resultado y un cuerpo con el formato adecuado
para permitir que el cliente analizar el resultado.

Por ejemplo, una operación POST debe devolver el código de estado 201 (Creado) y el mensaje de
respuesta debe incluir el URI del recurso recién creado en el encabezado Ubicación del mensaje de
respuesta.

Negociación de contenido de soporte

El cuerpo de un mensaje de respuesta puede contener datos en una variedad de formatos. Por
ejemplo, una solicitud HTTP GET podría devolver datos en formato JSON o XML. Cuando el cliente
envía una solicitud, puede incluir un encabezado de aceptación que especifica los formatos de
datos que puede manejar. Estos formatos se especifican como tipos de medios. Por ejemplo, un
cliente que emite una solicitud GET que recupera una imagen puede especificar un encabezado de
aceptación que enumera los tipos de medios que el cliente puede manejar, como image/jpeg,
image/gif, image/png. Cuando la API web devuelve el resultado, debe formatear los datos
utilizando uno de estos tipos de medios y especificar el formato en el encabezado Tipo de
contenido de la respuesta.

Si el cliente no especifica un encabezado de aceptación, utilice un formato predeterminado


razonable para el cuerpo de la respuesta. Como ejemplo, el marco de la API web de ASP.NET tiene
como valor predeterminado JSON para datos basados en texto.

Proporcione enlaces para apoyar la navegación estilo HATEOAS y el descubrimiento de recursos

El enfoque HATEOAS permite que un cliente navegue y descubra recursos desde un punto de
partida inicial. Esto se logra mediante el uso de enlaces que contienen URI; cuando un cliente
emite una solicitud HTTP GET para obtener un recurso, la respuesta debe contener URI que
permitan a una aplicación cliente localizar rápidamente cualquier recurso directamente
relacionado. Por ejemplo, en una API web que admite una solución de comercio electrónico, un
cliente puede haber realizado muchos pedidos. Cuando una aplicación cliente recupera los
detalles de un cliente, la respuesta debe incluir enlaces que permitan a la aplicación cliente enviar
solicitudes HTTP GET que puedan recuperar estos pedidos. Además, los enlaces de estilo HATEOAS
deben describir las otras operaciones (POST, PUT, DELETE, etc.) que admite cada recurso vinculado
junto con el URI correspondiente para realizar cada solicitud.Diseño de API .

Actualmente no existen estándares que rijan la implementación de HATEOAS, pero el siguiente


ejemplo ilustra un posible enfoque. En este ejemplo, una solicitud HTTP GET que encuentra los
detalles de un cliente devuelve una respuesta que incluye enlaces HATEOAS que hacen referencia
a los pedidos de ese cliente:

HTTP

Dupdo

GET https://adventure-works.com/customers/2 HTTP/1.1

Accept: text/json

...

HTTP

Dupdo
HTTP/1.1 200 OK

...

Content-Type: application/json; charset=utf-8

...

Content-Length: ...

{"CustomerID":2,"CustomerName":"Bert","Links":[

{"rel":"self",

"href":"https://adventure-works.com/customers/2",

"action":"GET",

"types":["text/xml","application/json"]},

{"rel":"self",

"href":"https://adventure-works.com/customers/2",

"action":"PUT",

"types":["application/x-www-form-urlencoded"]},

{"rel":"self",

"href":"https://adventure-works.com/customers/2",

"action":"DELETE",

"types":[]},

{"rel":"orders",

"href":"https://adventure-works.com/customers/2/orders",

"action":"GET",

"types":["text/xml","application/json"]},

{"rel":"orders",

"href":"https://adventure-works.com/customers/2/orders",

"action":"POST",

"types":["application/x-www-form-urlencoded"]}

]}

En este ejemplo, los datos del cliente están representados por la Customerclase que se muestra en
el siguiente fragmento de código. Los enlaces HATEOAS se mantienen en la Linkspropiedad de la
colección:
C#

Dupdo

public class Customer

public int CustomerID { get; set; }

public string CustomerName { get; set; }

public List<Link> Links { get; set; }

...

public class Link

public string Rel { get; set; }

public string Href { get; set; }

public string Action { get; set; }

public string [] Types { get; set; }

La operación HTTP GET recupera los datos del cliente del almacenamiento y construye un
Customerobjeto, y luego completa la Linkscolección. El resultado se formatea como un mensaje de
respuesta JSON. Cada enlace consta de los siguientes campos:

La relación entre el objeto que se devuelve y el objeto descrito por el vínculo. En este caso,
selfindica que el enlace es una referencia al objeto mismo (similar a un thispuntero en muchos
lenguajes orientados a objetos) y orderses el nombre de una colección que contiene la
información de pedido relacionada.

El hipervínculo ( Href) para el objeto descrito por el enlace en forma de URI.

El tipo de solicitud HTTP ( Action) que se puede enviar a este URI.

El formato de cualquier dato ( Types) que se debe proporcionar en la solicitud HTTP o que se
puede devolver en la respuesta, según el tipo de solicitud.
Los enlaces HATEOAS que se muestran en la respuesta HTTP de ejemplo indican que una
aplicación cliente puede realizar las siguientes operaciones:

Una solicitud HTTP GET al URI https://adventure-works.com/customers/2para obtener los detalles


del cliente (nuevamente). Los datos se pueden devolver como XML o JSON.

Una solicitud HTTP PUT a la URI https://adventure-works.com/customers/2para modificar los


detalles del cliente. Los nuevos datos deberán facilitarse en el mensaje de solicitud en formato x-
www-form-urlencoded.

Una solicitud HTTP DELETE al URI https://adventure-works.com/customers/2para eliminar al


cliente. La solicitud no espera ninguna información adicional ni datos de retorno en el cuerpo del
mensaje de respuesta.

Una solicitud HTTP GET al URI https://adventure-works.com/customers/2/orderspara encontrar


todos los pedidos del cliente. Los datos se pueden devolver como XML o JSON.

Una solicitud HTTP POST al URI https://adventure-works.com/customers/2/orderspara crear un


nuevo pedido para este cliente. Los datos deberán facilitarse en el mensaje de solicitud en
formato x-www-form-urlencoded.

Manejo de excepciones

Considere los siguientes puntos si una operación genera una excepción no detectada.

Capture excepciones y devuelva una respuesta significativa a los clientes

El código que implementa una operación HTTP debe proporcionar un manejo integral de
excepciones en lugar de permitir que las excepciones no detectadas se propaguen al marco. Si una
excepción hace que sea imposible completar la operación correctamente, la excepción se puede
devolver en el mensaje de respuesta, pero debe incluir una descripción significativa del error que
provocó la excepción. La excepción también debe incluir el código de estado HTTP apropiado en
lugar de simplemente devolver el código de estado 500 para cada situación. Por ejemplo, si la
solicitud de un usuario provoca una actualización de la base de datos que infringe una restricción
(como intentar eliminar un cliente que tiene pedidos pendientes), debe devolver el código de
estado 409 (Conflicto) y un cuerpo de mensaje que indique el motivo del conflicto. Si alguna otra
condición hace que la solicitud sea inalcanzable, puede devolver el código de estado 400 (Solicitud
incorrecta). Puede encontrar una lista completa de códigos de estado HTTP en elPágina de
definiciones de códigos de estado en el sitio web del W3C.

El ejemplo de código atrapa diferentes condiciones y devuelve una respuesta adecuada.

C#
Dupdo

[HttpDelete]

[Route("customers/{id:int}")]

public IHttpActionResult DeleteCustomer(int id)

try

// Find the customer to be deleted in the repository

var customerToDelete = repository.GetCustomer(id);

// If there is no such customer, return an error response

// with status code 404 (Not Found)

if (customerToDelete == null)

return NotFound();

// Remove the customer from the repository

// The DeleteCustomer method returns true if the customer

// was successfully deleted

if (repository.DeleteCustomer(id))

// Return a response message with status code 204 (No Content)

// To indicate that the operation was successful

return StatusCode(HttpStatusCode.NoContent);

else

{
// Otherwise return a 400 (Bad Request) error response

return BadRequest(Strings.CustomerNotDeleted);

catch

// If an uncaught exception occurs, return an error response

// with status code 500 (Internal Server Error)

return InternalServerError();

Propina

No incluya información que pueda ser útil para un atacante que intente acceder a su API.

Muchos servidores web atrapan las condiciones de error antes de que lleguen a la API web. Por
ejemplo, si configura la autenticación para un sitio web y el usuario no proporciona la información
de autenticación correcta, el servidor web debería responder con el código de estado 401 (no
autorizado). Una vez que se ha autenticado a un cliente, su código puede realizar sus propias
comprobaciones para verificar que el cliente debería poder acceder al recurso solicitado. Si esta
autorización falla, debe devolver el código de estado 403 (Prohibido).

Maneje las excepciones de manera consistente y registre información sobre errores

Para manejar las excepciones de manera consistente, considere implementar una estrategia global
de manejo de errores en toda la API web. También debe incorporar un registro de errores que
capture todos los detalles de cada excepción; este registro de errores puede contener información
detallada siempre que los clientes no puedan acceder a ella a través de la web.

Distinguir entre errores del lado del cliente y errores del lado del servidor

El protocolo HTTP distingue entre los errores que ocurren debido a la aplicación del cliente (los
códigos de estado HTTP 4xx) y los errores causados por un percance en el servidor (los códigos de
estado HTTP 5xx). Asegúrese de respetar esta convención en cualquier mensaje de respuesta de
error.
Optimización del acceso a datos del lado del cliente

En un entorno distribuido como el que implica un servidor web y aplicaciones cliente, una de las
principales fuentes de preocupación es la red. Esto puede actuar como un cuello de botella
considerable, especialmente si una aplicación cliente envía solicitudes o recibe datos con
frecuencia. Por lo tanto, debe intentar minimizar la cantidad de tráfico que fluye a través de la red.
Considere los siguientes puntos cuando implemente el código para recuperar y mantener datos:

Admite el almacenamiento en caché del lado del cliente

El protocolo HTTP 1.1 admite el almacenamiento en caché en clientes y servidores intermedios a


través de los cuales se enruta una solicitud mediante el uso del encabezado Cache-Control.
Cuando una aplicación cliente envía una solicitud HTTP GET a la API web, la respuesta puede
incluir un encabezado de control de caché que indica si el cliente o un servidor intermedio a través
del cual la solicitud puede almacenar en caché de manera segura los datos en el cuerpo de la
respuesta. sido enrutado y cuánto tiempo antes de que caduque y se considere obsoleto.

El siguiente ejemplo muestra una solicitud HTTP GET y la respuesta correspondiente que incluye
un encabezado Cache-Control:

HTTP

Dupdo

GET https://adventure-works.com/orders/2 HTTP/1.1

HTTP

Dupdo

HTTP/1.1 200 OK

...

Cache-Control: max-age=600, private

Content-Type: text/json; charset=utf-8

Content-Length: ...

{"orderID":2,"productID":4,"quantity":2,"orderValue":10.00}
En este ejemplo, el encabezado Cache-Control especifica que los datos devueltos deben caducar
después de 600 segundos, y solo son adecuados para un solo cliente y no deben almacenarse en
un caché compartido utilizado por otros clientes (es privado ). El encabezado Cache-Control podría
especificar public en lugar de private , en cuyo caso los datos se pueden almacenar en un caché
compartido, o podría especificar no-store, en cuyo caso el cliente no debe almacenar en caché los
datos. El siguiente ejemplo de código muestra cómo construir un encabezado de control de caché
en un mensaje de respuesta:

C#

Dupdo

public class OrdersController : ApiController

...

[Route("api/orders/{id:int:min(0)}")]

[HttpGet]

public IHttpActionResult FindOrderByID(int id)

// Find the matching order

Order order = ...;

...

// Create a Cache-Control header for the response

var cacheControlHeader = new CacheControlHeaderValue();

cacheControlHeader.Private = true;

cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);

...

// Return a response message containing the order and the cache control header

OkResultWithCaching<Order> response = new OkResultWithCaching<Order>(order, this)

CacheControlHeader = cacheControlHeader
};

return response;

...

Este código usa una IHttpActionResultclase personalizada llamada OkResultWithCaching. Esta


clase permite que el controlador establezca el contenido del encabezado de caché:

C#

Dupdo

public class OkResultWithCaching<T> : OkNegotiatedContentResult<T>

public OkResultWithCaching(T content, ApiController controller)

: base(content, controller) { }

public OkResultWithCaching(T content, IContentNegotiator contentNegotiator,


HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)

: base(content, contentNegotiator, request, formatters) { }

public CacheControlHeaderValue CacheControlHeader { get; set; }

public EntityTagHeaderValue ETag { get; set; }

public override async Task<HttpResponseMessage> ExecuteAsync(CancellationToken


cancellationToken)

HttpResponseMessage response;

try

response = await base.ExecuteAsync(cancellationToken);


response.Headers.CacheControl = this.CacheControlHeader;

response.Headers.ETag = ETag;

catch (OperationCanceledException)

response = new HttpResponseMessage(HttpStatusCode.Conflict) {ReasonPhrase =


"Operation was cancelled"};

return response;

Nota

El protocolo HTTP también define la directiva sin caché para el encabezado Cache-Control. De
manera bastante confusa, esta directiva no significa "no almacenar en caché" sino más bien
"revalidar la información almacenada en caché con el servidor antes de devolverla"; los datos aún
se pueden almacenar en caché, pero se verifican cada vez que se usan para garantizar que aún
estén actualizados.

La administración de caché es responsabilidad de la aplicación cliente o del servidor intermedio,


pero si se implementa correctamente, puede ahorrar ancho de banda y mejorar el rendimiento al
eliminar la necesidad de obtener datos que ya se recuperaron recientemente.

El valor max-age en el encabezado Cache-Control es solo una guía y no una garantía de que los
datos correspondientes no cambiarán durante el tiempo especificado. La API web debe establecer
la edad máxima en un valor adecuado según la volatilidad esperada de los datos. Cuando vence
este período, el cliente debe descartar el objeto del caché.

Nota

La mayoría de los navegadores web modernos admiten el almacenamiento en caché del lado del
cliente agregando los encabezados de control de caché apropiados a las solicitudes y examinando
los encabezados de los resultados, como se describe. Sin embargo, algunos navegadores antiguos
no almacenan en caché los valores devueltos desde una URL que incluye una cadena de consulta.
Esto no suele ser un problema para las aplicaciones cliente personalizadas que implementan su
propia estrategia de administración de caché basada en el protocolo que se analiza aquí.

Algunos proxies más antiguos exhiben el mismo comportamiento y es posible que no almacenen
en caché las solicitudes basadas en URL con cadenas de consulta. Esto podría ser un problema
para las aplicaciones cliente personalizadas que se conectan a un servidor web a través de dicho
proxy.

Proporcione ETags para optimizar el procesamiento de consultas

Cuando una aplicación cliente recupera un objeto, el mensaje de respuesta también puede incluir
una ETag (etiqueta de entidad). Una ETag es una cadena opaca que indica la versión de un recurso;
cada vez que un recurso cambia, la ETag también se modifica. La aplicación cliente debe almacenar
en caché esta ETag como parte de los datos. El siguiente ejemplo de código muestra cómo agregar
una ETag como parte de la respuesta a una solicitud HTTP GET. Este código usa el
GetHashCodemétodo de un objeto para generar un valor numérico que identifica el objeto (puede
anular este método si es necesario y generar su propio hash usando un algoritmo como MD5):

C#

Dupdo

public class OrdersController : ApiController

...

public IHttpActionResult FindOrderByID(int id)

// Find the matching order

Order order = ...;

...

var hashedOrder = order.GetHashCode();

string hashedOrderEtag = $"\"{hashedOrder}\"";

var eTag = new EntityTagHeaderValue(hashedOrderEtag);


// Return a response message containing the order and the cache control header

OkResultWithCaching<Order> response = new OkResultWithCaching<Order>(order, this)

...,

ETag = eTag

};

return response;

...

El mensaje de respuesta publicado por la API web se ve así:

HTTP

Dupdo

HTTP/1.1 200 OK

...

Cache-Control: max-age=600, private

Content-Type: text/json; charset=utf-8

ETag: "2147483648"

Content-Length: ...

{"orderID":2,"productID":4,"quantity":2,"orderValue":10.00}

Propina

Por motivos de seguridad, no permita que se almacenen en caché datos confidenciales o datos
devueltos a través de una conexión autenticada (HTTPS).

Una aplicación cliente puede emitir una solicitud GET posterior para recuperar el mismo recurso
en cualquier momento, y si el recurso ha cambiado (tiene una ETag diferente), la versión
almacenada en caché debe descartarse y la nueva versión debe agregarse a la memoria caché. Si
un recurso es grande y requiere una cantidad significativa de ancho de banda para transmitir al
cliente, las solicitudes repetidas para obtener los mismos datos pueden volverse ineficientes. Para
combatir esto, el protocolo HTTP define el siguiente proceso para optimizar las solicitudes GET que
debe admitir en una API web:

El cliente construye una solicitud GET que contiene la ETag para la versión actualmente
almacenada en caché del recurso al que se hace referencia en un encabezado HTTP If-None-
Match:

HTTP

Dupdo

GET https://adventure-works.com/orders/2 HTTP/1.1

If-None-Match: "2147483648"

La operación GET en la API web obtiene la ETag actual para los datos solicitados (orden 2 en el
ejemplo anterior) y la compara con el valor en el encabezado If-None-Match.

Si la ETag actual para los datos solicitados coincide con la ETag proporcionada por la solicitud, el
recurso no ha cambiado y la API web debería devolver una respuesta HTTP con un cuerpo de
mensaje vacío y un código de estado de 304 (No modificado).

Si la ETag actual para los datos solicitados no coincide con la ETag proporcionada por la solicitud,
entonces los datos han cambiado y la API web debe devolver una respuesta HTTP con los nuevos
datos en el cuerpo del mensaje y un código de estado de 200 (OK).

Si los datos solicitados ya no existen, la API web debería devolver una respuesta HTTP con el
código de estado 404 (No encontrado).

El cliente usa el código de estado para mantener el caché. Si los datos no han cambiado (código de
estado 304), el objeto puede permanecer en caché y la aplicación cliente debe continuar usando
esta versión del objeto. Si los datos han cambiado (código de estado 200), entonces el objeto
almacenado en caché debe descartarse e insertarse uno nuevo. Si los datos ya no están
disponibles (código de estado 404), el objeto debe eliminarse de la memoria caché.
Nota

Si el encabezado de respuesta contiene el encabezado Cache-Control sin almacenamiento,


entonces el objeto siempre debe eliminarse del caché, independientemente del código de estado
HTTP.

El siguiente código muestra el FindOrderByIDmétodo extendido para admitir el encabezado If-


None-Match. Tenga en cuenta que si se omite el encabezado If-None-Match, siempre se recupera
el orden especificado:

C#

Dupdo

public class OrdersController : ApiController

[Route("api/orders/{id:int:min(0)}")]

[HttpGet]

public IHttpActionResult FindOrderByID(int id)

try

// Find the matching order

Order order = ...;

// If there is no such order then return NotFound

if (order == null)

return NotFound();

}
// Generate the ETag for the order

var hashedOrder = order.GetHashCode();

string hashedOrderEtag = $"\"{hashedOrder}\"";

// Create the Cache-Control and ETag headers for the response

IHttpActionResult response;

var cacheControlHeader = new CacheControlHeaderValue();

cacheControlHeader.Public = true;

cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);

var eTag = new EntityTagHeaderValue(hashedOrderEtag);

// Retrieve the If-None-Match header from the request (if it exists)

var nonMatchEtags = Request.Headers.IfNoneMatch;

// If there is an ETag in the If-None-Match header and

// this ETag matches that of the order just retrieved,

// then create a Not Modified response message

if (nonMatchEtags.Count > 0 &&

String.CompareOrdinal(nonMatchEtags.First().Tag, hashedOrderEtag) == 0)

response = new EmptyResultWithCaching()

StatusCode = HttpStatusCode.NotModified,

CacheControlHeader = cacheControlHeader,

ETag = eTag

};

// Otherwise create a response message that contains the order details


else

response = new OkResultWithCaching<Order>(order, this)

CacheControlHeader = cacheControlHeader,

ETag = eTag

};

return response;

catch

return InternalServerError();

...

Este ejemplo incorpora una IHttpActionResultclase personalizada adicional llamada


EmptyResultWithCaching. Esta clase simplemente actúa como un envoltorio alrededor de un
HttpResponseMessageobjeto que no contiene un cuerpo de respuesta:

C#

Dupdo

public class EmptyResultWithCaching : IHttpActionResult

public CacheControlHeaderValue CacheControlHeader { get; set; }

public EntityTagHeaderValue ETag { get; set; }

public HttpStatusCode StatusCode { get; set; }


public Uri Location { get; set; }

public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)

HttpResponseMessage response = new HttpResponseMessage(StatusCode);

response.Headers.CacheControl = this.CacheControlHeader;

response.Headers.ETag = this.ETag;

response.Headers.Location = this.Location;

return response;

Propina

En este ejemplo, la ETag para los datos se genera mediante el hash de los datos recuperados de la
fuente de datos subyacente. Si la ETag se puede calcular de alguna otra manera, entonces el
proceso se puede optimizar aún más y los datos solo se deben obtener de la fuente de datos si ha
cambiado. Este enfoque es especialmente útil si los datos son grandes o si el acceso a la fuente de
datos puede generar una latencia significativa (por ejemplo, si la fuente de datos es una base de
datos remota).

Use ETags para admitir la simultaneidad optimista

Para permitir actualizaciones sobre datos previamente almacenados en caché, el protocolo HTTP
admite una estrategia de concurrencia optimista. Si, después de obtener y almacenar en caché un
recurso, la aplicación cliente envía posteriormente una solicitud PUT o DELETE para cambiar o
eliminar el recurso, debe incluirse en el encabezado If-Match que hace referencia a la ETag. La API
web puede usar esta información para determinar si otro usuario ya ha cambiado el recurso desde
que se recuperó y enviar una respuesta adecuada a la aplicación cliente de la siguiente manera:

El cliente construye una solicitud PUT que contiene los nuevos detalles para el recurso y la ETag
para la versión actualmente almacenada en caché del recurso al que se hace referencia en un
encabezado HTTP If-Match. El siguiente ejemplo muestra una solicitud PUT que actualiza una
orden:
HTTP

Dupdo

PUT https://adventure-works.com/orders/1 HTTP/1.1

If-Match: "2282343857"

Content-Type: application/x-www-form-urlencoded

Content-Length: ...

productID=3&quantity=5&orderValue=250

La operación PUT en la API web obtiene el ETag actual para los datos solicitados (orden 1 en el
ejemplo anterior) y lo compara con el valor en el encabezado If-Match.

Si la ETag actual para los datos solicitados coincide con la ETag proporcionada por la solicitud, el
recurso no ha cambiado y la API web debe realizar la actualización, devolviendo un mensaje con el
código de estado HTTP 204 (Sin contenido) si tiene éxito. La respuesta puede incluir encabezados
Cache-Control y ETag para la versión actualizada del recurso. La respuesta siempre debe incluir el
encabezado Ubicación que hace referencia al URI del recurso recién actualizado.

Si la ETag actual para los datos solicitados no coincide con la ETag proporcionada por la solicitud,
otro usuario ha cambiado los datos desde que se recuperaron y la API web debe devolver una
respuesta HTTP con un cuerpo de mensaje vacío y un código de estado de 412 (Error de condición
previa).

Si el recurso que se va a actualizar ya no existe, la API web debería devolver una respuesta HTTP
con el código de estado 404 (No encontrado).

El cliente usa el código de estado y los encabezados de respuesta para mantener el caché. Si los
datos se actualizaron (código de estado 204), el objeto puede permanecer en caché (siempre que
el encabezado Cache-Control no especifique que no se almacene), pero la ETag debe actualizarse.
Si otro usuario cambió los datos (código de estado 412) o no se encontraron (código de estado
404), entonces el objeto almacenado en caché debe descartarse.

El siguiente ejemplo de código muestra una implementación de la operación PUT para el


controlador de pedidos:
C#

Dupdo

public class OrdersController : ApiController

[HttpPut]

[Route("api/orders/{id:int}")]

public IHttpActionResult UpdateExistingOrder(int id, DTOOrder order)

try

var baseUri = Constants.GetUriFromConfig();

var orderToUpdate = this.ordersRepository.GetOrder(id);

if (orderToUpdate == null)

return NotFound();

var hashedOrder = orderToUpdate.GetHashCode();

string hashedOrderEtag = $"\"{hashedOrder}\"";

// Retrieve the If-Match header from the request (if it exists)

var matchEtags = Request.Headers.IfMatch;

// If there is an ETag in the If-Match header and

// this ETag matches that of the order just retrieved,

// or if there is no ETag, then update the Order

if (((matchEtags.Count > 0 &&

String.CompareOrdinal(matchEtags.First().Tag, hashedOrderEtag) == 0)) ||


matchEtags.Count == 0)

// Modify the order

orderToUpdate.OrderValue = order.OrderValue;

orderToUpdate.ProductID = order.ProductID;

orderToUpdate.Quantity = order.Quantity;

// Save the order back to the data store

// ...

// Create the No Content response with Cache-Control, ETag, and Location headers

var cacheControlHeader = new CacheControlHeaderValue();

cacheControlHeader.Private = true;

cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);

hashedOrder = order.GetHashCode();

hashedOrderEtag = $"\"{hashedOrder}\"";

var eTag = new EntityTagHeaderValue(hashedOrderEtag);

var location = new Uri($"{baseUri}/{Constants.ORDERS}/{id}");

var response = new EmptyResultWithCaching()

StatusCode = HttpStatusCode.NoContent,

CacheControlHeader = cacheControlHeader,

ETag = eTag,

Location = location

};

return response;
}

// Otherwise return a Precondition Failed response

return StatusCode(HttpStatusCode.PreconditionFailed);

catch

return InternalServerError();

...

Propina

El uso del encabezado If-Match es completamente opcional y, si se omite, la API web siempre
intentará actualizar el orden especificado, posiblemente sobrescribiendo ciegamente una
actualización realizada por otro usuario. Para evitar problemas debido a la pérdida de
actualizaciones, proporcione siempre un encabezado If-Match.

Manejo de grandes solicitudes y respuestas

Puede haber ocasiones en las que una aplicación cliente necesite emitir solicitudes que envíen o
reciban datos que pueden tener varios megabytes (o más) de tamaño. Si espera mientras se
transmite esta cantidad de datos, la aplicación cliente podría dejar de responder. Considere los
siguientes puntos cuando necesite manejar solicitudes que incluyan cantidades significativas de
datos:

Optimice las solicitudes y respuestas que involucran objetos grandes

Algunos recursos pueden ser objetos grandes o incluir campos grandes, como imágenes gráficas u
otros tipos de datos binarios. Una API web debe admitir la transmisión para permitir la carga y
descarga optimizadas de estos recursos.
El protocolo HTTP proporciona el mecanismo de codificación de transferencia fragmentada para
transmitir grandes objetos de datos a un cliente. Cuando el cliente envía una solicitud HTTP GET
para un objeto grande, la API web puede enviar la respuesta en fragmentos fragmentados a través
de una conexión HTTP. Es posible que inicialmente no se conozca la longitud de los datos en la
respuesta (es posible que se genere), por lo que el servidor que aloja la API web debe enviar un
mensaje de respuesta con cada fragmento que especifique Transfer-Encoding: encabezado
fragmentado en lugar de Content-Length encabezamiento. La aplicación cliente puede recibir cada
fragmento a su vez para generar la respuesta completa. La transferencia de datos se completa
cuando el servidor devuelve un fragmento final con tamaño cero.

Una sola solicitud posiblemente podría resultar en un objeto masivo que consume una cantidad
considerable de recursos. Si durante el proceso de transmisión, la API web determina que la
cantidad de datos en una solicitud ha excedido algunos límites aceptables, puede cancelar la
operación y devolver un mensaje de respuesta con el código de estado 413 (Entidad de solicitud
demasiado grande).

Puede minimizar el tamaño de los objetos grandes que se transmiten a través de la red mediante
la compresión HTTP. Este enfoque ayuda a reducir la cantidad de tráfico de red y la latencia de red
asociada, pero a costa de requerir un procesamiento adicional en el cliente y el servidor que aloja
la API web. Por ejemplo, una aplicación cliente que espera recibir datos comprimidos puede incluir
un encabezado de solicitud Accept-Encoding: gzip (también se pueden especificar otros algoritmos
de compresión de datos). Si el servidor admite la compresión, debe responder con el contenido en
formato gzip en el cuerpo del mensaje y el encabezado de respuesta Content-Encoding: gzip.

Puede combinar la compresión codificada con la transmisión; comprima los datos antes de
transmitirlos y especifique la codificación de contenido gzip y la codificación de transferencia
fragmentada en los encabezados de los mensajes. También tenga en cuenta que algunos
servidores web (como Internet Information Server) se pueden configurar para comprimir
automáticamente las respuestas HTTP, independientemente de si la API web comprime los datos o
no.

Implementar respuestas parciales para clientes que no admiten operaciones asincrónicas

Como alternativa a la transmisión asíncrona, una aplicación cliente puede solicitar explícitamente
datos para objetos grandes en fragmentos, conocidos como respuestas parciales. La aplicación
cliente envía una solicitud HTTP HEAD para obtener información sobre el objeto. Si la API web
admite respuestas parciales, debe responder a la solicitud HEAD con un mensaje de respuesta que
contenga un encabezado de rangos de aceptación y un encabezado de longitud de contenido que
indique el tamaño total del objeto, pero el cuerpo del mensaje debe estar vacío. La aplicación
cliente puede usar esta información para construir una serie de solicitudes GET que especifican un
rango de bytes para recibir. La API web debe devolver un mensaje de respuesta con el estado
HTTP 206 (contenido parcial), un encabezado de longitud de contenido que especifica la cantidad
real de datos incluidos en el cuerpo del mensaje de respuesta,

Las solicitudes HTTP HEAD y las respuestas parciales se describen con más detalle en el diseño de
la API .

Evite enviar mensajes de estado 100-Continue innecesarios en aplicaciones cliente

Una aplicación cliente que está a punto de enviar una gran cantidad de datos a un servidor puede
determinar primero si el servidor está realmente dispuesto a aceptar la solicitud. Antes de enviar
los datos, la aplicación cliente puede enviar una solicitud HTTP con un encabezado Expect: 100-
Continue, un encabezado Content-Length que indica el tamaño de los datos, pero un cuerpo de
mensaje vacío. Si el servidor está dispuesto a manejar la solicitud, debe responder con un mensaje
que especifique el estado HTTP 100 (Continuar). A continuación, la aplicación cliente puede
continuar y enviar la solicitud completa, incluidos los datos del cuerpo del mensaje.

Si aloja un servicio mediante IIS, el controlador HTTP.sys detecta y maneja automáticamente los
encabezados Expect: 100-Continue antes de pasar las solicitudes a su aplicación web. Esto significa
que es poco probable que vea estos encabezados en el código de su aplicación, y puede suponer
que IIS ya ha filtrado los mensajes que considera inadecuados o demasiado grandes.

Si está creando aplicaciones cliente mediante .NET Framework, todos los mensajes POST y PUT
enviarán primero mensajes con encabezados Expect: 100-Continue de forma predeterminada. Al
igual que con el lado del servidor, .NET Framework maneja el proceso de manera transparente. Sin
embargo, este proceso da como resultado que cada solicitud POST y PUT genere dos viajes de ida
y vuelta al servidor, incluso para solicitudes pequeñas. Si su aplicación no envía solicitudes con
grandes cantidades de datos, puede desactivar esta función utilizando la
ServicePointManagerclase para crear ServicePointobjetos en la aplicación cliente. Un
ServicePointobjeto maneja las conexiones que el cliente realiza a un servidor según el esquema y
alberga fragmentos de URI que identifican recursos en el servidor. A continuación, puede
establecer la Expect100Continuepropiedad de laServicePointobjeto falso. Todas las solicitudes
POST y PUT posteriores realizadas por el cliente a través de un URI que coincida con el esquema y
los fragmentos de host del ServicePointobjeto se enviarán sin encabezados Expect: 100-Continue.
El siguiente código muestra cómo configurar un ServicePointobjeto que configura todas las
solicitudes enviadas a URI con un esquema de httpy un host de www.contoso.com.

C#
Dupdo

Uri uri = new Uri("https://www.contoso.com/");

ServicePoint sp = ServicePointManager.FindServicePoint(uri);

sp.Expect100Continue = false;

También puede configurar la Expect100Continuepropiedad estática de la


ServicePointManagerclase para especificar el valor predeterminado de esta propiedad para todos
los objetos ServicePoint creados posteriormente.

Admite paginación para solicitudes que pueden devolver una gran cantidad de objetos

Si una colección contiene una gran cantidad de recursos, emitir una solicitud GET al URI
correspondiente podría generar un procesamiento significativo en el servidor que aloja la API web,
lo que afectaría el rendimiento y generaría una cantidad significativa de tráfico de red, lo que
generaría una mayor latencia.

Para manejar estos casos, la API web debe admitir cadenas de consulta que permitan a la
aplicación del cliente refinar las solicitudes o recuperar datos en bloques (o páginas) discretos y
más manejables. El siguiente código muestra el GetAllOrdersmétodo en el Orderscontrolador. Este
método recupera los detalles de los pedidos. Si este método no tuviera restricciones,
posiblemente podría devolver una gran cantidad de datos. Los parámetros limity offsetestán
destinados a reducir el volumen de datos a un subconjunto más pequeño, en este caso solo los
primeros 10 pedidos por defecto:

C#

Dupdo

public class OrdersController : ApiController

...

[Route("api/orders")]

[HttpGet]

public IEnumerable<Order> GetAllOrders(int limit=10, int offset=0)

// Find the number of orders specified by the limit parameter


// starting with the order specified by the offset parameter

var orders = ...

return orders;

...

Una aplicación de cliente puede emitir una solicitud para recuperar 30 pedidos a partir del
desplazamiento 50 utilizando el URI https://www.adventure-works.com/api/orders?
limit=30&offset=50.

Propina

Evite permitir que las aplicaciones cliente especifiquen cadenas de consulta que den como
resultado un URI de más de 2000 caracteres. Muchos clientes y servidores web no pueden
manejar URI que son tan largos.

Mantener la capacidad de respuesta, la escalabilidad y la disponibilidad

Muchas aplicaciones cliente que se ejecutan en cualquier parte del mundo pueden utilizar la
misma API web. Es importante asegurarse de que la API web se implemente para mantener la
capacidad de respuesta bajo una carga pesada, para que sea escalable para admitir una carga de
trabajo muy variable y para garantizar la disponibilidad para los clientes que realizan operaciones
críticas para el negocio. Considere los siguientes puntos al determinar cómo cumplir con estos
requisitos:

Proporcione soporte asíncrono para solicitudes de ejecución prolongada

Una solicitud que puede tardar mucho tiempo en procesarse debe realizarse sin bloquear al
cliente que envió la solicitud. La API web puede realizar una verificación inicial para validar la
solicitud, iniciar una tarea separada para realizar el trabajo y luego devolver un mensaje de
respuesta con el código HTTP 202 (Aceptado). La tarea podría ejecutarse de forma asíncrona como
parte del procesamiento de la API web o podría descargarse a una tarea en segundo plano.

La API web también debe proporcionar un mecanismo para devolver los resultados del
procesamiento a la aplicación cliente. Puede lograr esto proporcionando un mecanismo de sondeo
para que las aplicaciones cliente consulten periódicamente si el procesamiento ha finalizado y
obtenga el resultado, o habilitando la API web para enviar una notificación cuando la operación
haya finalizado.

Puede implementar un mecanismo de sondeo simple al proporcionar un URI de sondeo que actúa
como un recurso virtual mediante el siguiente enfoque:

La aplicación cliente envía la solicitud inicial a la API web.

La API web almacena información sobre la solicitud en una tabla que se encuentra en el
almacenamiento de tablas o en la caché de Microsoft Azure, y genera una clave única para esta
entrada, posiblemente en forma de GUID.

La API web inicia el procesamiento como una tarea separada. La API web registra el estado de la
tarea en la tabla como En ejecución .

La API web devuelve un mensaje de respuesta con el código de estado HTTP 202 (Aceptado) y el
GUID de la entrada de la tabla en el cuerpo del mensaje.

Cuando la tarea se ha completado, la API web almacena los resultados en la tabla y establece el
estado de la tarea en Completado . Tenga en cuenta que si la tarea falla, la API web también
podría almacenar información sobre la falla y establecer el estado en Failed .

Mientras se ejecuta la tarea, el cliente puede continuar realizando su propio procesamiento.


Puede enviar periódicamente una solicitud al URI /polling/{guid} donde {guid} es el GUID devuelto
en el mensaje de respuesta 202 por la API web.

La API web en el URI /polling/{guid} consulta el estado de la tarea correspondiente en la tabla y


devuelve un mensaje de respuesta con el código de estado HTTP 200 (OK) que contiene este
estado ( Running , Complete o Failed ). Si la tarea se completó o falló, el mensaje de respuesta
también puede incluir los resultados del procesamiento o cualquier información disponible sobre
el motivo de la falla.

Las opciones para implementar notificaciones incluyen:

Usar un centro de notificaciones para enviar respuestas asincrónicas a las aplicaciones cliente.
Para obtener más información, consulte Envío de notificaciones a usuarios específicos mediante
Azure Notification Hubs .

Usar el modelo Comet para conservar una conexión de red persistente entre el cliente y el
servidor que aloja la API web, y usar esta conexión para enviar mensajes del servidor al cliente. El
artículo de la revista MSDN Building a Simple Comet Application in the Microsoft .NET Framework
describe una solución de ejemplo.
Uso de SignalR para enviar datos en tiempo real desde el servidor web al cliente a través de una
conexión de red persistente. SignalR está disponible para aplicaciones web ASP.NET como paquete
NuGet. Puede encontrar más información en el sitio web de ASP.NET SignalR .

Asegúrese de que cada solicitud no tenga estado

Cada solicitud debe considerarse atómica. No debe haber dependencias entre una solicitud
realizada por una aplicación cliente y las solicitudes posteriores enviadas por el mismo cliente.
Este enfoque ayuda en la escalabilidad; las instancias del servicio web se pueden implementar en
varios servidores. Las solicitudes de los clientes pueden dirigirse a cualquiera de estas instancias y
los resultados deben ser siempre los mismos. También mejora la disponibilidad por una razón
similar; si un servidor web falla, las solicitudes se pueden enrutar a otra instancia (mediante Azure
Traffic Manager) mientras el servidor se reinicia sin efectos negativos en las aplicaciones cliente.

Realice un seguimiento de los clientes e implemente la limitación para reducir las posibilidades de
ataques de DOS

Si un cliente específico realiza una gran cantidad de solicitudes dentro de un período de tiempo
determinado, podría monopolizar el servicio y afectar el desempeño de otros clientes. Para mitigar
este problema, una API web puede monitorear las llamadas de las aplicaciones del cliente, ya sea
rastreando la dirección IP de todas las solicitudes entrantes o registrando cada acceso
autenticado. Puede utilizar esta información para limitar el acceso a los recursos. Si un cliente
excede un límite definido, la API web puede devolver un mensaje de respuesta con el estado 503
(Servicio no disponible) e incluir un encabezado Reintentar después que especifica cuándo el
cliente puede enviar la siguiente solicitud sin que sea rechazada. Esta estrategia puede ayudar a
reducir las posibilidades de un ataque de denegación de servicio (DOS) de un conjunto de clientes
que bloquean el sistema.

Administre las conexiones HTTP persistentes con cuidado

El protocolo HTTP admite conexiones HTTP persistentes cuando están disponibles. La


especificación HTTP 1.0 agregó el encabezado Connection:Keep-Alive que permite que una
aplicación cliente indique al servidor que puede usar la misma conexión para enviar solicitudes
posteriores en lugar de abrir otras nuevas. La conexión se cierra automáticamente si el cliente no
reutiliza la conexión dentro de un período definido por el host. Este comportamiento es el
predeterminado en HTTP 1.1 que usan los servicios de Azure, por lo que no es necesario incluir
encabezados Keep-Alive en los mensajes.

Mantener una conexión abierta puede ayudar a mejorar la capacidad de respuesta al reducir la
latencia y la congestión de la red, pero puede ser perjudicial para la escalabilidad al mantener
abiertas las conexiones innecesarias durante más tiempo del necesario, lo que limita la capacidad
de conexión de otros clientes simultáneos. También puede afectar la duración de la batería si la
aplicación cliente se ejecuta en un dispositivo móvil; si la aplicación solo realiza solicitudes
ocasionales al servidor, mantener una conexión abierta puede hacer que la batería se agote más
rápidamente. Para garantizar que una conexión no sea persistente con HTTP 1.1, el cliente puede
incluir un encabezado Connection:Close con mensajes para anular el comportamiento
predeterminado. De manera similar, si un servidor maneja una gran cantidad de clientes, puede
incluir un encabezado Connection:Close en los mensajes de respuesta que deberían cerrar la
conexión y ahorrar recursos del servidor.

Nota

Las conexiones HTTP persistentes son una característica puramente opcional para reducir la
sobrecarga de la red asociada con el establecimiento repetido de un canal de comunicaciones. Ni
la API web ni la aplicación cliente deben depender de la disponibilidad de una conexión HTTP
persistente. No utilice conexiones HTTP persistentes para implementar sistemas de notificación al
estilo de Comet; en su lugar, debe usar sockets (o sockets web si están disponibles) en la capa TCP.
Finalmente, tenga en cuenta que los encabezados Keep-Alive tienen un uso limitado si una
aplicación cliente se comunica con un servidor a través de un proxy; solo la conexión con el cliente
y el proxy será persistente.

Publicación y administración de una API web

Para que una API web esté disponible para aplicaciones cliente, la API web debe implementarse en
un entorno de host. Este entorno suele ser un servidor web, aunque puede ser algún otro tipo de
proceso de host. Debe tener en cuenta los siguientes puntos al publicar una API web:

Todas las solicitudes deben autenticarse y autorizarse, y debe aplicarse el nivel adecuado de
control de acceso.

Una API web comercial puede estar sujeta a varias garantías de calidad con respecto a los tiempos
de respuesta. Es importante asegurarse de que el entorno del host sea escalable si la carga puede
variar significativamente con el tiempo.

Puede ser necesario medir las solicitudes con fines de monetización.

Puede ser necesario regular el flujo de tráfico a la API web e implementar la limitación para
clientes específicos que hayan agotado sus cuotas.

Los requisitos reglamentarios pueden exigir el registro y la auditoría de todas las solicitudes y
respuestas.

Para garantizar la disponibilidad, puede ser necesario monitorear el estado del servidor que aloja
la API web y reiniciarlo si es necesario.
Es útil poder desvincular estos problemas de los problemas técnicos relacionados con la
implementación de la API web. Por este motivo, considere crear una fachada , que se ejecute
como un proceso independiente y que enrute las solicitudes a la API web. La fachada puede
proporcionar las operaciones de gestión y reenviar solicitudes validadas a la API web. El uso de
una fachada también puede traer muchas ventajas funcionales, que incluyen:

Actuando como un punto de integración para múltiples API web.

Transformación de mensajes y traducción de protocolos de comunicación para clientes


construidos utilizando diversas tecnologías.

Almacenamiento en caché de solicitudes y respuestas para reducir la carga en el servidor que aloja
la API web.

Prueba de una API web

Una API web debe probarse tan minuciosamente como cualquier otra pieza de software. Debería
considerar crear pruebas unitarias para validar la funcionalidad.

La naturaleza de una API web trae sus propios requisitos adicionales para verificar que funcione
correctamente. Debes prestar especial atención a los siguientes aspectos:

Pruebe todas las rutas para verificar que invoquen las operaciones correctas. Tenga especial
cuidado con el código de estado HTTP 405 (Método no permitido) que se devuelve
inesperadamente, ya que esto puede indicar una discrepancia entre una ruta y los métodos HTTP
(GET, POST, PUT, DELETE) que se pueden enviar a esa ruta.

Envíe solicitudes HTTP a rutas que no las admitan, como enviar una solicitud POST a un recurso
específico (las solicitudes POST solo deben enviarse a colecciones de recursos). En estos casos, la
única respuesta válida debe ser el código de estado 405 (No permitido).

Verifique que todas las rutas estén protegidas correctamente y estén sujetas a las verificaciones
de autenticación y autorización correspondientes.

Nota
Es más probable que algunos aspectos de la seguridad, como la autenticación del usuario, sean
responsabilidad del entorno del host en lugar de la API web, pero aún es necesario incluir pruebas
de seguridad como parte del proceso de implementación.

Pruebe el manejo de excepciones realizado por cada operación y verifique que se devuelva una
respuesta HTTP apropiada y significativa a la aplicación cliente.

Verifique que los mensajes de solicitud y respuesta estén bien formados. Por ejemplo, si una
solicitud HTTP POST contiene los datos de un nuevo recurso en formato x-www-form-urlencoded,
confirme que la operación correspondiente analiza correctamente los datos, crea los recursos y
devuelve una respuesta que contiene los detalles del nuevo recurso. , incluido el encabezado de
ubicación correcto.

Verifique todos los enlaces y URI en los mensajes de respuesta. Por ejemplo, un mensaje HTTP
POST debería devolver el URI del recurso recién creado. Todos los enlaces HATEOAS deben ser
válidos.

Asegúrese de que cada operación devuelva los códigos de estado correctos para diferentes
combinaciones de entrada. Por ejemplo:

Si una consulta es exitosa, debe devolver el código de estado 200 (OK)

Si no se encuentra un recurso, la operación debe devolver el código de estado HTTP 404 (No
encontrado).

Si el cliente envía una solicitud que elimina correctamente un recurso, el código de estado debe
ser 204 (Sin contenido).

Si el cliente envía una solicitud que crea un nuevo recurso, el código de estado debe ser 201
(Creado).

Tenga cuidado con los códigos de estado de respuesta inesperados en el rango 5xx. Estos
mensajes generalmente son informados por el servidor host para indicar que no pudo cumplir con
una solicitud válida.

Pruebe las diferentes combinaciones de encabezado de solicitud que una aplicación cliente puede
especificar y asegúrese de que la API web devuelva la información esperada en los mensajes de
respuesta.
Pruebe las cadenas de consulta. Si una operación puede tomar parámetros opcionales (como
solicitudes de paginación), pruebe las diferentes combinaciones y el orden de los parámetros.

Verifique que las operaciones asincrónicas se completen correctamente. Si la API web admite la
transmisión de solicitudes que devuelven objetos binarios grandes (como video o audio),
asegúrese de que las solicitudes de los clientes no se bloqueen mientras se transmiten los datos. Si
la API web implementa el sondeo para operaciones de modificación de datos de ejecución
prolongada, verifique que las operaciones informen su estado correctamente a medida que
avanzan.

También debe crear y ejecutar pruebas de rendimiento para verificar que la API web funcione
satisfactoriamente bajo presión. Puede crear un proyecto de prueba de carga y rendimiento web
mediante Visual Studio Ultimate.

Uso de la gestión de API de Azure

En Azure, considere usar Azure API Management para publicar y administrar una API web. Con
esta función, puede generar un servicio que actúe como fachada para una o más API web. El
servicio es en sí mismo un servicio web escalable que puede crear y configurar mediante Azure
Portal. Puede usar este servicio para publicar y administrar una API web de la siguiente manera:

Implemente la API web en un sitio web, un servicio en la nube de Azure o una máquina virtual de
Azure.

Conecte el servicio de administración de API a la API web. Las solicitudes enviadas a la URL de la
API de administración se asignan a los URI en la API web. El mismo servicio de administración de
API puede enrutar solicitudes a más de una API web. Esto le permite agregar varias API web en un
solo servicio de administración. De manera similar, se puede hacer referencia a la misma API web
desde más de un servicio de administración de API si necesita restringir o dividir la funcionalidad
disponible para diferentes aplicaciones.

Nota

Los URI en los enlaces HATEOAS generados como parte de la respuesta a las solicitudes HTTP GET
deben hacer referencia a la URL del servicio de administración de la API y no al servidor web que
aloja la API web.
Para cada API web, especifique las operaciones HTTP que expone la API web junto con los
parámetros opcionales que una operación puede tomar como entrada. También puede configurar
si el servicio de administración de API debe almacenar en caché la respuesta recibida de la API
web para optimizar las solicitudes repetidas de los mismos datos. Registre los detalles de las
respuestas HTTP que puede generar cada operación. Esta información se utiliza para generar
documentación para desarrolladores, por lo que es importante que sea precisa y completa.

Puede definir operaciones manualmente con los asistentes proporcionados por Azure Portal o
puede importarlas desde un archivo que contenga las definiciones en formato WADL o Swagger.

Configure los ajustes de seguridad para las comunicaciones entre el servicio de administración de
API y el servidor web que aloja la API web. El servicio de administración de API actualmente
admite la autenticación básica y la autenticación mutua mediante certificados y la autorización de
usuario de OAuth 2.0.

Crea un producto. Un producto es la unidad de publicación; agrega las API web que conectó
previamente al servicio de administración al producto. Cuando se publica el producto, las API web
quedan disponibles para los desarrolladores.

Nota

Antes de publicar un producto, también puede definir grupos de usuarios que pueden acceder al
producto y agregar usuarios a estos grupos. Esto le da control sobre los desarrolladores y las
aplicaciones que pueden usar la API web. Si una API web está sujeta a aprobación, antes de poder
acceder a ella, un desarrollador debe enviar una solicitud al administrador del producto. El
administrador puede conceder o denegar el acceso al desarrollador. Los desarrolladores existentes
también pueden bloquearse si cambian las circunstancias.

Configure políticas para cada API web. Las políticas rigen aspectos tales como si se deben permitir
llamadas entre dominios, cómo autenticar clientes, si convertir entre formatos de datos XML y
JSON de forma transparente, si restringir llamadas desde un rango de IP dado, cuotas de uso y si
limitar la tasa de llamadas. . Las políticas se pueden aplicar globalmente en todo el producto, para
una sola API web en un producto o para operaciones individuales en una API web.

Para obtener más información, consulte la documentación de administración de API .


Propina

Azure proporciona Azure Traffic Manager que le permite implementar la conmutación por error y
el equilibrio de carga, y reducir la latencia en varias instancias de un sitio web alojado en
diferentes ubicaciones geográficas. Puede usar Azure Traffic Manager junto con API Management
Service; API Management Service puede enrutar solicitudes a instancias de un sitio web a través
de Azure Traffic Manager. Para obtener más información, consulte Métodos de enrutamiento de
Traffic Manager .

En esta estructura, si usa nombres DNS personalizados para sus sitios web, debe configurar el
registro CNAME adecuado para cada sitio web para que apunte al nombre DNS del sitio web de
Azure Traffic Manager.

Apoyando a los desarrolladores del lado del cliente

Los desarrolladores que construyen aplicaciones cliente generalmente requieren información


sobre cómo acceder a la API web y documentación sobre los parámetros, tipos de datos, tipos de
devolución y códigos de devolución que describen las diferentes solicitudes y respuestas entre el
servicio web y la aplicación cliente.

Documentar las operaciones REST para una API web

Azure API Management Service incluye un portal para desarrolladores que describe las
operaciones REST expuestas por una API web. Cuando un producto ha sido publicado aparece en
este portal. Los desarrolladores pueden usar este portal para registrarse para acceder; el
administrador puede entonces aprobar o denegar la solicitud. Si se aprueba al desarrollador, se le
asigna una clave de suscripción que se utiliza para autenticar las llamadas de las aplicaciones
cliente que desarrolla. Esta clave debe proporcionarse con cada llamada a la API web; de lo
contrario, será rechazada.

Este portal también ofrece:

Documentación del producto, listando las operaciones que expone, los parámetros requeridos y
las diferentes respuestas que se pueden devolver. Tenga en cuenta que esta información se
genera a partir de los detalles proporcionados en el paso 3 de la lista de Publicación de una API
web mediante el uso de la sección Servicio de administración de API de Microsoft Azure.

Fragmentos de código que muestran cómo invocar operaciones desde varios lenguajes, incluidos
JavaScript, C#, Java, Ruby, Python y PHP.
Una consola de desarrolladores que permite a un desarrollador enviar una solicitud HTTP para
probar cada operación en el producto y ver los resultados.

Una página donde el desarrollador puede informar cualquier problema o problema encontrado.

Azure Portal le permite personalizar el portal para desarrolladores para cambiar el estilo y el
diseño para que coincida con la marca de su organización.

Implementar un SDK de cliente

Crear una aplicación cliente que invoque solicitudes REST para acceder a una API web requiere
escribir una cantidad significativa de código para construir cada solicitud y formatearla de manera
adecuada, enviar la solicitud al servidor que aloja el servicio web y analizar la respuesta para
determinar si la solicitud tuvo éxito o falló y extrae los datos devueltos. Para aislar la aplicación
cliente de estas preocupaciones, puede proporcionar un SDK que envuelva la interfaz REST y
abstraiga estos detalles de bajo nivel dentro de un conjunto de métodos más funcional. Una
aplicación cliente utiliza estos métodos, que convierten de forma transparente las llamadas en
solicitudes REST y luego vuelven a convertir las respuestas en valores de retorno del método. Esta
es una técnica común que implementan muchos servicios, incluido el SDK de Azure.

La creación de un SDK del lado del cliente es una tarea considerable, ya que debe implementarse
de manera consistente y probarse cuidadosamente. Sin embargo, gran parte de este proceso se
puede hacer mecánico y muchos proveedores proporcionan herramientas que pueden
automatizar muchas de estas tareas.

Monitoreo de una API web

Dependiendo de cómo haya publicado e implementado su API web, puede monitorear la API web
directamente o puede recopilar información de uso y estado analizando el tráfico que pasa a
través del servicio de administración de API.

Supervisar una API web directamente

Si implementó su API web mediante la plantilla de API web de ASP.NET (ya sea como un proyecto
de API web o como una función web en un servicio en la nube de Azure) y Visual Studio 2013,
puede recopilar datos de disponibilidad, rendimiento y uso utilizando ASP.NET Application
Insights. Application Insights es un paquete que rastrea y registra de manera transparente
información sobre solicitudes y respuestas cuando la API web se implementa en la nube; una vez
que el paquete está instalado y configurado, no necesita modificar ningún código en su API web
para usarlo. Cuando implementa la API web en un sitio web de Azure, se examina todo el tráfico y
se recopilan las siguientes estadísticas:
Tiempo de respuesta del servidor.

Número de solicitudes del servidor y los detalles de cada solicitud.

Las principales solicitudes más lentas en términos de tiempo de respuesta promedio.

Los detalles de cualquier solicitud fallida.

El número de sesiones iniciadas por diferentes navegadores y agentes de usuario.

Las páginas vistas con más frecuencia (principalmente útiles para aplicaciones web en lugar de API
web).

Los diferentes roles de usuario que acceden a la API web.

Puede ver estos datos en tiempo real en Azure Portal. También puede crear pruebas web que
controlen el estado de la API web. Una prueba web envía una solicitud periódica a un URI
específico en la API web y captura la respuesta. Puede especificar la definición de una respuesta
exitosa (como el código de estado HTTP 200), y si la solicitud no devuelve esta respuesta, puede
hacer arreglos para que se envíe una alerta a un administrador. Si es necesario, el administrador
puede reiniciar el servidor que aloja la API web si ha fallado.

Para obtener más información, consulte Application Insights: Introducción a ASP.NET .

Monitoreo de una API web a través del servicio de administración de API

Si ha publicado su API web mediante el servicio API Management, la página API Management en
Azure Portal contiene un panel que le permite ver el rendimiento general del servicio. La página de
análisis le permite profundizar en los detalles de cómo se utiliza el producto. Esta página contiene
las siguientes pestañas:

uso _ Esta pestaña proporciona información sobre la cantidad de llamadas API realizadas y el
ancho de banda utilizado para manejar estas llamadas a lo largo del tiempo. Puede filtrar los
detalles de uso por producto, API y operación.

salud _ Esta pestaña le permite ver el resultado de las solicitudes de la API (los códigos de estado
HTTP devueltos), la efectividad de la política de almacenamiento en caché, el tiempo de respuesta
de la API y el tiempo de respuesta del servicio. Nuevamente, puede filtrar los datos de salud por
producto, API y operación.

actividad _ Esta pestaña proporciona un resumen de texto de la cantidad de llamadas exitosas,


llamadas fallidas, llamadas bloqueadas, tiempo de respuesta promedio y tiempos de respuesta
para cada producto, API web y operación. Esta página también enumera la cantidad de llamadas
realizadas por cada desarrollador.
De un vistazo Esta pestaña muestra un resumen de los datos de rendimiento, incluidos los
desarrolladores responsables de realizar la mayoría de las llamadas a la API y los productos, las API
web y las operaciones que recibieron estas llamadas.

Puede usar esta información para determinar si una operación o API web en particular está
causando un cuello de botella y, si es necesario, escalar el entorno del host y agregar más
servidores. También puede determinar si una o más aplicaciones están utilizando un volumen de
recursos desproporcionado y aplicar las políticas adecuadas para establecer cuotas y limitar las
tasas de llamadas.

Nota

Puede cambiar los detalles de un producto publicado y los cambios se aplican inmediatamente.
Por ejemplo, puede agregar o eliminar una operación de una API web sin necesidad de volver a
publicar el producto que contiene la API web.

Más información

ASP.NET Web API OData contiene ejemplos y más información sobre cómo implementar una API
web de OData mediante ASP.NET.

Introducción a la compatibilidad con lotes en Web API y Web API OData describe cómo
implementar operaciones por lotes en una API web mediante OData.

Los patrones de idempotencia en el blog de Jonathan Oliver brindan una descripción general de la
idempotencia y cómo se relaciona con las operaciones de administración de datos.

Las definiciones de códigos de estado en el sitio web de W3C contienen una lista completa de
códigos de estado HTTP y sus descripciones.

Ejecutar tareas en segundo plano con WebJobs proporciona información y ejemplos sobre el uso
de WebJobs para realizar operaciones en segundo plano.

Azure Notification Hubs notifica a los usuarios muestra cómo usar Azure Notification Hub para
enviar respuestas asincrónicas a las aplicaciones cliente.

API Management describe cómo publicar un producto que proporciona acceso controlado y
seguro a una API web.

La referencia de la API REST de Azure API Management describe cómo usar la API REST de API
Management para crear aplicaciones de administración personalizadas.

Los métodos de enrutamiento de Traffic Manager resumen cómo se puede usar Azure Traffic
Manager para equilibrar la carga de solicitudes en varias instancias de un sitio web que hospeda
una API web.
Application Insights: Introducción a ASP.NET proporciona información detallada sobre cómo
instalar y configurar Application Insights en un proyecto de API web de ASP.NET.

También podría gustarte