Estoy diseñando un servicio web RESTful usando WebApi y me preguntaba qué respuestas HTTP y cuerpos de respuesta devolver al actualizar / crear objetos.
Por ejemplo, puedo usar el método POST para enviar algunos JSON al servicio web y luego crear un objeto. ¿Es una buena práctica establecer el estado HTTP en creado (201) o bien (200) y simplemente devolver un mensaje como "Nuevo empleado agregado", o devolver el objeto que se envió originalmente?
Lo mismo ocurre con el método PUT. ¿Qué estado HTTP es mejor usar y debo devolver el objeto que se creó o simplemente un mensaje? Teniendo en cuenta el hecho de que el usuario sabe qué objeto está tratando de crear / actualizar de todos modos.
¿Alguna idea?
Ejemplo:
Añadir nuevo empleado:
POST /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json
{
"Employee": {
"Name" : "Joe Bloggs",
"Department" : "Finance"
}
}
Actualizar empleado existente:
PUT /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json
{
"Employee": {
"Id" : 1
"Name" : "Joe Bloggs",
"Department" : "IT"
}
}
Respuestas:
Respuesta con objeto creado / actualizado
HTTP/1.1 201 Created
Content-Length: 39
Content-Type: application/json; charset=utf-8
Date: Mon, 28 Mar 2016 14:32:39 GMT
{
"Employee": {
"Id" : 1
"Name" : "Joe Bloggs",
"Department" : "IT"
}
}
Respuesta con solo mensaje:
HTTP/1.1 200 OK
Content-Length: 39
Content-Type: application/json; charset=utf-8
Date: Mon, 28 Mar 2016 14:32:39 GMT
{
"Message": "Employee updated"
}
Respuesta con solo código de estado:
HTTP/1.1 204 No Content
Content-Length: 39
Date: Mon, 28 Mar 2016 14:32:39 GMT
UPDATE/INSERT ... RETURNING
variante Postgresql para SQL. Es extremadamente útil, especialmente porque mantiene la presentación de nuevos datos y la solicitud de la versión actualizada atómica.Respuestas:
Como con la mayoría de las cosas, depende. Su compensación es la facilidad de uso frente al tamaño de la red. Puede ser muy útil para los clientes ver el recurso creado. Puede incluir campos poblados por el servidor, como el último tiempo de creación. Como parece que está incluyendo el en
id
lugar de usarhateoas
, los clientes probablemente deseen ver la identificación del recurso que acaban dePOST
editar.Si no incluye el recurso creado, no cree un mensaje arbitrario. Los campos 2xx y Ubicación son información suficiente para que los clientes estén seguros de que su solicitud se manejó adecuadamente.
fuente
Personalmente, siempre vuelvo solo
200 OK
.Para citar tu pregunta
¿Por qué agregar ancho de banda adicional (que podría tener que pagarse) para decirle al cliente lo que ya sabe?
fuente
200
/204 No Content
para evitar confundir jQuery y similares.@iswinky Siempre enviaría la carga útil en caso de POST y PUT.
En el caso de POST, puede crear la entidad con una ID interna o un UUID. Por lo tanto, tiene sentido devolver la carga útil.
De manera similar, en el caso de PUT, podría ignorar algunos campos del usuario (valores inmutables, por ejemplo), o en el caso de un PATCH, los datos también podrían haber sido modificados por otros usuarios.
Enviar los datos nuevamente tal como fueron almacenados siempre es una buena idea y definitivamente no hace daño. Si la persona que llama no necesita estos datos devueltos, no los procesará, sino que solo consumirá el código de estado. De lo contrario, pueden usar estos datos como algo para actualizar la interfaz de usuario.
Solo en el caso de DELETE, no enviaría la carga útil y haría un 200 con un contenido de respuesta o un 204 sin contenido de respuesta.
Editar: Gracias a algunos comentarios de abajo, estoy reescribiendo mi respuesta. Todavía mantengo la forma en que diseño mis API y envío las respuestas, pero creo que tiene sentido calificar algunos de mis pensamientos de diseño.
a) Cuando digo devolver la carga útil, en realidad quise decir devolver los datos del recurso, no la misma carga que vino en la solicitud. Por ejemplo: si envía una carga útil de creación, en el backend puedo crear otras entidades como UUID y (tal vez) marcas de tiempo e incluso algunas conexiones (gráficas). Enviaría todo esto de vuelta en la respuesta (no solo la carga útil de la solicitud como está, lo cual no tiene sentido).
b) No enviaría respuestas en caso de que la carga útil sea muy grande. He discutido esto en los comentarios, pero me gustaría advertir que haré todo lo posible para diseñar mis API o mis recursos de manera que no tenga que tener cargas útiles muy grandes. Intentaría dividir los recursos en entidades más pequeñas y manejables de modo que cada recurso esté definido por 15-20 atributos JSON y no más grandes.
En el caso de que el objeto sea muy grande o el objeto principal se actualice, entonces enviaría las estructuras anidadas como hrefs.
En pocas palabras, definitivamente trataría de devolver los datos que tengan sentido para que el consumidor / UI procese de inmediato y se haga con una acción de API atómica en lugar de tener que ir y buscar 2-5 API más solo para actualizar la UI publicar el creación / actualización de los datos.
Las API de servidor a servidor pueden pensar de manera diferente al respecto. Me estoy centrando en las API que impulsan la experiencia del usuario.
fuente
Haciendo referencia a los estándares RFC de enlace , debe devolver el estado 201 (creado) al almacenar correctamente el recurso de solicitud mediante Post. En la mayoría de las aplicaciones, el servidor mismo genera la identificación del recurso, por lo que es una buena práctica devolver la identificación del recurso creado. Devolver todo el objeto es la sobrecarga para la solicitud de publicación. La práctica ideal es devolver la ubicación de la URL del recurso recién creado.
Por ejemplo, puede consultar el siguiente ejemplo que guarda el objeto de empleado en la base de datos y devuelve la URL del objeto de recurso recién creado como respuesta.
Este punto final de descanso devolverá la respuesta como:
Estado 201 - CREADO
Ubicación del encabezado → http: // localhost: 8080 / employee / 1
fuente
Haría una carga útil en el cuerpo de retorno condicional a un parámetro HTTP.
En la mayoría de los casos, lo mejor es devolver algún tipo de contenido al consumidor de API para evitar viajes de ida y vuelta innecesarios (una de las razones por las que existe GraphQL).
De hecho, a medida que nuestras aplicaciones se vuelven más intensivas en datos y distribuidas, trato de observar esta guía:
Mi directriz :
Cada vez que hay un caso de uso que exige un OBTENER inmediatamente después de una POST o PUT, ese es un caso en el que sería mejor simplemente devolver algo en la respuesta POST / PUT.
Cómo se hace esto y qué tipo de contenido devolver de un PUT o POST es específico de la aplicación. Ahora, sería interesante si la aplicación pudiera parametrizar el tipo de "contenido" en el cuerpo de la respuesta (¿queremos solo la ubicación del nuevo objeto, o algunos de los campos, o el objeto completo, etc.)
Una aplicación podría definir un conjunto de parámetros que un POST / PUT puede recibir para controlar el tipo de "contenido" que se devolverá en el cuerpo de la respuesta. O podría codificar algún tipo de consulta GraphQL como parámetro (puedo ver que esto es útil pero también se convierte en una pesadilla de mantenimiento).
De cualquier manera, me parece que:
Entonces, 1) hazlo, pero 2) hazlo simple.
Otra opción que he visto es que las personas crean puntos finales alternativos (por ejemplo, / clients para POST / PUT que no devuelven nada en el cuerpo y / customer_with_details para POST / PUT a / clients, pero que devuelven algo en el cuerpo de respuesta).
Sin embargo, evitaría este enfoque. ¿Qué sucede cuando legítimamente necesitas devolver diferentes tipos de contenido? ¿Un punto final por tipo de contenido? No escalable ni mantenible.
fuente