rails - ¿Por qué HTTP PUT no permite realizar actualizaciones parciales en una API REST?
rails put vs patch (3)
¿Quién dice que las API RESTful deben soportar actualizaciones parciales por separado a través de HTTP PATCH?
Parece que no tiene beneficios. Agrega más trabajo para implementar en el lado del servidor y más lógica en el lado del cliente para decidir qué tipo de actualización solicitar.
Formulo esta pregunta en el contexto de la creación de una API REST con HTTP que proporciona abstracción a modelos de datos conocidos. Requerir PATCH para actualizaciones parciales en lugar de PUT para parcial o total parece que no tiene ningún beneficio, pero podría persuadirse.
Relacionado
http://restcookbook.com/HTTP%20Methods/idempotency/ - esto implica que no tiene control sobre el software del servidor que puede almacenar en caché las solicitudes.
¿Cuál es la justificación detrás de no permitir parcial PUT? - no se da una respuesta clara, solo referencia a lo que HTTP define para PUt frente a PATCH.
http://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/17415 - muestra la división de pensamientos sobre esto.
¿Quien dice? El tipo que inventó REST dice:
@mnot Oy, sí, PATCH fue algo que creé para la propuesta inicial de HTTP / 1.1 porque PUT parcial nunca es RESTful. ;-)
https://twitter.com/fielding/status/275471320685367296
En primer lugar, REST es un estilo arquitectónico, y uno de sus principios es aprovechar el comportamiento estandarizado del protocolo subyacente, por lo que si desea implementar una API RESTful sobre HTTP, debe seguir HTTP estrictamente para que sea Sosegado. Eres libre de no hacerlo si crees que no es adecuado para tus necesidades, nadie te maldecirá por eso, pero entonces no estás haciendo REST. Tendrá que documentar dónde y cómo se desvía del estándar, creando un fuerte acoplamiento entre las implementaciones del cliente y del servidor, y el objetivo de usar REST es precisamente evitar eso y enfocarse en sus tipos de medios.
Entonces, basado en RFC 7231, PUT debe usarse solo para el reemplazo completo de una representación, en una operación idempotente. PATCH debe usarse para actualizaciones parciales, que no se requiere que sean idempotentes, pero es bueno hacerlas idempotentes al requerir una precondición o validar el estado actual antes de aplicar el diff. Si necesita realizar actualizaciones no idempotentes, parciales o no, use POST. Sencillo. Todo el mundo que use su API y sepa cómo funcionan PUT y PATCH espera que funcione de esa manera, y usted no tiene que documentar ni explicar qué deberían hacer los métodos para un recurso dado. Puede hacer que PUT actúe de cualquier otra forma que le parezca, pero deberá documentarlo para sus clientes, y deberá encontrar otra palabra de moda para su API, porque eso no es RESTful.
Tenga en cuenta que REST es un estilo arquitectónico centrado en la evolución a largo plazo de su API. Hacerlo bien agregará más trabajo ahora, pero hará que los cambios sean más fáciles y menos traumáticos más adelante. Eso no significa que REST sea adecuado para todo y para todos. Si su enfoque es la facilidad de implementación y el uso a corto plazo, simplemente use los métodos que desee. Puede hacer todo a través de POST si no desea preocuparse por los clientes que eligen los métodos correctos.
Para ampliar la respuesta existente , se supone que PUT
realiza una actualización completa (sobrescritura) del estado del recurso simplemente porque HTTP define el método de esta manera. El RFC 2616 original sobre HTTP / 1.1 no es muy explícito al respecto, RFC 7231 agrega aclaraciones semánticas:
El método PUT solicita que el estado del recurso objetivo sea creado o reemplazado por el estado definido por la representación incluida en la carga útil del mensaje de solicitud. Un PUT exitoso de una representación dada sugeriría que un GET posterior en ese mismo recurso objetivo dará como resultado que se envíe una representación equivalente en una respuesta 200 (OK).
Como se indica en la otra respuesta, adherirse a esta convención simplifica la comprensión y el uso de las API, y no es necesario documentar explícitamente el comportamiento del método PUT.
Sin embargo, las actualizaciones parciales no están prohibidas debido a la idempotencia. Me parece importante destacar esto, ya que estos conceptos a menudo se confunden, incluso en muchas respuestas de (por ejemplo, here ).
Idempotent significa únicamente que la aplicación de una solicitud una o más veces produce el mismo efecto en el servidor. Para citar RFC 7231 una vez más:
Un método de solicitud se considera "idempotente" si el efecto deseado en el servidor de múltiples solicitudes idénticas con ese método es el mismo que el efecto para una única solicitud de este tipo.
Siempre que una actualización parcial contenga solo nuevos valores del estado del recurso y no dependa de valores previos (es decir, esos valores se sobrescriben), se cumple el requisito de idempotencia. Independientemente de cuántas veces se aplique dicha actualización parcial, el estado del servidor siempre mantendrá los valores especificados en la solicitud.
Si una solicitud intermedia de otro cliente puede cambiar una parte diferente del recurso no es relevante, porque idempotencia se refiere a la operación (es decir, el método PUT
), no al estado en sí. Y con respecto a la operación de una actualización de sobrescritura parcial, su aplicación produce el mismo efecto después de ser aplicada una o más veces.
Por el contrario, una operación que no es idempotente depende del estado actual del servidor, por lo tanto, conduce a diferentes resultados dependiendo de cuántas veces se ejecuta. El ejemplo más fácil para esto es incrementar un número (no idempotente) vs. establecerlo en un valor absoluto (idempotente).
Para cambios no idempotentes, HTTP prevé los métodos POST
y PATCH
, mientras que PATCH
está diseñado explícitamente para llevar modificaciones a un recurso existente, mientras que POST
se puede interpretar mucho más libremente con respecto a la URI de solicitud, contenido corporal y efectos secundarios en el servidor .
¿Qué significa esto en la práctica? REST es un paradigma para implementar API sobre el protocolo HTTP, una convención que muchas personas han considerado razonable y, por lo tanto, es probable que sea adoptada o entendida. Aún así, hay controversias con respecto a lo que es RESTful y lo que no, pero incluso dejando de lado esas cosas, REST no es la única forma correcta o significativa de crear HTTP API.
El protocolo HTTP en sí mismo impone restricciones sobre lo que puede y no puede hacer, y muchos de ellos tienen un impacto práctico real. Por ejemplo, ignorar la idempotencia puede hacer que los servidores de caché cambien el número de solicitudes realmente emitidas por el cliente y, posteriormente, interrumpan la lógica esperada por las aplicaciones. Por lo tanto, es crucial estar al tanto de las implicaciones cuando se desvía del estándar.
Al ser estrictamente REST, no hay una solución completamente satisfactoria para las actualizaciones parciales (algunos incluso dicen que esta necesidad por sí sola va en contra de REST). El problema es que PATCH
, que primero parece estar hecho solo para este propósito, no es idempotente. Por lo tanto, al usar PATCH
para las actualizaciones parciales idempotentes, se pierden las ventajas de la idempotencia (número arbitrario de reintentos automáticos, lógica más simple, potencial de optimizaciones en el cliente, el servidor y la red). Como tal, puede preguntarse si el uso de PUT
es realmente la peor idea, siempre que el comportamiento esté claramente documentado y no se rompa porque los usuarios (y los nodos de red intermedios) confían en cierto comportamiento ...
PUT permite las actualizaciones parciales (según RFC 7231 http://tools.ietf.org/html/rfc7231#section-4.3.4 ).
", ... La solicitud PUT se define como la sustitución del estado del recurso objetivo." - reemplazar una parte del objeto básicamente cambia el estado de la misma.
"Las actualizaciones de contenido parciales son posibles apuntando a un recurso identificado por separado con un estado que se superpone a una parte del recurso más grande, ..."
De acuerdo con esa próxima solicitud de RFC es válida: PUT / resource / 123 {name: ''new name''} Cambiará solo el nombre del recurso especificado. Especificar el ID dentro de la carga útil de la solicitud sería incorrecto (ya que PUT no permite actualizaciones parciales para recursos no especificados).
PD: A continuación se muestra un ejemplo cuando PATCH es útil.
Hay un objeto que tiene Array adentro. Con PUT no puede actualizar el valor específico. Solo puedes reemplazar toda la lista por una nueva. Con PATCH, puede reemplazar un valor por otro. Con mapas y objetos más complejos, el beneficio será aún mayor.