¿Está bien por REST devolver contenido después de POST?

88

Estoy usando RESTlet y he creado un recurso. Manejo POST mediante el acceptRepresentationmétodo de anulación .

El cliente debería enviarme algunos datos, luego los almaceno en DB, establezco la respuesta en 201 (SUCCESS_CREATED) y necesito devolver algunos datos al cliente, pero el tipo de retorno acceptRepresentationes void.

En mi caso, necesito devolver algún identificador para que el cliente pueda acceder a ese recurso.

Por ejemplo, si tengo un recurso con URL /resourcey el cliente envía una solicitud POST, agrego una nueva fila en DB y su dirección debería ser /resource/{id}. Necesito enviar {id}.

¿Estoy haciendo algo mal? ¿Los principios de REST permiten devolver algo después de POST? Si es así, ¿cómo puedo hacerlo, y si no, cuál es la forma de manejar esta situación?

del-chico
fuente
Vea la respuesta de Thom para saber cómo configurar el cuerpo de la respuesta desde acceptRepresentation ().
Avi Flax

Respuestas:

96

REST solo dice que debe ajustarse a la interfaz uniforme. En otras palabras, dice que debe hacer lo que se supone que debe hacer POST según la especificación HTTP . Aquí está la cita de esa especificación que es relevante,

Si se ha creado un recurso en el servidor de origen, la respuesta DEBERÍA ser 201 (Creado) y contener una entidad que describe el estado de la solicitud y se refiere al nuevo recurso, y un encabezado de Ubicación (ver sección 14.30).

Como puede ver en esto, tiene dos lugares donde puede indicarle al cliente dónde reside el recurso recién creado. El encabezado Ubicación debe tener una URL que apunte al nuevo recurso y también puede devolver una entidad con los detalles.

No estoy seguro de cuál es la diferencia entre anular acceptRepresentation () y anular post (), pero este ejemplo muestra cómo devolver una respuesta de un POST.

Darrel Miller
fuente
2
@ del-boy: Vea la respuesta de Thom para saber cómo configurar el cuerpo de la respuesta desde acceptRepresentation ().
Avi Flax
1
La cita de especificación HTTP no prohíbe una respuesta, si mira en la Sección 6, está claro: está permitido: Request and Response messages MAY transfer an entity if not otherwise restricted by the request method or response status code. An entity consists of entity-header fields and an entity-body, although some responses will only include the entity-headers.
MikeF
@MikeF No era mi intención inferir que no se permitía un cuerpo de respuesta. La parte de la especificación que cité específicamente dice "y contiene una entidad". Debería haber sido más claro en mi texto.
Darrel Miller
16

Renunciaré a enviar cualquier cosa en el cuerpo de la respuesta. Simplemente configure Ubicación: en la URL (completa) del recurso recién creado.

Su descripción sugiere que esta es exactamente la semántica que usted:

  1. PUBLICAR algo para crearlo
  2. Responde con suficiente para saber dos cosas:
    1. Que sucedió la creación (el 201)
    2. Dónde encontrar lo nuevo (el encabezado de Ubicación)

Cualquier otra cosa es superflua.

cdent
fuente
No es que Wikipedia sea siempre una buena fuente, sino que también afirma "[...] Para proporcionar información sobre la ubicación de un recurso recién creado. En esta circunstancia, el encabezado de ubicación debe enviarse con un código de estado HTTP de 201 o 202 . "
Arjan
1
POST puede ejecutar lógica que crea uno o más recursos. El resultado del procesamiento puede ser necesario para el cliente. Por lo tanto, devolverlo en la respuesta evita la necesidad de realizar una o más llamadas GET a la API. Los datos creados / modificados por el método POST pueden no ser (y a menudo no lo son) superfluos para el cliente.
Paulo Merson
10

Dos preguntas diferentes:

¿El patrón de aplicación REST admite la devolución de datos en un POST?

No creo que REST lo rechace explícitamente, pero el tratamiento preferido se detalla en la respuesta de Darrel.

¿El marco RESTlet permite devolver datos en un POST?

Sí, aunque devuelve void, en una clase que extiende Resource, tiene acceso completo al objeto del objeto Response a través del método getResponse (). Entonces puede llamar a getResponse (). SetEntity () con los datos que desee.

Thom
fuente
6

Envíela en cualquier formato que se solicite. Eso podría ser:

<success>
    <id>5483</id>
</success>

O:

{ "type": "success", "id": 5483 }

Depende de lo que hagas habitualmente. Si no esperan los datos, simplemente deberían ignorarlos, pero cualquier cliente que quiera manejarlos correctamente debería poder hacerlo.

Samir Talwar
fuente
Ok, tengo dos formatos posibles (html y xml). Sé cómo manejar el tipo de formato solicitado, pero no sé cómo agregar datos a la respuesta. El método represent devuelve Representación, así que solo devuelvo lo que quiera, pero acceptRepresentation es un método vacío, por lo que no puedo devolver ningún dato ...
del-boy
1

Si responde 201 Creado con un cuerpo de entidad, en lugar de una redirección de ubicación, entonces es una buena idea incluir un encabezado de ubicación de contenido que apunte al recurso que se está representando en la respuesta.

Esto evitará una posible confusión, en la que un cliente podría (justificadamente) asumir que la entidad de respuesta realmente representa un nuevo estado del 'creador', y no el recurso creado.

> POST /collection
> ..new item..

< 201 Created
< Location: /collection/1354
< Content-Location: /collection/1354
< <div class="item">This is the new item that was created</div>
Miguel
fuente
3
Creo que Content-Location tiene un propósito diferente. La especificación HTTP dice que la ubicación de contenido no está definida para POST y PUT. El encabezado Location se usa con 201-Create. Devolver una ubicación no redirige automáticamente, necesita un código de respuesta 3XX para eso.
Darrel Miller
1
El encabezado de ubicación se utiliza (en una respuesta 201) para indicar dónde se encuentra el recurso creado; no es relevante para el cuerpo de la entidad de la respuesta que acompaña. Mi punto fue que, si desea incluir el recurso creado en la respuesta 201 en sí (en lugar de dirigir / redirigir al cliente a otro URI), sería una buena idea un encabezado de ubicación de contenido. Es probable que esto esté 'doblando un poco las reglas', pero es más eficiente que requerir otro ciclo de solicitud / respuesta para obtener el estado del nuevo recurso para el cliente.
Mike
Tiene sentido para mi. Nunca antes había usado el encabezado Content-Location.
Darrel Miller
si el cliente es un humano con un navegador, devolver 201 con el encabezado Location no tiene sentido. El usuario no sabrá qué hacer con él. si el cliente es un robot, se puede programar para saber cómo manejarlo, como un GET de seguimiento en la ubicación.
irrefutable
3
@irreputable: Creo que REST fue diseñado para diseñar API, donde A no significa Agente de usuario que busca algo de HTML para renderizar.
Hermes