HTTPQUERY
Español

428 Precondition Required

Uso

El código de estado 428 Precondition Required indica que el servidor espera que las solicitudes HTTP de este tipo sean condicionales e incluyan una cabecera HTTP adecuada, como If-Match, If-None-Match, If-Modified-Since e If-Unmodified-Since.

Estas cabeceras HTTP las usan los clientes de forma opcional cuando el servidor las admite, pero en este caso el servidor exige su uso. Según el caso de uso, el objetivo es reducir las situaciones de pérdida de datos, como el problema de la “actualización perdida” (lost update).

Una actualización perdida se produce cuando un cliente usa GET para obtener un recurso, lo modifica y usa PUT para devolver la versión modificada al servidor. Sin interferencias de terceros no hay problema. Si después del GET inicial un tercero modifica el estado del recurso en el servidor, surge un conflicto. Si el cliente usa PUT sin comprobar antes el estado del recurso, la actualización del tercero queda sobrescrita (una actualización perdida).

Al imponer comprobaciones condicionales mediante ETags y fechas, se reducen las ocasiones en que los clientes sobrescriben actualizaciones, porque se hacen menos suposiciones sobre el estado del recurso.

Esto está relacionado con la respuesta 412 Precondition Failed, que el servidor envía cuando una o varias de las condiciones no se cumplen.

Impacto en SEO

Los motores de búsqueda como Google no indexarán una URL que responda con el estado 428. Las URL indexadas previamente que devuelvan este código de estado se eliminarán de los resultados de búsqueda.

Ejemplo

El cliente había obtenido anteriormente una copia del recurso y desde entonces ha modificado la copia local. Cuando el cliente intenta hacer PUT del recurso para actualizar el servidor, este responde con 428 Precondition Required porque las cabeceras HTTP no incluían ninguna comprobación condicional.

Solicitud

PUT /reservations.txt HTTP/1.1
Host: example.com

Respuesta

HTTP/1.1 428 Precondition Required
Content-Type: text/html
Content-Length: 193

<html>
  <head>
    <title>Conditional Update Required</title>
  </head>
  <body>
   <p>This PUT request must be done conditionally.
   Try again using If-Unmodified-Since.</p>
  </body>
</html>

Cómo solucionarlo

Obtenga primero el recurso con una solicitud GET y extraiga el valor de ETag de las cabeceras de respuesta. Después vuelva a enviar la solicitud modificadora (PUT, PATCH o DELETE) con una cabecera If-Match establecida al valor de ETag recuperado.

Como alternativa, use la cabecera If-Unmodified-Since con la fecha Last-Modified de la respuesta GET inicial. El servidor compara la fecha y continúa solo si el recurso no ha cambiado desde entonces.

El enfoque basado en ETag es más preciso. Las marcas de tiempo tienen una granularidad de segundos y pasan por alto ediciones rápidas y sucesivas. Los ETags cambian con cada modificación, sin importar el momento.

Asegúrese de que el GET usado para recuperar el ETag apunte al mismo recurso que la solicitud modificadora posterior. Usar un ETag de otro registro provoca una respuesta 412 Precondition Failed.

Las API construidas sobre SAP, Salesforce y plataformas similares suelen exigir solicitudes condicionales en las operaciones de actualización y eliminación. Consulte la documentación de la API para saber qué endpoints requieren precondiciones y qué cabeceras de validación se aceptan.

En el lado del servidor, la respuesta 428 ayuda a evitar el problema de la “actualización perdida”, en el que dos clientes que editan el mismo recurso se sobrescriben mutuamente. Incluir cabeceras ETag en todos los recursos mutables proporciona a los clientes los valores que necesitan para las solicitudes condicionales.

Referencias de código

.NET

HttpStatusCode.PreconditionRequired

Rust

http::StatusCode::PRECONDITION_REQUIRED

Rails

:precondition_required

Go

http.StatusPreconditionRequired

Symfony

Response::HTTP_PRECONDITION_REQUIRED

Python3.5+

http.HTTPStatus.PRECONDITION_REQUIRED

Apache HttpComponents Core

org.apache.hc.core5.http.HttpStatus.SC_PRECONDITION_REQUIRED

Angular

@angular/common/http/HttpStatusCode.PreconditionRequired