pagina - http/1.1 200 ok
Código de respuesta HTTP para POST cuando el recurso ya existe (15)
Estoy construyendo un servidor que permite a los clientes almacenar objetos. Esos objetos están totalmente construidos en el lado del cliente, completos con ID de objeto que son permanentes durante toda la vida 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 la solicitud.
Ahora, también estoy considerando permitir que los clientes creen el objeto utilizando POST:
POST /objects/ HTTP/1.1
...
{json representation of the object, including ID}
Dado que POST se entiende como una operación "anexar", 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 (cuál)?
"302 Found" suena lógico para mí. Y el RFC 2616 dice que PUEDE ser respondido por otras solicitudes que no sean GET y HEAD (y esto seguramente incluye POST)
Pero todavía mantiene al visitante yendo a esta URL para obtener este recurso "Encontrado", por el RFC. Para hacer que vaya directamente a la URL "Encontrada" real, uno debe estar usando "303 Ver Otro", lo cual tiene sentido, pero obliga a otra llamada a obtener su siguiente URL. En el lado bueno, este GET es cacheable.
Creo que usaría "303 Ver Otros" . 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, todavía creo 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 señala @ Wrikken), tal vez incluyendo un encabezado de Ubicación que apunta al recurso existente.
¿Por qué no un 202 Aceptado ? Es una solicitud OK (200s), no hubo errores de cliente (400s) per se.
De 10 Definiciones de Código de Estado :
"202 Aceptado. La solicitud se ha aceptado para su procesamiento, pero el proceso no se ha completado".
... porque no necesitaba ser completado, porque ya existía. El cliente no sabe que ya existía, no hicieron nada malo.
Me estoy inclinando en lanzar un 202 y devolver un contenido similar a lo que habría devuelto un GET /{resource}/{id}
.
¿Qué hay de 208 - http://httpstatusdogs.com/208-already-reported ? ¿Es esa una opción?
En mi opinión, si lo único es un recurso de repetición, no se debe generar ningún error. Después de todo, no hay error ni en el lado del cliente o del servidor.
¿Qué hay de devolver un 418?
Debido a que el cliente pide que persista una entidad que ya existe en el servidor, el servidor finalmente se enoja y piensa que es una tetera y regresa: 418 I''m a teapot
.
Referencias:
- RFC 2324
- Uso practico
- Blog explicando el código.
- Que pregunta
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, use el 409. Si el conflicto realmente no es tan importante y desea continuar con la solicitud, responda redireccionando el Cliente a la entidad que fue encontrada. Creo que las API de REST correctas deberían estar redirigiendo (o al menos proporcionando el encabezado de ubicación) al punto final GET para ese recurso después de una POST, por lo que este comportamiento proporcionaría una experiencia consistente.
EDITAR: también vale la pena señalar que debe considerar un PUT ya que está proporcionando la ID. Entonces el comportamiento es simple: "No me importa lo que esté ahí ahora, pon esto ahí". Es decir, si no hay nada allí, será creado; Si hay algo ahí será reemplazado. Creo que un POST es más apropiado cuando el servidor administra esa ID. Básicamente, separar los dos conceptos le indica cómo lidiar con ellos (es decir, PUT es idempotente por lo que siempre debería funcionar siempre que la carga útil se valide, la POST siempre se crea, por lo que si hay una colisión de ID, un 409 describiría ese conflicto) .
De acuerdo con RFC 7231 , se puede usar un 303 Ver Otros si el resultado de procesar un POST sería equivalente a una representación de un recurso existente .
Iría con la 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 código de error que no sea 4xx
implicaría que no es un error del cliente, y obviamente lo es. Usar un código de error que no sea 4xx
para representar un error del cliente simplemente no tiene ningún sentido.
Parece que 409 Conflict
es la respuesta más común aquí, pero, según la especificación, eso implica que el recurso ya existe y que los nuevos datos que está aplicando son incompatibles con su estado actual. Si está enviando una solicitud POST
, con, por ejemplo, un nombre de usuario que ya se ha tomado, no está realmente en conflicto con el recurso de destino, ya que el recurso de destino aún no se ha publicado. Es un error específicamente para el control de versiones, cuando existe 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 según el historial de revisiones". La solicitud para crear otro usuario con ese nombre de usuario es simplemente no procesable, y no tiene nada que ver con el control de versiones.
Para el registro, 422 también es el código de estado que usa GitHub cuando intenta crear un repositorio con un nombre que ya está en uso.
Más probable es que es 400 Bad Request
6.5.1. 400 Petición Incorrecta
El código de estado 400 (Solicitud errónea) indica que el servidor no puede o no procesará la solicitud debido a algo que se percibe como un error del cliente (por ejemplo, sintaxis de solicitud mal formada, trama de mensajes de solicitud no válida o enrutamiento de solicitud engañosa).
Como la solicitud contiene un valor duplicado (valor que ya existe), puede percibirse como un error del cliente. Necesitas cambiar la solicitud antes del siguiente intento.
Al considerar estos hechos, podemos concluir como HTTP STATUS 400 Bad Request.
Me topé con esta pregunta mientras buscaba el código correcto para un registro duplicado.
Perdone mi ignorancia, pero no entiendo por qué todo el mundo ignora el código "300" que dice claramente "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 un sistema particular para su propio uso. ¡Podría estar equivocado también!
Mi sentimiento es 409 Conflict
es el más apropiado, sin embargo, rara vez se ve en la naturaleza por supuesto:
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 la respuesta DEBERÍA incluir suficiente información para que el usuario reconozca el origen 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.
No creo que debas hacer esto.
El POST es, como usted sabe, modificar la colección y se utiliza para CREAR un nuevo elemento. Por lo tanto, si envía el ID (creo que no es una buena idea), debe modificar la colección, es decir, modificar el elemento, pero es confuso.
Úsalo para agregar un artículo, sin identificación. Es la mejor práctica.
Si desea capturar una restricción ÚNICA (no la ID), puede responder 409, como puede hacer en las solicitudes PUT. Pero no la identificación.
Otro tratamiento potencial es usar PATCH después de todo. Un PARCHE se define como algo que cambia el estado interno y no se limita a adjuntar.
PATCH resolvería el problema permitiéndole actualizar elementos ya existentes. Ver: RFC 5789: PARCHE
Personalmente voy con la extensión WebDAV 422 Unprocessable Entity
.
Los patrones REST lo describen como
El código de estado de la
422 Unprocessable Entity
significa que el servidor entiende el tipo de contenido de la entidad de solicitud (por lo tanto, un código de estado de415 Unsupported Media Type
es inapropiado) y la sintaxis de la entidad de solicitud es correcta (por lo tanto, un código de estado de400 Bad Request
es inapropiado) pero no pudo procesar las instrucciones contenidas.
Se trata de contexto , y también de quién es responsable de tener duplicados (servidor o cliente o ambos)
Si el servidor solo apunta el duplicado , mira 4xx:
- 400 Solicitud incorrecta: cuando el servidor no procesará la solicitud porque es un error obvio del cliente
- 409 Conflicto: si el servidor no procesará la solicitud, pero la razón no es culpa del cliente
Para el manejo implícito de duplicados, mire 2XX:
- 200 ok
- 201 creado
Si se espera que el servidor devuelva algo , mire 3XX:
- 302 encontrados
- 303 Ver otros
Cuando el servidor es capaz de señalar 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.
Tal vez tarde en el juego, pero me topé con este problema semántico al intentar hacer una API REST.
Para ampliar un poco la respuesta de Wrikken, creo que podría usar 409 Conflict
o 403 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, puede No envíe una solicitud DELETE
para eliminar explícitamente el recurso), o use 409 si es posible que se pueda hacer algo.
10.4.4 403 Prohibido
El servidor entendió la solicitud, pero se niega a cumplirla. La autorización no ayudará y la solicitud NO DEBE repetirse. Si el método de solicitud no era HEAD y el servidor desea hacer público el motivo por el cual la solicitud no se ha cumplido, DEBE describir el motivo de la denegación en la entidad. Si el servidor no desea que esta información esté disponible para el cliente, se puede usar el código de estado 404 (No encontrado) en su lugar.
Hoy en día, alguien dice "403" y un tema de permisos o autenticación viene a la mente, pero la especificación dice que básicamente es el servidor que le dice al cliente que no lo va a hacer, no lo vuelva a preguntar, y he aquí por qué el cliente no debería hacerlo. ''t
En cuanto a PUT
vs. POST
... POST
debe usar para crear una nueva instancia de un recurso cuando el usuario no tiene medios para crear un identificador para el recurso. PUT
se utiliza cuando se conoce la identidad del recurso.
9.6 PONER
...
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,
DEBE enviar una respuesta 301 (Movida permanentemente); El agente de usuario PUEDE entonces tomar su propia decisión sobre si redirigir o no la solicitud.