Imagine una API para identificar si una persona ha seleccionado su animal espiritual. Solo pueden tener cero o un espíritu animal.
Actualmente:
/person/{id}/selectedSpiritAnimal
cuando han seleccionado un animal devuelve http 200 y {selectedAnimal:mole}
pero cuando no tienen selección, devuelve http 404.
Esto hace que mi espíritu animal sea infeliz ya que estamos representando un problema de dominio válido, ya que aún no hemos seleccionado un espíritu animal, como un error HTTP.
Además, como empresa, erm Sprit-Animal-Hampers-R-us, queremos saber cuándo alguien no tiene una selección para poder avisarle.
¿Cuál es una mejor respuesta aquí:
HTTP 200 y {selectedAnimal:null}
o incluso más explícito
HTTP 200 y {selectedAnimal:null, spiritAnimalSelected: false}
¿O es mejor devolver un 404? Dado que al igual que this image has not yet been uploaded
al ver una imagen en línea, sería un 404. this person has not selected a spirit animal
podría ser un 404
Esta pregunta se ha propuesto como un duplicado, pero esa pregunta aborda una URL válida que se solicita cuando la aplicación se ha configurado para no permitir el cambio que representa la URL.
Mientras que aquí estoy viendo cómo uno representa un recurso donde la ausencia del recurso es significativa. Es decir, es válido que el cliente solicite la URL y la respuesta es que ha solicitado con éxito el recurso que representa la ausencia de una cosa.
Entonces, esto no es 'lógica de negocios', sino más bien una circunstancia en la que la ausencia de una cosa tiene sentido (puede ser que muchos de mis colegas estén argumentando que 404 todavía es correcto) pero no estoy seguro de cómo asignar eso al Especificaciones.
Muy difícil elegir una respuesta. He cambiado de opinión varias veces sobre la conversación aquí y la que está en curso en el trabajo.
Lo que me soluciona aquí es que la especificación dice que un 4xx es cuando el cliente ha cometido un error . En este caso, se le ha dicho al cliente que espere una respuesta de la url seleccionada de SpiritAnimal, por lo que no se ha equivocado.
El consenso entre mis colegas es que este es un síntoma de un mal diseño de API
Probablemente sería mejor que simplemente solicitemos / person / {id} y eso devuelva un conjunto de relaciones de enlace para la persona ... entonces, si no recibe el enlace / selectedSpiritAnimal (cuando una persona no tiene selección) pero usted llamarlo de todos modos, entonces un 404 tiene sentido. O que implemente respuestas parciales y deje que / person / {id} devuelva un documento más completo a menos que el cliente solicite un subconjunto de datos
Respuestas:
Los códigos HTTP 4xx probablemente no sean la opción correcta para este escenario. Usted declara que tener cero animales espirituales es un estado válido, y la ruta API
person/{id}/selectedSpiritAnimal
tendrá en cuenta si la personaid
tiene o no uno.Las respuestas HTTP 4xx están reservadas para la situación en la que un cliente ha hecho algo incorrecto en la solicitud (consulte el archivo de w3 de la especificación original ). Pero el cliente está haciendo una solicitud válida, ya sea que la persona
id
tenga o no un animal espiritual.Entonces me inclino hacia las segundas soluciones usando un cuerpo JSON formateado correctamente en la respuesta y un código HTTP 2xx.
Ahora, si recibe una solicitud de este tipo y resulta que la persona
id
no existe, un código 4xx tiene más sentido.fuente
cases in which the client seems to have erred
, pero por el otro, el 404 dice directamenteThe server has not found anything matching the Request-URI
. Podría considerar solicitar algo que no exista un error del cliente. Entiendo que la persona no existe frente a un subproceso no existente, pero eso podría indicarse como el mensaje de respuesta. 204 también parece relevante, ya que la entidad existe, pero no tiene contenido para una subpropiedad.Déjame presentarte el modelo de madurez de Richardson .
Su problema es que está representando dos recursos como uno, donde realmente debería tener dos recursos que tengan una relación indicada por hipermedia. Usar hipermedia para describir relaciones es el glorioso nivel 3 de Descanso.
Su persona debe vivir debajo del URI
/person/{id}
y el animal debe vivir debajo/spiritanimal/{id}
. La persona debe indicar que tiene un espíritu animal usando un enlace al animal.Imaginemos una persona llamada Bob, que tiene id 123 y un animal espíritu Unicornio.
GET /person/123
volvería;
Ahora, cualquiera que lea a la persona 123 sabrá que tiene un animal espiritual y que tiene el URI donde puede obtener más información sobre él.
GET /spitiranimal/789
podría regresar
Ahora imaginemos a una persona llamada Fred, que tiene id 456 y no tiene espíritu animal.
GET /person/456
volvería;
Ahora, cualquiera que lea a la persona 456 sabrá que no tiene un espíritu animal, ya que no hay ningún vínculo. No es necesario utilizar ningún código de estado HTTP para representar la falta de una relación.
fuente
Esta es la url apropiada para obtener animales espirituales; por lo tanto, un error 404 es inapropiado. 404 es para representar un problema técnico, no un problema lógico.
La solución adecuada es devolver http 200 y
{"selectedAnimal": null}
Debería tener un método web separado
/person/{id}/hasSelectedSpiritAnimal
que regrese{"isSpiritAnimalSelected": false}
. Detrás de escena, puede o no hacer las mismas llamadas de método, simplemente devolviendo falso si es nulo, pero eso depende de él, no del código consumidor.Es mejor evitar combinar para separar consultas en un método web sin una razón convincente para hacerlo, incluso si las consultas están estrechamente relacionadas.
fuente
When you said "the spirit animal is not currently on file", it seemed quite similar to me to "there is no content"
Sin contenido significa que no hay contenido . es decir: devuelve "". Estos dos no son similares en absoluto. "El espíritu animal no está actualmente en el archivo" es muy diferente de "".Lo que representa su punto final no es solo un animal; Es un animal o falta de él. Es un valor mejor representado por un
Optional
/Maybe
/Nullable
/ etc.Por lo tanto, los valores legítimos (como en 200 OK) pueden ser:
{'animal': <some animal>, 'selected': true}
{'animal': null, 'selected': false}
Me imagino que ese
DELETE
método, cuando se aplica al punto final, puede establecerse'selected'
defalse
nuevo, es decir, desarmar el animal seleccionado.Puede, por supuesto, soltar la
'selected'
clave aquí, solo se muestra para mayor claridad; string vsnull
es suficiente para la distinción.fuente
Deberías usar 404.
Como está creando una interfaz de programación, no una interfaz humana, el texto 404 es opcional.
Prefiero esto porque prefiero los protocolos estándar tanto como sea posible. HTTP tiene una forma de representar la no existencia, y eso es lo que usaría.
EDITAR: suponga que agregó una función en la que los usuarios pueden elegir si desean compartir sus espíritus animales y alguien no los comparte. ¿Devolverías 200 OK
null
o 200 OK"Unauthorized
? ¿O utilizaría el estándar 401 no autorizado / 403 prohibido? Esto parece directamente análogo a no elegir uno en primer lugar.Alternativamente, si desea utilizar 200 OK + JSON, debe regresar
null
.Mantén las cosas limpias. Cree más envoltura solo si es necesario.
fuente
null
(no tienen valor). Esto es diferente al cliente que solicita algo para lo cual no existe un espacio para mantener el valor. No sugeriría lanzar unAttributeError
en Python cuando el valor seaNone
; eso haría que la interfaz fuera poco práctica e innecesariamente difícil de trabajar. Más pragmáticamente, muchas API de clientes HTTP podrían convertir el 404 en el mecanismo de manejo de errores estándar del lenguaje (código de error, excepción, tipo de error), lo que significa que tendría que suprimir un error extraño./person/{id}/selectedSpritAnimal
, observa el error tipográficoSprit
)./person/{id}/isSpiritAnimalSelected
que le dirá al cliente si se seleccionó uno. Me parece el mismo ejemplo clásico de probar si existe un archivo antes de leerlo. Simplemente lea el archivo y maneje el error ENOENT si se lanza./person/{id}/selectedSpiritAnimal
está destinado a ser utilizado incluso si el animal espiritual no existe. Esto significa que HTTP 4xx es incorrecto, cuando se usa en tal caso. Op también afirma correctamente que esto puede ser un olor a mal diseño de API.