'Mejor' práctica para una respuesta POST tranquila

217

Así que nada nuevo aquí, solo estoy tratando de obtener alguna aclaración y parece que no puedo encontrar ninguna en otras publicaciones.

Estoy creando un nuevo recurso con calma, digamos:

/books (POST)

con un cuerpo:

{
  title: 'The Lion, the Witch and the Wardrobe',
  author: 'C. S. Lewis'
}

Sé que debería devolver un 201 (Creado) con un encabezado de Ubicación del nuevo recurso:

Location: /books/12345

La pregunta que parece que no puedo responder por mí mismo es qué debería devolver el servidor en el cuerpo.

A menudo he hecho este tipo de respuesta:

{
  id: 12345,
  title: 'The Lion, the Witch and the Wardrobe',
  author: 'C. S. Lewis'
}

He hecho esto por un par de razones:

  1. He escrito api para marcos frontales como angularjs. En mi caso particular, estoy usando recursos angulares y a menudo necesito solo la identificación del recurso para ubicarlo. Si no devolvía la identificación en el cuerpo de la respuesta, tendría que analizarla fuera del encabezado de Ubicación.
  2. En una OBTENCIÓN de todos los libros, generalmente devuelvo el objeto completo, no solo la identificación. En este sentido, mi código de cliente no tiene que diferenciar de dónde obtener la identificación (encabezado o cuerpo de ubicación).

Ahora sé que estoy realmente en el área gris aquí, pero la mayoría de la gente dice que devolver todo el recurso es una 'mala' práctica. Pero, ¿qué pasa si el servidor cambia / agrega información al recurso? Definitivamente agrega la identificación, pero también podría agregar otras cosas como una marca de tiempo. En el caso de que no devuelva todo el recurso, ¿es realmente mejor hacer una POST, devolver la identificación y luego hacer que el cliente realice una OBTENCIÓN para obtener el nuevo recurso?

perdido en la traducción
fuente
Personalmente prefiero el cuerpo vacío para las respuestas POST. ¿No debería ser el valor del encabezado RESTful Location un URI (identificador de recurso único)? Entonces, tal vez debería usarlo como ID y no analizarlo para descubrir una ID interna del servidor. Los consumidores de la API IMO y RESTful deben navegar usando los hipervínculos proporcionados y no construir la ruta, adivinando dónde un servidor en particular ubica los recursos ... Y después de todo, ¿el cliente no sabe el estado del recurso que acaba de crear? repetirlo es un desperdicio de recursos de red.
ch4mp
1
Para Crear / Insertar, Estado 201 - CREADO, Ubicación del encabezado → localhost: 8080 / empleados / 1 (Ver: aquí )
Hassan Tareq

Respuestas:

129

Devolver el objeto completo en una actualización no parecería muy relevante, pero difícilmente puedo ver por qué devolver el objeto completo cuando se crea sería una mala práctica en un caso de uso normal. Esto sería útil al menos para obtener la identificación fácilmente y para obtener las marcas de tiempo cuando sea relevante. Este es realmente el comportamiento predeterminado que se obtiene al andamiaje con Rails.

Realmente no veo ninguna ventaja en devolver solo la identificación y hacer una solicitud GET después, para obtener los datos que podría haber obtenido con su POST inicial.

De todos modos, siempre que su API sea consistente, creo que debe elegir el patrón que mejor se adapte a sus necesidades. No hay ninguna forma correcta de cómo construir una API REST, imo.

Daniel Pérez
fuente
26
Sé que esto es antiguo, pero puedo dar un argumento convincente para usar un GET después de su POST. En la especificación http / 1.1, cualquier herramienta histórica puede ignorar la configuración de la memoria caché transmitida desde su respuesta GET ... por lo tanto, si su usuario usa el botón Atrás en el navegador para volver a esta página después de actualizarla con la POST, puede usar obsoleta datos en caché del GET original. Entonces, si reutiliza el GET, puede actualizar el caché y obtener una mejor instantánea de cómo se veía la página cuando se fueron ...
Sombreado
8
@Shaded Si la API está diseñada para ser utilizada también por aplicaciones, entonces su argumento para hacer dos solicitudes no es válido. Allí, generalmente almacena en caché los datos manteniendo objetos de un tipo de modelo en la memoria, lo que generalmente se hace con la respuesta a las solicitudes POST. Y con respecto a los navegadores, la respuesta a una solicitud POST realmente no duele siempre y cuando todavía haya un punto final GET api.
Jeehut
Suscribo lo que dice Daniel aquí. Incluso si verifica marcos maduros como Spring Data, siempre devuelven todo el objeto después de persistirlo. Creo que es una buena práctica, como en el que el cliente se ahorrará una ida y vuelta del servidor para obtener la misma información
frandevel
205

La devolución del nuevo objeto se ajusta al principio REST de "Interfaz uniforme: manipulación de recursos a través de representaciones". El objeto completo es la representación del nuevo estado del objeto que se creó.

Aquí hay una referencia realmente excelente para el diseño de API: Mejores prácticas para diseñar una API RESTful pragmática

Incluye una respuesta a su pregunta aquí: las actualizaciones y la creación deben devolver una representación de recursos

Dice:

Para evitar que un consumidor de API tenga que volver a presionar la API para obtener una representación actualizada, haga que la API devuelva la representación actualizada (o creada) como parte de la respuesta.

Me parece muy pragmático y encaja con el principio REST que mencioné anteriormente.

grahamesd
fuente
66
¿qué tal devolver todo el conjunto de objetos relevantes? De esta manera, es posible la clasificación puede hacerse del lado del servidor, y facilita la aplicación front-end
phil294
2
Pero estas mejores prácticas no son las mejores. El autor afirma que HATEOAS, que es tan importante como otros principios, no debe usarse porque "no está listo". HATEOAS nunca estará "listo", porque todos los principios RESTful son solo principios de diseño arquitectónico, no una implementación específica. La referencia citada es sobre la visión del autor sobre RESTful API, que no es RESTful en absoluto debido a la caída de HATEOAS. Es por eso que esta no es la mejor referencia :)
marcinn
1
@marcinn: notarás que la pregunta original tenía citas sobre 'Mejor', supongo porque hay una gran cantidad de opinión en esta área. La referencia que señalé es algo que he encontrado práctico. Si tiene una mejor referencia, compártala. Siempre estoy abierto a aprender más.
grahamesd
@grahamesd Una implementación es una cosa diferente que el diseño / principio de diseño arquitectónico. Nadie puede esperar que HATEOAS esté listo algún día, pero existe la posibilidad de que alguien cree una implementación aceptable para muchos. Vinay también escribió sobre la asignación de métodos http a URL y operaciones específicas (CRUD), afirmó que el control de versiones mediante el prefijo de URL es más pragmático, escribió que filtrar por parámetros de consulta es un camino a seguir ... está bien, pero todo esto tiene poco para hacer con arquitectura RESTful. Escribió sobre algún tipo de contrato. Eso está bien para la API HTTP, pero no lo llame RESTful.
marcinn
@grahamesd Aquí hay algunas publicaciones que explican esto: - medium.com/@andrea.chiarelli/… - restfulapi.net
marcinn