http - example - PUT vs POST en REST
rest post example (30)
El servidor de origen puede crear el recurso con ese URI.
Entonces usa POST y probablemente, pero no es necesario, PUT para la creación de recursos. No tienes que apoyar a ambos. Para mi POST es perfectamente suficiente. Así que es una decisión de diseño.
Como mencionó su cita, usted usa PUT para la creación de que no hay un recurso asignado a un IRI, y desea crear un recurso de todos modos. Por ejemplo, PUT /users/123/password
generalmente reemplaza la contraseña anterior por una nueva, pero puede usarla para crear una contraseña si aún no existe (por ejemplo, usuarios recién registrados o restaurando usuarios prohibidos).
Según la especificación de HTTP / 1.1:
El método
POST
se utiliza para solicitar que el servidor de origen acepte la entidad incluida en la solicitud como un nuevo subordinado del recurso identificado por elRequest-URI
deRequest-Line
En otras palabras, POST
se utiliza para crear .
El método
PUT
solicita que la entidad adjunta se almacene bajo elRequest-URI
suministrado. Si laRequest-URI
refiere a un recurso ya existente, la entidad adjunta DEBERÍA considerarse como una versión modificada de la que reside en el servidor de origen. Si elRequest-URI
no apunta a un recurso existente, y ese URI es capaz de ser definido como un nuevo recurso por el agente del usuario solicitante, el servidor de origen puede crear el recurso con ese URI ".
Es decir, PUT
se utiliza para crear o actualizar .
Entonces, ¿cuál debería usarse para crear un recurso? ¿O uno necesita apoyar a ambos?
Resumen:
Crear:
Se puede realizar tanto con PUT como con POST de la siguiente manera:
PONER
Crea el nuevo recurso con newResourceId como el identificador, bajo la URI / recursos, o colección .
PUT /resources/<newResourceId> HTTP/1.1
ENVIAR
Crea un nuevo recurso bajo el URI / recursos, o colección . Normalmente el identificador es devuelto por el servidor.
POST /resources HTTP/1.1
Actualizar:
Solo se puede realizar con PUT de la siguiente manera:
PONER
Actualiza el recurso con existingResourceId como el identificador, bajo el URI / resources, o colección .
PUT /resources/<existingResourceId> HTTP/1.1
Explicación:
Cuando se trata de REST y URI como general, tiene genérico a la izquierda y específico a la derecha . Los genéricos se suelen llamar colecciones y los elementos más específicos se pueden llamar recurso . Tenga en cuenta que un recurso puede contener una colección .
Ejemplos:
<- genérico - específico ->
URI: website.com/users/john website.com - whole site users - collection of users john - item of the collection, or a resource URI:website.com/users/john/posts/23 website.com - whole site users - collection of users john - item of the collection, or a resource posts - collection of posts from john 23 - post from john with identifier 23, also a resource
Cuando usa POST, siempre se está refiriendo a una colección , por lo que siempre que diga:
POST /users HTTP/1.1
estás publicando un nuevo usuario en la colección de usuarios .
Si sigues e intentas algo como esto:
POST /users/john HTTP/1.1
funcionará, pero semánticamente está diciendo que desea agregar un recurso a la colección de john en la colección de usuarios .
Una vez que esté utilizando PUT, se está refiriendo a un recurso o elemento individual, posiblemente dentro de una colección . Así que cuando dices:
PUT /users/john HTTP/1.1
le está diciendo a la actualización del servidor, o cree, si no existe, el recurso john en la colección de usuarios .
Especulación:
Permítanme resaltar algunas partes importantes de la especificación:
ENVIAR
El método POST se utiliza para solicitar que el servidor de origen acepte la entidad incluida en la solicitud como un nuevo subordinado del recurso identificado por el URI de solicitud en la línea de solicitud
Por lo tanto, crea un nuevo recurso en una colección .
PONER
El método PUT solicita que la entidad adjunta se almacene bajo el URI de solicitud suministrado. Si la Solicitud-URI se refiere a un recurso ya existente , la entidad adjunta DEBERÍA considerarse como una versión modificada de la que reside en el servidor de origen. Si el Request-URI no apunta a un recurso existente , y ese URI es capaz de ser definido como un nuevo recurso por el agente del usuario solicitante, el servidor de origen puede crear el recurso con ese URI ".
Por lo tanto, crear o actualizar en función de la existencia del recurso .
Referencia:
Me gustaría añadir mi consejo "pragmático". Use PUT cuando sepa el "id" por el cual se puede recuperar el objeto que está guardando. El uso de PUT no funcionará demasiado bien si necesita, por ejemplo, una ID generada en la base de datos que se le devolverá para que pueda realizar futuras búsquedas o actualizaciones.
Entonces: para guardar un usuario existente, o uno donde el cliente genere la identificación y se haya verificado que la identificación es única:
PUT /user/12345 HTTP/1.1 <-- create the user providing the id 12345
Host: mydomain.com
GET /user/12345 HTTP/1.1 <-- return that user
Host: mydomain.com
De lo contrario, use POST para crear inicialmente el objeto, y PUT para actualizar el objeto:
POST /user HTTP/1.1 <--- create the user, server returns 12345
Host: mydomain.com
PUT /user/12345 HTTP/1.1 <--- update the user
Host: mydomain.com
POST significa "crear nuevo" como en "Aquí está la entrada para crear un usuario, créelo por mí".
PUT significa "insertar, reemplazar si ya existe" como en "Aquí están los datos para el usuario 5".
PUBLICAS en example.com/users porque aún no conoces la URL del usuario, quieres que el servidor la cree.
PONE en example.com/users/id ya que desea reemplazar / crear un usuario específico .
POSTing dos veces con los mismos datos significa crear dos usuarios idénticos con diferentes identificaciones. Poner dos veces con los mismos datos crea al usuario el primero y lo actualiza al mismo estado la segunda vez (sin cambios). Ya que terminas con el mismo estado después de un PUT, no importa cuántas veces lo realices, se dice que es "igualmente potente" cada vez: idempotente. Esto es útil para reintentar automáticamente las solicitudes. No más "¿está seguro de que desea volver a enviar" cuando presiona el botón Atrás en el navegador?
Un consejo general es utilizar POST cuando necesite que el servidor controle la generación de URL de sus recursos. Utilice PUT de lo contrario. Prefiero PUT sobre POST.
REST es un concepto de muy alto nivel. De hecho, ¡ni siquiera menciona HTTP en absoluto!
Si tiene alguna duda sobre cómo implementar REST en HTTP, siempre puede consultar la especificación Atom Publication Protocol (AtomPub) . AtomPub es un estándar para escribir servicios web RESTful con HTTP que fue desarrollado por muchas luminarias HTTP y REST, con algunas aportaciones de Roy Fielding, el inventor de REST y (co) inventor de HTTP.
De hecho, es posible que incluso puedas usar AtomPub directamente. Si bien salió de la comunidad de blogs, no se limita de ninguna manera a los blogs: es un protocolo genérico para interactuar RESTAMENTE con colecciones arbitrarias (anidadas) de recursos arbitrarios a través de HTTP. Si puede representar su aplicación como una colección anidada de recursos, entonces solo puede usar AtomPub y no preocuparse por usar PUT o POST, qué códigos de estado HTTP devolver y todos esos detalles.
Esto es lo que AtomPub tiene que decir sobre la creación de recursos (sección 9.2):
Para agregar miembros a una Colección, los clientes envían solicitudes POST al URI de la Colección.
Use POST para crear, y PUT para actualizar. Así es como lo hace Ruby on Rails, de todos modos.
PUT /items/1 #=> update
POST /items #=> create
Usted puede encontrar afirmaciones en la web que dicen
- POST debe utilizarse para crear un recurso, y PUT debe utilizarse para modificar uno
- Se debe usar PUT para crear un recurso, y POST debe usarse para modificar uno
Tampoco está del todo bien.
Mejor es elegir entre PUT y POST en función de la idempotence de la acción.
PUT implica poner un recurso: reemplazar por completo lo que esté disponible en la URL dada por algo diferente. Por definición, un PUT es idempotente. Hazlo tantas veces como quieras, y el resultado es el mismo. x=5
es idempotente. Puede PONER un recurso, ya sea que exista previamente o no (por ejemplo, para Crear o Actualizar).
POST actualiza un recurso, agrega un recurso subsidiario o provoca un cambio. Un POST no es idempotente, de la manera en que x++
no es idempotente.
Por este argumento, PUT es para crear cuando conoce la URL de lo que creará. POST se puede utilizar para crear cuando conoce la URL de la "fábrica" ​​o el administrador de la categoría de cosas que desea crear.
asi que:
POST /expense-report
o:
PUT /expense-report/10929
En general:
Se pueden usar tanto PUT como POST para crear.
Tienes que preguntar "¿a qué estás realizando la acción?" para distinguir lo que debes usar. Supongamos que estás diseñando una API para hacer preguntas. Si desea utilizar POST, debe hacerlo en una lista de preguntas. Si quieres usar PUT, entonces harías eso con una pregunta en particular.
Se pueden usar ambos, por lo que debería usar en mi diseño RESTful:
No es necesario que admita PUT y POST.
Lo que se usa se deja a ti. Pero recuerde usar el correcto en función del objeto al que haga referencia en la solicitud.
Algunas consideraciones:
- ¿Nombra sus objetos URL que crea explícitamente o deja que el servidor decida? Si los nombras, entonces usa PUT. Si dejas que el servidor decida, usa POST.
- PUT es idempotente, por lo que si PONE un objeto dos veces, no tendrá ningún efecto. Esta es una buena propiedad, así que usaría PUT cuando sea posible.
- Puede actualizar o crear un recurso con PUT con la misma URL de objeto
- Con POST puede recibir 2 solicitudes al mismo tiempo que realiza modificaciones a una URL, y pueden actualizar diferentes partes del objeto.
Un ejemplo:
Escribí lo siguiente como parte de otra respuesta en SO sobre esto :
ENVIAR:
Utilizado para modificar y actualizar un recurso.
POST /questions/<existing_question> HTTP/1.1 Host: www.example.com/
Tenga en cuenta que lo siguiente es un error:
POST /questions/<new_question> HTTP/1.1 Host: www.example.com/
Si la URL aún no se ha creado, no debe usar POST para crearla mientras especifica el nombre. Esto debería dar como resultado un error de ''recurso no encontrado'' porque
<new_question>
aún no existe.<new_question>
debe PONER el<new_question>
en el servidor.Sin embargo, podría hacer algo como esto para crear recursos utilizando POST:
POST /questions HTTP/1.1 Host: www.example.com/
Tenga en cuenta que en este caso no se especifica el nombre del recurso, se le devolverá la nueva ruta de la URL de los objetos.
PONER:
Se utiliza para crear un recurso, o sobrescribirlo. Mientras especificas los recursos, la nueva URL.
Para un nuevo recurso:
PUT /questions/<new_question> HTTP/1.1 Host: www.example.com/
Para sobrescribir un recurso existente:
PUT /questions/<existing_question> HTTP/1.1 Host: www.example.com/
La decisión de utilizar PUT o POST para crear un recurso en un servidor con una API HTTP + REST se basa en quién posee la estructura de URL. Hacer que el cliente sepa, o participe en la definición, la estructura de URL es un acoplamiento innecesario similar a los acoplamientos indeseables que surgieron de SOA. Escapar de tipos de acoplamientos es la razón por la cual REST es tan popular. Por lo tanto, el método apropiado para usar es POST. Hay excepciones a esta regla y ocurren cuando el cliente desea mantener el control sobre la estructura de ubicación de los recursos que implementa. Esto es raro y probablemente significa que algo más está mal.
En este punto, algunas personas argumentarán que si se usan RESTful-URL , el cliente conoce la URL del recurso y, por lo tanto, un PUT es aceptable. Después de todo, esta es la razón por la cual las URL canónicas y normalizadas de Ruby on Rails, Django son importantes, mire la API de Twitter ... bla bla bla. Esas personas deben comprender que no existe tal cosa como una URL Restful y que el propio Roy Fielding afirma que :
Una API REST no debe definir nombres o jerarquías de recursos fijos (un acoplamiento obvio de cliente y servidor). Los servidores deben tener la libertad de controlar su propio espacio de nombres. En su lugar, permita que los servidores instruyan a los clientes sobre cómo construir los URI apropiados, como se hace en formularios HTML y plantillas de URI, definiendo esas instrucciones dentro de los tipos de medios y las relaciones de enlace. [La falla aquí implica que los clientes están asumiendo una estructura de recursos debido a la información fuera de banda, como un estándar específico del dominio, que es el equivalente orientado a los datos al acoplamiento funcional de RPC].
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
La idea de una URL RESTful es en realidad una violación de REST, ya que el servidor está a cargo de la estructura de la URL y debe ser libre de decidir cómo usarla para evitar el acoplamiento. Si esto te confunde, lees sobre el significado del descubrimiento automático en el diseño de API.
El uso de POST para crear recursos conlleva una consideración de diseño porque POST no es idempotente. Esto significa que repetir un POST varias veces no garantiza el mismo comportamiento cada vez. Esto asusta a las personas a usar PUT para crear recursos cuando no deberían. Saben que está mal (POST es para CREAR) pero lo hacen de todos modos porque no saben cómo resolver este problema. Esta preocupación se demuestra en la siguiente situación:
- El cliente envía un nuevo recurso al servidor.
- El servidor procesa la solicitud y envía una respuesta.
- El cliente nunca recibe la respuesta.
- El servidor desconoce que el cliente no ha recibido la respuesta.
- El cliente no tiene una URL para el recurso (por lo tanto, PUT no es una opción) y repite el POST.
- POST no es idempotente y el servidor ...
El paso 6 es donde las personas comúnmente se confunden sobre qué hacer. Sin embargo, no hay razón para crear un kludge para resolver este problema. En su lugar, HTTP se puede usar como se especifica en RFC 2616 y el servidor responde:
10.4.10 409 Conflicto
La solicitud no se pudo completar debido a un conflicto con el estado actual del recurso. Este código solo se permite en situaciones donde se espera que el usuario pueda resolver el conflicto y volver a enviar la solicitud. El cuerpo de respuesta DEBE incluir suficiente
Información para que el usuario reconozca la fuente del conflicto. Idealmente, la entidad de respuesta incluiría suficiente información para que el usuario o el agente de usuario solucione el problema; Sin embargo, eso podría no ser posible y no es obligatorio.
Es más probable que ocurran conflictos en respuesta a una solicitud PUT. Por ejemplo, si se estaban utilizando las versiones y la entidad PUT incluía cambios en un recurso que entraba en conflicto con los pedidos realizados por un tercero, el servidor podría usar la respuesta 409 para indicar que no puede completar la solicitud. . En este caso, la entidad de respuesta probablemente contendría una lista de las diferencias entre las dos versiones en un formato definido por el tipo de contenido de respuesta.
Responder con un código de estado de 409 Conflicto es el recurso correcto porque :
- Realizar una POST de datos que tenga una ID que coincida con un recurso que ya se encuentra en el sistema es "un conflicto con el estado actual del recurso".
- Dado que la parte importante es que el cliente entienda que el servidor tiene el recurso y que debe tomar las medidas adecuadas. Esta es una "situación (es) en la que se espera que el usuario pueda resolver el conflicto y volver a enviar la solicitud".
- Una respuesta que contenga la URL del recurso con el ID en conflicto y las condiciones previas apropiadas para el recurso proporcionaría "suficiente información para que el usuario o el agente de usuario solucione el problema", que es el caso ideal según RFC 2616.
Actualización basada en el lanzamiento de RFC 7231 para reemplazar 2616
El RFC 7231 está diseñado para reemplazar 2616 y en la Sección 4.3.3 describe la siguiente respuesta posible para un POST
Si el resultado de procesar un POST sería equivalente a una representación de un recurso existente, un servidor de origen PUEDE redirigir al agente de usuario a ese recurso enviando una respuesta 303 (Ver Otro) con el identificador del recurso existente en el campo Ubicación. Esto tiene los beneficios de proporcionar al agente de usuario un identificador de recursos y transferir la representación a través de un método más adecuado para el almacenamiento en caché compartido, aunque al costo de una solicitud adicional si el agente de usuario aún no tiene la representación en caché.
Ahora puede ser tentador simplemente devolver un 303 en caso de que se repita un POST. Sin embargo, lo opuesto es verdadero. Devolver un 303 solo tendría sentido si varias solicitudes de creación (creando diferentes recursos) devuelven el mismo contenido. Un ejemplo sería un "agradecimiento por enviar el mensaje de solicitud" que el cliente no necesita volver a descargar cada vez. RFC 7231 aún mantiene en la sección 4.2.2 que POST no debe ser idempotente y continúa manteniendo que POST debe usarse para crear.
Para más información sobre esto, lea este article .
Nueva respuesta (ahora que entiendo mejor a REST):
PUT es simplemente una declaración de qué contenido debe utilizar, a partir de ahora, el servicio para representar el recurso identificado por el cliente; POST es una declaración de qué contenido debe contener el servicio, a partir de ahora, (posiblemente duplicado) pero depende del servidor cómo identificar ese contenido.
PUT x
(si x
identifica un resource ): "Reemplazar el contenido del recurso identificado x
con mi contenido".
PUT x
(si x
no identifica un recurso): "Cree un nuevo recurso que contenga mi contenido y utilícelo x
para identificarlo".
POST x
: "Almacenar mi contenido y darme un identificador que pueda usar para identificar un recurso (antiguo o nuevo) que contenga dicho contenido (posiblemente mezclado con otro contenido). Dicho recurso debe ser idéntico o subordinado al que se x
identifica". " Y ''recurso s está subordinada a x '' recurso s" es típicamente, pero no necesariamente implementado por hacer y una subruta de x (por ejemplo, x = /foo
y y = /foo/bar
) y la modificación de la representación (s) de x recurso ''s para reflejar la existencia de un nuevo recurso, por ejemplo, con un hipervínculo a yEl recurso y algunos metadatos. Solo lo último es realmente esencial para un buen diseño, ya que las URL son opacas en REST: se supone que debe utilizar hipermedia en lugar de la construcción de la URL del lado del cliente para atravesar el servicio de todos modos.
En REST, no existe un recurso que contenga "contenido". Me refiero como "contenido" a los datos que el servicio usa para hacer representaciones de manera consistente. Normalmente consta de algunas filas relacionadas en una base de datos o un archivo (por ejemplo, un archivo de imagen). Depende del servicio convertir el contenido del usuario en algo que el servicio pueda usar, por ejemplo, convertir una carga útil JSON en declaraciones SQL.
Respuesta original (podría ser más fácil de leer) :
PUT /something
(si /something
ya existe): "Toma lo que tengas /something
y reemplázalo con lo que te doy".
PUT /something
(si /something
aún no existe): "Toma lo que te doy y ponlo en /something
".
POST /something
: "Toma lo que te doy y colócalo en el lugar que quieras /something
, siempre y cuando me des su URL cuando hayas terminado".
Respuesta corta:
Regla simple: use POST para crear, use PUT para actualizar.
Respuesta larga:
ENVIAR:
- POST se utiliza para enviar datos al servidor.
- Útil cuando la URL del recurso es desconocida
PONER:
- PUT se utiliza para transferir el estado al servidor
- Útil cuando se conoce la URL de un recurso
Respuesta más larga:
Para entenderlo, debemos preguntarnos por qué se requirió PUT, cuáles fueron los problemas que PUT estaba tratando de resolver que POST no pudo.
Desde el punto de vista de una arquitectura REST no hay nada que importe. Podríamos haber vivido sin PUT también. Pero desde el punto de vista del desarrollador de un cliente, su vida era mucho más sencilla.
Antes de PUT, los clientes no podían saber directamente la URL que generó el servidor o si todo lo que había generado o si los datos que se enviarán al servidor ya están actualizados o no. PUT alivió al desarrollador de todos estos dolores de cabeza. PUT es idempotente, PUT controla las condiciones de carrera y PUT permite al cliente elegir la URL.
Además de las diferencias sugeridas por otros, quiero agregar una más.
En el método POST puedes enviar params de cuerpo enform-data
En el método PUT tienes que enviar params de cuerpo enx-www-form-urlencoded
Encabezamiento Content-Type:application/x-www-form-urlencoded
De acuerdo con esto, no puede enviar archivos o datos de varias partes en el método PUT
EDITAR
El tipo de contenido "application / x-www-form-urlencoded" es ineficaz para enviar grandes cantidades de datos binarios o texto que contiene caracteres no ASCII. El tipo de contenido "multipart / form-data" se debe usar para enviar formularios que contengan archivos, datos que no sean ASCII y datos binarios.
Lo que significa que si tienes que enviar
Archivos, datos no ASCII y datos binarios
debes usar el método POST
Aquí hay una regla simple:
Se debe usar PUT en una URL para actualizar o crear el recurso que se puede ubicar en esa URL.
La POST a una URL debe usarse para actualizar o crear un recurso que se encuentre en otra URL ("subordinada"), o que no se pueda ubicar a través de HTTP.
De una manera muy simple, estoy tomando el ejemplo de la línea de tiempo de Facebook.
Caso 1: cuando publicas algo en tu línea de tiempo, es una nueva entrada nueva. Entonces, en este caso, usan el método POST porque el método POST no es idempotente.
Caso 2: si su amigo comenta en su publicación la primera vez, también se creará una nueva entrada en la base de datos, por lo que se usará el método POST.
Caso 3: Si su amigo edita su comentario, en este caso, tenían un ID de comentario, por lo que actualizarán un comentario existente en lugar de crear una nueva entrada en la base de datos. Por lo tanto, para este tipo de operación use el método PUT porque es idempotente. *
En una sola línea, use POST para agregar una nueva entrada en la base de datos y PUT para actualizar algo en la base de datos.
En breve:
PUT es idempotente, donde el estado del recurso será el mismo si la misma operación se ejecuta una o varias veces.
POST no es idempotente, donde el estado del recurso puede ser diferente si la operación se ejecuta varias veces en comparación con la ejecución una sola vez.
Analogía con consulta de base de datos
PUEDE pensar que es similar a "ACTUALIZAR ESTUDIANTE SET dirección =" abc "donde id =" 123 ";
POSTE Puede pensar en algo como "INSERTAR EN EL ESTUDIANTE (nombre, dirección) VALORES (" abc "," xyzzz ");
La identificación del estudiante se genera automáticamente.
Con PUT, si la misma consulta se ejecuta varias veces o una vez, el estado de la tabla ESTUDIANTE sigue siendo el mismo.
En el caso de POST, si la misma consulta se ejecuta varias veces, se crean múltiples registros de Estudiantes en la base de datos y el estado de la base de datos cambia en cada ejecución de una consulta "INSERTAR".
NOTA: PUT necesita una ubicación de recursos (ya-recurso) en la que debe realizarse la actualización, mientras que POST no requiere eso. Por lo tanto, POST intuitivamente está destinado a la creación de un nuevo recurso, mientras que PUT es necesario para actualizar el recurso ya existente.
Algunos pueden llegar a que las actualizaciones se pueden realizar con POST. No hay una regla estricta sobre cuál usar para las actualizaciones o cuál usar para crear. Nuevamente, estas son convenciones, e intuitivamente me inclino por el razonamiento antes mencionado y lo sigo.
La mayoría de las veces, los usarás así:
- Publicar un recurso en una colección
- PONER un recurso identificado por la colección /: id
Por ejemplo:
- POST / artículos
- PUT / artículos / 1234
En ambos casos, el cuerpo de la solicitud contiene los datos para el recurso que se creará o actualizará. Debería ser obvio a partir de los nombres de ruta que POST no es idempotente (si lo llama 3 veces creará 3 objetos), pero PUT es idempotente (si lo llama 3 veces el resultado es el mismo). PUT se usa a menudo para la operación "upsert" (crear o actualizar), pero siempre puede devolver un error 404 si solo quiere usarlo para modificar.
Tenga en cuenta que POST "crea" un nuevo elemento en la colección y PUT "reemplaza" un elemento en una URL determinada, pero es una práctica muy común usar PUT para modificaciones parciales, es decir, usarlo solo para actualizar los recursos existentes y solo modifique los campos incluidos en el cuerpo (ignorando los otros campos). Esto es técnicamente incorrecto, si quiere ser purista de REST, PUT debería reemplazar todo el recurso y debería usar PATCH para la actualización parcial. Personalmente, no me importa mucho en la medida en que el comportamiento sea claro y coherente en todos los puntos finales de su API.
Recuerde, REST es un conjunto de convenciones y pautas para mantener su API simple. Si terminas con una solución complicada solo para marcar la casilla "RESTfull", estás derrotando el propósito;)
Ruby on Rails 4.0 utilizará el método ''PATCH'' en lugar de PUT para hacer actualizaciones parciales.
RFC 5789 dice acerca de PATCH (desde 1995):
Es necesario un nuevo método para mejorar la interoperabilidad y evitar errores. El método PUT ya está definido para sobrescribir un recurso con un nuevo cuerpo completo y no se puede reutilizar para hacer cambios parciales. De lo contrario, los servidores proxy y los cachés, e incluso los clientes y servidores, pueden confundirse con el resultado de la operación. POST ya está en uso pero sin una amplia interoperabilidad (por un lado, no existe una forma estándar de descubrir el soporte de formato de parche) PATCH se mencionó en las especificaciones HTTP anteriores, pero no se definió completamente.
" Edge Rails: PATCH es el nuevo método HTTP principal para actualizaciones " lo explica.
Se supone que la semántica es diferente, ya que "PUT", como "GET" se supone que es idempotente, lo que significa que puedes hacer la misma solicitud PUT exacta varias veces y el resultado será como si lo ejecutaras solo una vez.
Describiré las convenciones que creo que son las más utilizadas y útiles:
Cuando PONAS un recurso en una URL particular, lo que sucede es que debería guardarse en esa URL, o algo así.
Cuando PUBLICAS a un recurso en una URL particular, a menudo estás publicando una información relacionada a esa URL. Esto implica que el recurso en la URL ya existe.
Por ejemplo, cuando desea crear una nueva transmisión, puede PONERLO a alguna URL. Pero cuando desea POSTAR un mensaje a una transmisión existente, POST a su URL.
En cuanto a la modificación de las propiedades del flujo, puede hacerlo con PUT o POST. Básicamente, solo use "PUT" cuando la operación sea idempotente; de ​​lo contrario, use POST.
Sin embargo, tenga en cuenta que no todos los navegadores modernos admiten verbos HTTP distintos de GET o POST.
Si bien es probable que haya una forma agnóstica de describirlos, parece estar en conflicto con varias afirmaciones de las respuestas a los sitios web.
Seamos muy claros y directos aquí. Si usted es un desarrollador de .NET que trabaja con la API web, los datos son (de la documentación de la API de Microsoft), http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web-api-that-supports-crud-operations :
1. PUT = UPDATE (/api/products/id)
2. MCSD Exams 2014 - UPDATE = PUT, there are **NO** multiple answers for that question period.
Asegúrese de que "puede" usar "POST" para actualizar, pero simplemente siga las convenciones establecidas para usted con su marco dado. En mi caso, es .NET / Web API, por lo que PUT es para ACTUALIZAR que no hay debate.
Espero que esto ayude a cualquier desarrollador de Microsoft que lea todos los comentarios con enlaces a sitios web de Amazon y Sun / Java.
Si está familiarizado con las operaciones de base de datos, hay
- Seleccionar
- Insertar
- Actualizar
- Borrar
- Fusionar (Actualizar si ya existe, si no insertar)
Yo uso PUT
para Combinar y actualizar operaciones similares y uso POST
para Inserciones.
Voy a aterrizar con lo siguiente:
PUT se refiere a un recurso, identificado por el URI. En este caso, lo estás actualizando. Es la parte de los tres verbos que se refieren a los recursos: eliminar y obtener los otros dos.
POST es básicamente un mensaje de formato libre, cuyo significado se define como "fuera de banda". Si el mensaje puede interpretarse como agregar un recurso a un directorio, eso estaría bien, pero básicamente necesita entender el mensaje que está enviando (publicando) para saber qué ocurrirá con el recurso.
Debido a que PUT, GET y DELETE se refieren a un recurso, también son, por definición, idempotent.
POST puede realizar las otras tres funciones, pero luego la semántica de la solicitud se perderá en los intermediarios, como cachés y proxies. Esto también se aplica a proporcionar seguridad en el recurso, ya que el URI de una publicación no necesariamente indica el recurso al que se aplica (aunque puede).
Un PUT no necesita ser un creador; el servicio podría generar un error si el recurso aún no se ha creado, pero de lo contrario, actualícelo. O viceversa: puede crear el recurso, pero no permitir actualizaciones. Lo único que se requiere sobre PUT es que apunta a un recurso específico, y su carga útil es la representación de ese recurso. Un PUT exitoso significa (salvo interferencia) que un GET recuperaría el mismo recurso.
Edición: una cosa más: un PUT puede crear, pero si lo hace, entonces la ID debe ser una ID natural, también una dirección de correo electrónico. De esa manera, cuando PONAS dos veces, la segunda opción es una actualización de la primera. Esto lo hace idempotente .
Si se genera la ID (una nueva ID de empleado, por ejemplo), entonces el segundo PUT con la misma URL crearía un nuevo registro, que viola la regla idempotent. En este caso, el verbo sería POST y el mensaje (no el recurso) sería crear un recurso utilizando los valores definidos en este mensaje.
A riesgo de repetir lo que ya se ha dicho, parece importante recordar que PUT implica que el cliente controla lo que la URL va a terminar siendo, al crear un recurso. Por lo tanto, parte de la elección entre PUT y POST será sobre cuánto puede confiar en el cliente para que proporcione una URL correcta y normalizada que sea coherente con el esquema de URL.
Cuando no puede confiar completamente en que el cliente haga lo correcto, sería más apropiado usar POST para crear un nuevo elemento y luego enviar la URL al cliente en la respuesta.
En la práctica, POST funciona bien para crear recursos. La URL del recurso recién creado debe devolverse en el encabezado de respuesta de Ubicación. PUT debe utilizarse para actualizar un recurso completamente. Por favor, comprenda que estas son las mejores prácticas al diseñar una API RESTful. La especificación HTTP como tal no restringe el uso de PUT / POST con algunas restricciones para crear / actualizar recursos. Eche un vistazo a http://techoctave.com/c7/posts/71-twitter-rest-api-dissected que resume las mejores prácticas.
La consideración más importante es la fiabilidad . Si un mensaje POST se pierde, el estado del sistema no está definido. La recuperación automática es imposible. Para los mensajes PUT, el estado es indefinido solo hasta el primer reintento exitoso.
Por ejemplo, puede que no sea una buena idea crear transacciones de tarjetas de crédito con POST.
Si tiene URI generados automáticamente en su recurso, aún puede usar PUT pasando un URI generado (que apunta a un recurso vacío) al cliente.
Algunas otras consideraciones:
- POST invalida las copias en caché de todo el recurso que contiene (mejor consistencia)
- Las respuestas PUT no se pueden almacenar en caché mientras que las POST son (Requerir ubicación de contenido y caducidad)
- PUT es menos compatible con, por ejemplo, Java ME, navegadores más antiguos, cortafuegos
Los lectores nuevos en este tema se sorprenderán con la discusión interminable sobre lo que debe hacer y la relativa ausencia de lecciones de la experiencia. El hecho de que REST sea "preferido" sobre SOAP es, supongo, un aprendizaje de alto nivel a partir de la experiencia, pero ¿hay que progresar desde allí? Es 2016. La disertación de Roy fue en 2000. ¿Qué hemos desarrollado? ¿Fue divertido? ¿Fue fácil de integrar? ¿Apoyar? ¿Manejará el auge de los teléfonos inteligentes y las conexiones móviles inestables?
Según ME, las redes de la vida real no son confiables. Solicita tiempo de espera. Se restablecen las conexiones. Las redes se caen durante horas o días a la vez. Los trenes entran en túneles con usuarios móviles a bordo. Para cualquier solicitud dada (como se reconoce ocasionalmente en toda esta discusión) la solicitud puede caer en el agua en su camino, o la respuesta puede caer en el agua en su camino de regreso. En estas condiciones, emitir solicitudes PUT, POST y DELETE directamente contra recursos sustanciales siempre me ha parecido un poco brutal e ingenuo.
HTTP no hace nada para garantizar la finalización confiable de la solicitud-respuesta, y eso está bien porque este es el trabajo adecuado de las aplicaciones conscientes de la red. Al desarrollar una aplicación de este tipo, puede saltar a través de aros para usar PUT en lugar de POST, y luego más aros para dar un cierto tipo de error en el servidor si detecta solicitudes duplicadas. De vuelta en el cliente, entonces tienes que saltar a través de aros para interpretar estos errores, volver a obtener, revalidar y volver a publicar.
O puede hacer esto : considere sus solicitudes inseguras como recursos efímeros de un solo usuario (llamémosles acciones). Los clientes solicitan una nueva "acción" en un recurso sustantivo con un POST vacío para el recurso. POST será utilizado sólo para esto. Una vez que está seguro de poseer el URI de la acción recién acuñada, el cliente PONE la solicitud insegura al URI de acción, no al recurso objetivo . Resolver la acción y actualizar el recurso "real" es un trabajo adecuado de su API, y aquí se desacopla de la red no confiable.
El servidor hace el negocio, devuelve la respuesta y la almacena contra el URI de acción acordado . Si algo sale mal, el cliente repite la solicitud (¡comportamiento natural!), Y si el servidor ya la ha visto, repite la respuesta almacenada y no hace nada más .
Rápidamente notará la similitud con las promesas: creamos y devolvemos el marcador de posición para el resultado antes de hacer nada. También como una promesa, una acción puede tener éxito o fallar una vez, pero su resultado se puede recuperar repetidamente.
Lo mejor de todo es que damos a las aplicaciones de envío y recepción la oportunidad de vincular la acción identificada de manera única con la singularidad en sus respectivos entornos. Y podemos comenzar a exigir y aplicar el comportamiento responsable de los clientes: repita sus solicitudes todo lo que desee, pero no genere una nueva acción hasta que esté en posesión de un resultado definitivo del existente.
Como tal, numerosos problemas espinosos desaparecen. Las solicitudes de inserción repetidas no crearán duplicados, y no creamos el recurso real hasta que estemos en posesión de los datos. (Las columnas de la base de datos pueden permanecer sin nula). Las solicitudes de actualización repetidas no alcanzarán estados incompatibles y no sobrescribirán los cambios posteriores. Los clientes pueden (re) buscar y procesar sin problemas la confirmación original por cualquier motivo (el cliente se bloqueó, la respuesta se perdió, etc.).
Las solicitudes de eliminación sucesivas pueden ver y procesar la confirmación original, sin llegar a un error 404. Si las cosas tardan más de lo esperado, podemos responder provisionalmente y tenemos un lugar donde el cliente puede verificar el resultado definitivo. La mejor parte de este patrón es su propiedad de Kung-Fu (Panda). Tomamos una debilidad, la propensión a que los clientes repitan una solicitud cada vez que no entienden la respuesta y la convierten en una fortaleza :-)
Antes de decirme que esto no es REST, considere las numerosas formas en que se respetan los principios REST. Los clientes no construyen URL. La API permanece visible, aunque con un pequeño cambio en la semántica. Los verbos HTTP se usan apropiadamente. Si crees que este es un gran cambio para implementar, te puedo decir por experiencia que no lo es.
Si cree que tendrá grandes cantidades de datos para almacenar, hablemos de volúmenes: una confirmación de actualización típica es una fracción de un kilobyte. HTTP actualmente te da un minuto o dos para responder definitivamente. Incluso si solo almacena acciones durante una semana, los clientes tienen muchas posibilidades de ponerse al día. Si tiene volúmenes muy altos, es posible que desee un almacén de valores clave dedicado que cumpla con los requisitos de ácido, o una solución en memoria.
Me gusta este consejo, de la definición de PUT de RFC 2616 :
La diferencia fundamental entre las solicitudes POST y PUT se refleja en el significado diferente de la solicitud-URI. El URI en una solicitud POST identifica el recurso que manejará la entidad adjunta. Ese recurso podría ser un proceso de aceptación de datos, una puerta de enlace a algún otro protocolo o una entidad separada que acepte anotaciones. En contraste, el URI en una solicitud PUT identifica la entidad incluida en la solicitud: el agente de usuario sabe a qué se destina el URI y el servidor NO DEBE intentar aplicar la solicitud a algún otro recurso.
Esto concuerda con el otro consejo aquí, que PUT se aplica mejor a los recursos que ya tienen un nombre, y POST es bueno para crear un nuevo objeto bajo un recurso existente (y dejar que el servidor lo nombre).
Interpreto esto, y los requisitos de idempotencia en PUT, para significar que:
- POST es bueno para crear nuevos objetos en una colección (y crear no tiene que ser idempotente)
- PUT es bueno para actualizar objetos existentes (y la actualización debe ser idempotente)
- POST también se puede usar para actualizaciones no idempotentes a objetos existentes (especialmente, cambiar parte de un objeto sin especificarlo todo; si lo piensa, crear un nuevo miembro de una colección es realmente un caso especial de este tipo Actualización, desde la perspectiva de la colección.
- PUT también se puede usar para crear si y solo si permite que el cliente asigne un nombre al recurso. Pero como se supone que los clientes REST no deben hacer suposiciones sobre la estructura de la URL, esto está menos relacionado con el espíritu de las cosas.
POST es como publicar una carta en un buzón o publicar un correo electrónico en una cola de correo electrónico. PUT es como cuando pones un objeto en un agujero de cubículo o un lugar en un estante (tiene una dirección conocida).
Con POST, estás publicando en la dirección de QUEUE o COLLECTION. Con PUT, estás poniendo a la dirección del ARTÍCULO.
PUT es idempotente. Puede enviar la solicitud 100 veces y no importará. POST no es idempotente. Si envía la solicitud 100 veces, recibirá 100 correos electrónicos o 100 cartas en su casilla postal.
Una regla general: si conoce el ID o el nombre del elemento, use PUT. Si desea que la parte receptora asigne el ID o el nombre del elemento, utilice POST.
Parece que siempre hay cierta confusión sobre cuándo usar HTTP POST en comparación con el método HTTP PUT para los servicios REST. La mayoría de los desarrolladores intentarán asociar las operaciones CRUD directamente a los métodos HTTP. Argumentaré que esto no es correcto y uno no puede simplemente asociar los conceptos de CRUD a los métodos HTTP. Es decir:
Create => HTTP PUT
Retrieve => HTTP GET
Update => HTTP POST
Delete => HTTP DELETE
Es cierto que R (etrieve) y D (elete) de las operaciones CRUD se pueden asignar directamente a los métodos HTTP GET y DELETE, respectivamente. Sin embargo, la confusión radica en las operaciones C (reate) y U (actualización). En algunos casos, se puede usar el PUT para crear, mientras que en otros casos se requerirá un POST. La ambigüedad radica en la definición de un método HTTP PUT frente a un método HTTP POST.
De acuerdo con las especificaciones HTTP 1.1, los métodos GET, HEAD, DELETE y PUT deben ser idempotentes, y el método POST no es idempotente. Es decir, una operación es idempotente si se puede realizar en un recurso una o varias veces y siempre devuelve el mismo estado de ese recurso. Mientras que una operación no idempotente puede devolver un estado modificado del recurso de una solicitud a otra. Por lo tanto, en una operación no idempotente, no hay garantía de que uno reciba el mismo estado de un recurso.
Según la definición de idempotente anterior, mi opinión sobre el uso del método HTTP PUT frente al método HTTP POST para los servicios REST es: Utilice el método HTTP PUT cuando:
The client includes all aspect of the resource including the unique identifier to uniquely identify the resource. Example: creating a new employee.
The client provides all the information for a resource to be able to modify that resource.This implies that the server side does not update any aspect of the resource (such as an update date).
En ambos casos, estas operaciones se pueden realizar varias veces con los mismos resultados. Es decir, el recurso no se modificará solicitando la operación más de una vez. Por lo tanto, una verdadera operación idempotente. Utilice el método HTTP POST cuando:
The server will provide some information concerning the newly created resource. For example, take a logging system. A new entry in the log will most likely have a numbering scheme which is determined on the server side. Upon creating a new log entry, the new sequence number will be determined by the server and not by the client.
On a modification of a resource, the server will provide such information as a resource state or an update date. Again in this case not all information was provided by the client and the resource will be changing from one modification request to the next. Hence a non idempotent operation.
Conclusión
No correlacione ni asigne directamente las operaciones CRUD a los métodos HTTP para los servicios REST. El uso de un método HTTP PUT en lugar de un método HTTP POST debe basarse en el aspecto idempotente de esa operación. Es decir, si la operación es idempotente, entonces use el método HTTP PUT. Si la operación no es idempotente, use el método HTTP POST.
- POST a una URL crea un recurso secundario en una URL definida por el servidor .
- Poner en una URL crea / reemplaza el recurso en su totalidad en la URL definida por el cliente .
- PATCH a una URL actualiza parte del recurso en esa URL definida por el cliente.
La especificación relevante para PUT y POST es RFC 2616 §9.5ff.
POST crea un recurso secundario , por lo que POST to /items
crea un recurso que vive en el recurso /items
. P.ej. /items/1
. Enviar el mismo paquete posterior dos veces creará dos recursos.
PUT es para crear o reemplazar un recurso en una URL conocida por el cliente .
Por lo tanto: PUT es solo un candidato para CREAR donde el cliente ya conoce la url antes de que se cree el recurso. P.ej. /blogs/nigel/entry/when_to_use_post_vs_put
ya que el título se usa como clave de recursos
PUT reemplaza el recurso en la url conocida si ya existe, por lo que enviar la misma solicitud dos veces no tiene ningún efecto. En otras palabras, las llamadas a PUT son idempotentes .
El RFC se lee así:
La diferencia fundamental entre las solicitudes POST y PUT se refleja en el significado diferente de la solicitud-URI. El URI en una solicitud POST identifica el recurso que manejará la entidad adjunta. Ese recurso podría ser un proceso de aceptación de datos, una puerta de enlace a algún otro protocolo o una entidad separada que acepte anotaciones. En contraste, el URI en una solicitud PUT identifica la entidad incluida en la solicitud: el agente de usuario sabe a qué se destina el URI y el servidor NO DEBE intentar aplicar la solicitud a algún otro recurso. Si el servidor desea que la solicitud se aplique a un URI diferente,
Nota: PUT se ha utilizado principalmente para actualizar recursos (reemplazándolos en su totalidad), pero recientemente se está avanzando hacia el uso de PATCH para actualizar recursos existentes, ya que PUT especifica que reemplaza a todo el recurso. RFC 5789.