Header Ads Widget

Ticker

6/recent/ticker-posts

REST: Actualizaciones parciales con PATCH

En publicaciones anteriores aprendimos cómo actualizar / reemplazar recursos usando la operación HTTP PUT . También aprendimos sobre las diferencias entre POST, PUT y PATCH . En esta publicación ahora veremos cómo realizar actualizaciones parciales con el método HTTP PATCH.

Antes de comenzar, veamos rápidamente por qué las actualizaciones parciales pueden ser útiles:

  • Simplicidad: si un cliente solo desea actualizar un campo, una solicitud de actualización parcial puede ser más sencilla de implementar.
  • Ancho de banda: si las representaciones de sus recursos son bastante grandes, las actualizaciones parciales pueden reducir la cantidad de ancho de banda requerido.
  • Actualizaciones perdidas: los reemplazos de recursos con PUT pueden ser susceptibles del problema de actualización perdida. Si bien las actualizaciones parciales no resuelven este problema, pueden ayudar a reducir la cantidad de posibles conflictos.

El método PATCH HTTP

Otros como PUT o POST, el método PATCH no es parte del RFC HTTP original. Más tarde se agregó a través de RFC 5789 . El método PATCH no es seguro ni idempotente . Sin embargo, PATCH se suele utilizar de forma idempotente.

Una solicitud de PATCH puede contener uno o más cambios solicitados a un recurso. Si se solicita más de un cambio, el servidor debe asegurarse de que todos los cambios se apliquen de forma atómica. El RFC dice:

El servidor DEBE aplicar todo el conjunto de cambios de forma atómica y nunca proporcionar ([..]) una representación parcialmente modificada. Si no se puede aplicar correctamente todo el documento de parche, el servidor NO DEBE aplicar ninguno de los cambios.

El cuerpo de la solicitud de PATCH es bastante flexible. La RFC solo dice que el cuerpo de la solicitud debe contener instrucciones sobre cómo se debe modificar el recurso:

Con PATCH, [..], la entidad adjunta contiene un conjunto de instrucciones que describen cómo un recurso que reside actualmente en el servidor de origen debe modificarse para producir una nueva versión.

Esto significa que no tenemos que usar la misma representación de recursos para las solicitudes de PATCH que podríamos usar para las solicitudes PUT o GET. Podemos usar un tipo de medio completamente diferente para describir los cambios de recursos.

PATCH se puede utilizar de dos formas habituales que tienen sus pros y sus contras. Examinaremos ambos en las siguientes secciones.

Usar la representación de recursos estándar para enviar cambios (JSON Merge Patch)

La forma más intuitiva de usar PATCH es mantener la representación de recursos estándar que se usa en las solicitudes GET o PUT. Sin embargo, con PATCH solo incluimos los campos que deben cambiarse.

Supongamos que tenemos un recurso de producto simple La respuesta de una simple solicitud GET podría verse así:

1
GET /products/123
01
02
03
04
05
06
07
08
09
10
11
{
    "name""Cool Gadget",
    "description""It looks very cool",
    "price"4.50,
    "dimension": {
        "width"1.3,
        "height"2.52,
        "depth"0.9
    }
    "tags": ["cool""cheap""gadget"]
}

Ahora queremos aumentar el precio , eliminar la etiqueta barata y actualizar el ancho del producto Para lograr esto, podemos usar la siguiente solicitud de PATCH:

1
2
3
4
5
6
7
8
PATCH /products/123
{
    "price"6.20,
    "dimension": {
        "width"1.35
    }
    "tags": ["cool""gadget"]
}

Los campos no incluidos en la solicitud no deben modificarse. Para eliminar un elemento de la matriz de etiquetas , tenemos que incluir todos los elementos restantes de la matriz.

Este uso de PATCH se denomina JSON Merge Patch y se define en RFC 7396 . Puede pensar en una solicitud PUT que solo use un subconjunto de campos. Parchar de esta manera hace que las solicitudes de PATCH sean generalmente idempotentes.

JSON Merge Patch y valores nulos

Hay una advertencia con JSON Merge Patch que debe tener en cuenta: el procesamiento de valores nulos .

Supongamos que queremos eliminar la descripción del recurso de producto utilizado anteriormente La solicitud de PATCH se ve así:

1
2
3
4
PATCH /products/123
{
    "description"null
}

Para cumplir con la intención del cliente, el servidor debe diferenciar entre las siguientes situaciones:

  • El campo de descripción no forma parte del documento JSON. En este caso, la descripción no debe modificarse.
  • El campo de descripción es parte del documento JSON y tiene el valor nulo . Aquí, el servidor debería eliminar la descripción actual.

Tenga en cuenta esta diferenciación cuando utilice bibliotecas JSON que asignan documentos JSON a objetos. En lenguajes de programación fuertemente tipados como Java, es probable que ambos casos produzcan el mismo resultado cuando se mapea a un objeto fuertemente tipado (el campo de descripción puede resultar en ser nulo en ambos casos).

Por lo tanto, al admitir valores nulos , debe asegurarse de poder manejar ambas situaciones.

Usando un formato de parche separado

Como se mencionó anteriormente, está bien usar un tipo de medio diferente para las solicitudes de PATCH.

Nuevamente queremos aumentar el precio , eliminar la etiqueta barata y actualizar el ancho del producto Una forma diferente de lograr esto, podría verse así:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
PATCH /products/123
{
    "$.price": {
        "action""replace",
        "newValue"6.20
    },
    "$.dimension.width": {        
        "action""replace",
        "newValue"1.35
    },
    "$.tags[?(@ == 'cheap')]": {
        "action""remove"
    }
}

Aquí usamos expresiones JSONPath para seleccionar los valores que queremos cambiar. Para cada valor seleccionado, usamos un pequeño objeto JSON para describir la acción deseada.

Para reemplazar valores simples, este formato es bastante detallado. Sin embargo, también tiene algunas ventajas, especialmente cuando se trabaja con matrices. Como se muestra en el ejemplo, podemos eliminar un elemento de matriz sin enviar todos los elementos de matriz restantes. Esto puede resultar útil cuando se trabaja con matrices grandes.

Parche JSON

Un tipo de medio estandarizado para describir cambios usando JSON es JSON Patch (descrito en RFC 6902 ). Con JSON Patch, nuestra solicitud se ve así:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
dieciséis
17
18
19
PATCH /products/123
Content-Type: application/json-patch+json
 
[
    
        "op""replace"
        "path""/price"
        "value"6.20
    },
    {
        "op""replace",
        "path""/dimension/width",
        "value"1.35
    },
    {
        "op""remove"
        "path""/tags/1"
    }
]

Esto se parece un poco a nuestra solución anterior. JSON Patch usa el elemento op para describir la acción deseada. El elemento de ruta contiene un puntero JSON (otro RFC) para seleccionar el elemento al que se debe aplicar el cambio.

Tenga en cuenta que la versión actual de JSON Patch no admite la eliminación de un elemento de matriz por valor. En cambio, tenemos que eliminar el elemento usando el índice de la matriz. Con / tags / 1 podemos seleccionar el segundo elemento de la matriz.

Antes de usar JSON Patch, debe evaluar si satisface sus necesidades y si está de acuerdo con sus limitaciones. En los problemas del repositorio de GitHub json-patch2 , puede encontrar una discusión sobre una posible revisión de JSON Patch.

Si está utilizando XML en lugar de JSON, debería echar un vistazo a XML Patch ( RFC 5261 ) que funciona de manera similar, pero utiliza XML.

El encabezado Accept-Patch

El RFC para HTTP PATCH también define un nuevo encabezado de respuesta para las solicitudes HTTP OPTIONS: Accept-Patch . Con Accept-Patch, el servidor puede comunicar qué tipos de medios son compatibles con la operación PATCH para un recurso determinado. El RFC dice:

Accept-Patch DEBERÍA aparecer en la respuesta OPTIONS para cualquier recurso que admita el uso del método PATCH.

Un ejemplo de solicitud / respuesta HTTP OPTIONS para un recurso que admite el método PATCH y usa JSON Patch podría verse así:

Solicitud:

1
OPTIONS /products/123

Respuesta:

1
2
3
HTTP/1.1 200 OK
Allow: GET, PUT, POST, OPTIONS, HEAD, DELETE, PATCH
Accept-Patch: application/json-patch+json

Respuestas a las operaciones HTTP PATCH

El PATCH RFC no exige cómo debe verse el cuerpo de respuesta de una operación PATCH. Está bien devolver el recurso actualizado. También está bien dejar el cuerpo de respuesta vacío.

El servidor responde a las solicitudes HTTP PATCH generalmente con uno de los siguientes códigos de estado HTTP :

  • 204 (Sin contenido): indica que la operación se ha completado correctamente y no se devuelven datos
  • 200 (Ok): la operación se completó correctamente y el cuerpo de la respuesta contiene más información (por ejemplo, el recurso actualizado).
  • 400 (Solicitud incorrecta): el cuerpo de la solicitud tiene un formato incorrecto y no se puede procesar.
  • 409 (Conflicto): la solicitud es sintácticamente válida pero no se puede aplicar al recurso. Por ejemplo, se puede usar con JSON Patch si el elemento seleccionado por un puntero JSON (el campo de ruta ) no existe.

Resumen

La operación PATCH es bastante flexible y se puede utilizar de diferentes formas. JSON Merge Patch utiliza representaciones de recursos estándar para realizar actualizaciones parciales. Sin embargo, JSON Patch utiliza un formato de PATCH independiente para describir los cambios deseados. también está bien crear un formato PATCH personalizado. Los recursos que admiten la operación PATCH deben devolver el encabezado Accept-Patch para las solicitudes OPTIONS.

Publicar un comentario

0 Comentarios