¿Debo devolver una respuesta 204 o 404 cuando no se encuentra un recurso?

15

Estoy desarrollando un servicio RESTful simple para torneos y horarios. Cuando se crea un torneo a través de una solicitud POST que contiene un cuerpo JSON, el torneo se inserta en un BiMap, declarado de la siguiente manera en una implementación DAO:

private BiMap<String, Tournament> tournaments = Maps.synchronizedBiMap(HashBiMap.create());

Cuando se crea un torneo, se devuelve su ID de cadena asociada para que el usuario pueda tener una referencia futura de ese torneo. Él / ella puede obtener información del nuevo torneo realizando la siguiente solicitud:

GET http://localhost:8080/eventscheduler/c15268ce-474a-49bd-a623-b0b865386f39

¿Pero qué pasa si no se encuentra un torneo con tal identificación? Hasta ahora, estoy devolviendo una respuesta 204. Bueno, Jersey lo está haciendo por mí cuando regresa nullde uno de sus métodos. Este es el método que corresponde a la ruta anterior:

@Path("/{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Tournament getTournament(@PathParam("id") String id) {
    Optional<Tournament> optTournament = tournamentDao.getTournament(id);
    if (optTournament.isPresent())
        return optTournament.get();
    return null;
}

Mi pregunta es: ¿está bien devolver una 204: No Contentrespuesta, o debería ser una 404respuesta, ya que no se encontró el recurso?

Si debo cambiarlo a 404, pregunta obvia: ¿Debería cambiar la firma del método correcto? Como ahora un torneo (de tipo Tournament) podría no ser devuelto, el método debería verse diferente. ¿Debo usar el Responsetipo como el tipo de retorno en su lugar?

dabadaba
fuente

Respuestas:

32

HTTP 204significa que se encontró algo , pero está vacío. Por ejemplo, imagine que está sirviendo archivos de registro a través de HTTP, con solicitudes como http://example.com/logs/[date-goes-here] . El 18 de mayo de 2015:

  • http://example.com/logs/2015-05-19 volvería HTTP 404, lo que significa que no hay registros, porque, bueno, es difícil registrar el futuro.

  • http://example.com/logs/2015-05-18 , sin embargo, regresaría HTTP 200con las entradas de registro en el contenido de la respuesta, o HTTP 204si se creó el archivo de registro, pero todavía no hay registros registrados para esto fecha.

Si proporciona nullal marco como respuesta a una solicitud, se supone que encontró una entrada, y esta entrada está vacía, por lo tanto HTTP 204. En su lugar, debe throw new NotFoundException();indicar al marco que la entrada no existe, para que genere un HTTP 404.

Si debo cambiarlo a 404, pregunta obvia: ¿Debería cambiar la firma del método correcto?

No, tu no. Eso es lo bueno de eso throw new NotFoundException();. Funcionará sin importar cuál sea el tipo de retorno real de su método.

Arseni Mourzenko
fuente
55
Tome nota especial de RFC 2616 . 204 respuestas solo cumplen con las especificaciones si está omitiendo el cuerpo del mensaje por completo. Hasta cierto punto, el objetivo de una respuesta 204 es decir: "no, no es un accidente que no haya devuelto contenido". Para ampliar el ejemplo de MainMa: si una herramienta de búsqueda de registros escupió archivos de texto (por ejemplo, un envoltorio delgado alrededor de los archivos de registro que solo escupe el archivo de registro tal como está), un 204 sería apropiado para un archivo de registro vacío. Si la respuesta fuera un objeto JSON vacío (por ejemplo, {content: ''}), una respuesta 204 sería inapropiada.
Brian
" porque, bueno, es difícil registrar el futuro " . - Este bit depende de una fecha arbitraria; ¿Por qué no convertirlo en algo que no requiera que el lector finja que no es hoy? Tal vez usar 2015-02-29sería mejor, ya que es una fecha que no existe en absoluto.
Fondo de la demanda de Mónica
1

Su solicitud es GET http://localhost:8080/eventscheduler/c15268ce-474a-49bd-a623-b0b865386f39.

Si http://localhost:8080/eventscheduler/no existe como punto final, debe devolver un 404. Está intentando acceder a un recurso ( /eventscheduler/) que no existe. Esto indicaría a un cliente que existe un servidor localhost:8080, pero no hay nada en el eventschedulerpunto final.

Si http://localhost:8080/eventscheduler/existe como un punto final pero los recursos requeridos no están disponibles, es apropiado un error 5xx. Un buen ejemplo de esto sería si una base de datos está fuera de línea, donde podría devolver un 503. Por supuesto, es posible que solo desee devolver un error genérico 500 en lugar de una instancia específica.

Si http://localhost:8080/eventscheduler/existe pero la cosa representada por c15268ce-474a-49bd-a623-b0b865386f39no existe, devolvería un 200 con un cuerpo que indica los detalles. El punto final existe, la solicitud realizada era totalmente válida y podía procesarse, pero no había coincidencia.

Si la solicitud de su cliente al punto final no era válida, debería ver los otros errores 4xx. Puede indicar que el cliente no está autorizado para acceder al punto final o los elementos solicitados con un 401 o 403 o puede usar un 400 para indicar que la solicitud no es válida. Con cualquiera de estos, se puede proporcionar información adicional en el cuerpo de respuesta.

Thomas Owens
fuente
No es necesario distinguir entre el punto final y el recurso. Si el URI no coincide con ningún recurso, por alguna razón, el servidor debe devolver 404.
bdsl
Consulte el código de respuesta en este sitio para ver un ejemplo de un sitio que hace lo correcto. Es un sitio web, no una API, pero se aplica la misma especificación http. softwareengineering.stackexchange.com/questions/266183385
bdsl
@ bdsl, puedo decirte que eso está absolutamente mal. Por ejemplo, estoy interactuando con un servicio de usuario que puede devolver un perfil de usuario. Digamos que este punto final es /usery se usa como /[email protected]. Como consumidor de API, quiero saber si /userpor alguna razón no existe en el servidor (tal vez se agregó en la v2 de la API y el servidor está en la v1 o se cambió el nombre en la v3) o si el usuario con el correo electrónico [email protected]no existe El primero es un 404, el segundo es un 200 con un cuerpo que indica que ningún usuario tiene esa dirección de correo electrónico.
Thomas Owens
@bdsl Eso es bueno, pero eso no significa que sea correcto o mejor. Tampoco creo que pueda comparar un sitio web diseñado para la interacción humana a través de un navegador web frente a una API diseñada para su uso en un sistema de software.
Thomas Owens
1
Este problema se trata más adelante en youtube.com/watch?v=nSKp2StlS6s
bdsl el