Estoy construyendo un servidor que permite a los clientes almacenar objetos. Esos objetos están completamente construidos en el lado del cliente, completos con ID de objetos que son permanentes durante toda la vida útil del objeto.
He definido la API para que los clientes puedan crear o modificar objetos usando PUT:
PUT /objects/{id} HTTP/1.1
...
{json representation of the object}
El {id} es el ID del objeto, por lo que forma parte del URI de solicitud.
Ahora, también estoy considerando permitir que los clientes creen el objeto usando POST:
POST /objects/ HTTP/1.1
...
{json representation of the object, including ID}
Dado que POST se entiende como operación "agregar", no estoy seguro de qué hacer en caso de que el objeto ya esté allí. ¿Debo tratar la solicitud como una solicitud de modificación o debo devolver algún código de error (que)?
Respuestas:
Mi sentimiento es
409 Conflict
el más apropiado, sin embargo, rara vez se ve en la naturaleza, por supuesto:fuente
HTTP 409
con unLocation
encabezado apuntando al recurso existente / conflictivo.De acuerdo con RFC 7231 , un 303 Ver otro PUEDE usarse si el resultado del procesamiento de un POST sería equivalente a una representación de un recurso existente .
fuente
Personalmente voy con la extensión WebDAV
422 Unprocessable Entity
.De acuerdo con RFC 4918
fuente
422
que me parece extraño ...Se trata de contexto , y también de quién es responsable de manejar los duplicados en las solicitudes (servidor o cliente o ambos)
Si el servidor solo apunta el duplicado , mire 4xx:
Para el manejo implícito de duplicados, mire 2XX:
Si se espera que el servidor devuelva algo , mire 3XX:
cuando el servidor puede apuntar el recurso existente, implica una redirección.
Si lo anterior no es suficiente, siempre es una buena práctica preparar algún mensaje de error en el cuerpo de la respuesta.
fuente
Tal vez tarde en el juego, pero me topé con este problema de semántica al intentar hacer una API REST.
Para ampliar un poco la respuesta de Wrikken, creo que podría usar cualquiera
409 Conflict
o403 Forbidden
dependiendo de la situación; en resumen, use un error 403 cuando el usuario no puede hacer absolutamente nada para resolver el conflicto y completar la solicitud (por ejemplo, no puede enviar unDELETE
solicitud para eliminar explícitamente el recurso), o use 409 si algo podría hacerse.Hoy en día, alguien dice "403" y me viene a la mente un problema de permisos o autenticación, pero la especificación dice que es básicamente el servidor que le dice al cliente que no lo va a hacer, no lo pregunte nuevamente, y esta es la razón por la cual el cliente no debería 't.
En cuanto a
PUT
vs.POST
...POST
debe usarse para crear una nueva instancia de un recurso cuando el usuario no tiene medios para o no debe crear un identificador para el recurso.PUT
se usa cuando se conoce la identidad del recurso.fuente
POST
solicitud (cuando se usa correctamente), ya que establece que debería devolverse cuando entra en conflicto con el recurso de destino . Como el recurso de destino aún no se ha publicado, no puede entrar en conflicto y, por lo tanto, responder409 Conflict
no tiene ningún sentido.POST
, de hecho, inferiría lo contrario porque "Es más probable que ocurran conflictos en respuesta a una solicitud PUT". parece indicar que otros métodos de solicitud también pueden usar este código. Además, "El cuerpo de respuesta debe incluir suficiente información para que el usuario reconozca la fuente del conflicto. Idealmente, la entidad de respuesta debería incluir suficiente información para que el usuario o agente de usuario solucione el problema; sin embargo, eso podría no ser posible y es no requerido ". ( webdav.org/specs/rfc2616.html#status.409 )"302 encontrado" me parece lógico. Y el RFC 2616 dice que PUEDE ser respondido para otras solicitudes que no sean GET y HEAD (y esto seguramente incluye POST)
Pero aún mantiene al visitante yendo a esta URL para obtener este recurso "Encontrado", por el RFC. Para que vaya directamente a la URL "Encontrada" real, se debe usar "303 Ver otra", lo cual tiene sentido, pero obliga a otra llamada a OBTENER la siguiente URL. En el lado bueno, este GET es almacenable en caché.
Creo que usaría "303 See Other" . No sé si puedo responder con la "cosa" que se encuentra en el cuerpo, pero me gustaría hacerlo para guardar un viaje de ida y vuelta al servidor.
ACTUALIZACIÓN: Después de volver a leer el RFC, sigo pensando que un código inexistente "4XX + 303 encontrado" debería ser el correcto. Sin embargo, el "Conflicto 409" es el mejor código de respuesta existente (como lo señaló @Wrikken), tal vez incluyendo un encabezado de ubicación que apunta al recurso existente.
fuente
No creo que debas hacer esto.
La POST es, como saben, para modificar la colección y se usa para CREAR un nuevo elemento. Entonces, si envía la identificación (creo que no es una buena idea), debe modificar la colección, es decir, modificar el elemento, pero es confuso.
Úselo para agregar un elemento, sin identificación. Es la mejor práctica.
Si desea capturar una restricción ÚNICA (no la identificación), puede responder 409, como puede hacer en las solicitudes PUT. Pero no la identificación.
fuente
Iría con
422 Unprocessable Entity
, que se usa cuando una solicitud no es válida pero el problema no está en la sintaxis o la autenticación.Como argumento en contra de otras respuestas, usar cualquier
4xx
código sin error implicaría que no es un error del cliente, y obviamente lo es. Usar un4xx
código sin error para representar un error del cliente simplemente no tiene ningún sentido.Parece que esa
409 Conflict
es la respuesta más común aquí, pero, de acuerdo con la especificación, eso implica que el recurso ya existe y los nuevos datos que está aplicando son incompatibles con su estado actual. Si está enviando unPOST
solicite, por ejemplo, un nombre de usuario que ya está en uso, no está en conflicto con el recurso de destino, ya que el recurso de destino (el recurso que está intentando crear) aún no se ha publicado. Es un error específicamente para el control de versiones, cuando hay un conflicto entre la versión del recurso almacenado y la versión del recurso solicitado. Es muy útil para ese propósito, por ejemplo, cuando el cliente ha almacenado en caché una versión anterior del recurso y envía una solicitud basada en esa versión incorrecta que ya no sería condicionalmente válida. "En este caso, la representación de la respuesta probablemente contendría información útil para fusionar las diferencias en función del historial de revisiones". La solicitud de crear otro usuario con ese nombre de usuario simplemente no se puede procesar, ya que no tiene nada que ver con el control de versiones.Para el registro, 422 también es el código de estado que GitHub usa cuando intenta crear un repositorio con un nombre que ya está en uso.
fuente
Creo que para REST, solo tiene que tomar una decisión sobre el comportamiento de ese sistema en particular, en cuyo caso, creo que la respuesta "correcta" sería una de las dos respuestas que se dan aquí. Si desea que la solicitud se detenga y se comporte como si el cliente cometiera un error que necesita corregir antes de continuar, utilice 409. Si el conflicto realmente no es tan importante y desea mantener la solicitud en marcha, responda redirigiendo el cliente a la entidad que se encontró. Creo que las API REST adecuadas deberían redirigirse (o al menos proporcionar el encabezado de ubicación) al punto final GET para ese recurso después de una POST de todos modos, por lo que este comportamiento daría una experiencia consistente.
EDITAR: También vale la pena señalar que debe considerar un PUT ya que está proporcionando la identificación. Entonces el comportamiento es simple: "No me importa lo que hay ahora, pon esto aquí". Es decir, si no hay nada allí, se creará; Si hay algo allí, será reemplazado. Creo que una POST es más apropiada cuando el servidor gestiona esa ID. La separación de los dos conceptos básicamente le dice cómo tratarlo (es decir, PUT es idempotente, por lo que siempre debería funcionar siempre que la carga útil se valide, POST siempre crea, por lo que si hay una colisión de ID, entonces un 409 describiría ese conflicto) .
fuente
POST
solicitud (cuando se usa correctamente), ya que establece que debería devolverse cuando entra en conflicto con el recurso de destino . Como el recurso de destino aún no se ha publicado, no puede entrar en conflicto y, por lo tanto, responder409 Conflict
no tiene ningún sentido.PUT
embargo, me gusta su sugerencia de usar .Otro posible tratamiento es usar PATCH después de todo. Un PATCH se define como algo que cambia el estado interno y no se limita a agregar.
PATCH resolvería el problema permitiéndole actualizar elementos ya existentes. Ver: RFC 5789: PARCHE
fuente
¿Por qué no un 202 aceptado ? Es una solicitud correcta (200s), no hubo errores del cliente (400s), per se.
De 10 definiciones de código de estado :
... porque no necesitaba completarse, porque ya existía. El cliente no sabe que ya existía, no hicieron nada malo.
Me estoy inclinando por lanzar un 202 y devolver contenido similar al que
/{resource}/{id}
habría obtenido un GET .fuente
Tropecé con esta pregunta mientras buscaba el código correcto para el registro duplicado.
Disculpe mi ignorancia pero no entiendo por qué todos ignoran el código "300" que claramente dice "opción múltiple" o "Ambiguo"
En mi opinión, este sería el código perfecto para construir un sistema no estándar o particular para su propio uso. ¡También podría estar equivocado!
https://tools.ietf.org/html/rfc7231#section-6.4.1
fuente
Es más probable que sea
400 Bad Request
Como la solicitud contiene un valor duplicado (valor que ya existe), se puede percibir como un error del cliente. Necesita cambiar la solicitud antes del próximo intento.
Al considerar estos hechos, podemos concluir como HTTP STATUS 400 Bad Request.
fuente
¿Qué pasa con 208 - http://httpstatusdogs.com/208-already-reported ? ¿Es esa una opción?
En mi opinión, si lo único es un recurso repetido, no se debe generar ningún error. Después de todo, no hay error ni en el lado del cliente o del servidor.
fuente
En tu caso puedes usar
409 Conflict
Y si desea consultar otros
HTTPs
códigos de estado de la lista a continuación1 × aislado informativo
2 × aislado éxito
Redirección de 3 ×
Error de cliente 4 ×font>
5 × error del servidor
fuente