O REST pode retornar conteúdo após o POST?

89

Estou usando RESTlet e criei um recurso. Eu lido com o POST substituindo o acceptRepresentationmétodo.

O cliente deve me enviar alguns dados, então eu armazeno no banco de dados, configure a resposta para 201 (SUCCESS_CREATED) e preciso retornar alguns dados ao cliente, mas o tipo de retorno acceptRepresentationé void.

No meu caso, preciso retornar algum identificador para que o cliente possa acessar esse recurso.

Por exemplo, se eu tivesse um recurso com URL /resourcee o cliente enviasse a solicitação POST, adiciono uma nova linha no banco de dados e seu endereço deveria ser /resource/{id}. Eu preciso enviar {id}.

Estou fazendo algo errado? Os princípios REST permitem retornar algo após o POST? Em caso afirmativo, como posso fazer e, em caso negativo, qual é a forma de lidar com esta situação?

del-boy
fonte
Consulte a resposta de Thom para saber como definir o corpo da resposta em acceptRepresentation ().
Avi Flax

Respostas:

97

REST apenas diz que você deve estar em conformidade com a interface uniforme. Em outras palavras, ele diz que você deve fazer o que o POST deve fazer de acordo com a especificação HTTP . Aqui está a citação dessa especificação que é relevante,

Se um recurso tiver sido criado no servidor de origem, a resposta DEVE ser 201 (Created) e conter uma entidade que descreve o status da solicitação e se refere ao novo recurso, e um cabeçalho Location (ver seção 14.30).

Como você pode ver, você tem dois lugares onde pode indicar ao cliente onde reside o recurso recém-criado. O cabeçalho Location deve ter um URL que aponta para o novo recurso e você também pode retornar uma entidade com os detalhes.

Não tenho certeza de qual é a diferença entre substituir acceptRepresentation () e substituir post (), mas este exemplo mostra como retornar uma resposta de um POST.

Darrel Miller
fonte
2
@ del-boy: Consulte a resposta de Thom para saber como definir o corpo da resposta em acceptRepresentation ().
Avi Flax
1
A citação de especificação HTTP não proíbe uma resposta, se você olhar na Seção 6 está claro sobre isso: é 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 Não era minha intenção inferir que um corpo de resposta não era permitido. A parte da especificação que citei diz especificamente "e contém uma entidade". Eu deveria ter sido mais claro no meu texto.
Darrel Miller de
16

Eu renunciaria a enviar qualquer coisa no corpo da resposta. Basta definir Localização: para a URL (completa) do recurso recém-criado.

Sua descrição sugere que esta é exatamente a semântica que você:

  1. POSTAR algo para criá-lo
  2. Responda com o suficiente para saber duas coisas:
    1. Que a criação aconteceu (o 201)
    2. Onde encontrar o novo (o cabeçalho Location)

Qualquer outra coisa é supérflua.

cdent
fonte
Não que a Wikipedia seja sempre uma boa fonte, mas que também afirma "[...] fornecer informações sobre a localização de um recurso recém-criado. Nesta circunstância, o cabeçalho Location deve ser enviado com um código de status HTTP 201 ou 202 . "
Arjan
1
O POST pode executar a lógica que cria um ou mais recursos. O resultado do processamento pode ser necessário para o cliente. Portanto, retorná-lo na resposta evita a necessidade de fazer uma ou mais chamadas GET para a API. Os dados criados / alterados pelo método POST podem não ser (e muitas vezes não são) supérfluos para o cliente.
Paulo Merson
10

Duas questões diferentes:

O padrão de aplicativo REST suporta o retorno de dados em um POST?

Não acho que REST o proíba explicitamente, mas o tratamento preferido é explicado na resposta de Darrel.

A estrutura RESTlet permite retornar dados em um POST?

Sim, embora ele retorne void, em uma classe que estende Resource, você tem acesso total ao objeto do objeto Response por meio do método getResponse (). Portanto, você pode chamar getResponse (). SetEntity () com quaisquer dados que desejar.

Thom
fonte
6

Produza em qualquer formato solicitado. Isso pode ser:

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

Ou:

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

Depende do que você costuma fazer. Se não estiverem esperando os dados, eles devem simplesmente ignorá-los, mas qualquer cliente que deseje manipulá-los adequadamente deve conseguir.

Samir Talwar
fonte
Ok, tenho dois formatos possíveis (html e xml). Eu sei como lidar com o tipo de formato solicitado, mas não sei como adicionar dados à resposta. O método represent retorna Representation, então eu apenas retorno o que eu quiser, mas acceptRepresentation é o método nulo, então não posso retornar nenhum dado ...
del-boy
1

Se você responder 201 Criado com um corpo de entidade, em vez de um redirecionamento de local, é uma boa ideia incluir um cabeçalho Content-Location apontando para o recurso que está sendo representado na resposta.

Isso evitará confusão potencial - na qual um cliente poderia (justificadamente) assumir que a entidade de resposta realmente representa um novo estado do 'criador', e não o recurso criado.

> 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>
Mike
fonte
3
Acho que Content-Location tem um propósito diferente. A especificação HTTP diz que o Content-Location não está definido para POST e PUT. O cabeçalho Location é usado com um 201-Create. Retornar um local não faz um redirecionamento automaticamente, você precisa de um código de resposta 3XX para isso.
Darrel Miller
1
O cabeçalho de localização é usado (em uma resposta 201) para indicar onde o recurso criado está localizado; não é relevante para o corpo da entidade da resposta que acompanha. Meu ponto é que - se você quiser incluir o recurso criado na própria resposta 201 (em vez de direcionar / redirecionar o cliente para outro URI), um cabeçalho de localização de conteúdo seria uma boa ideia. Isso provavelmente está 'distorcendo as regras' um pouco, mas é mais eficiente do que exigir outro ciclo de solicitação / resposta para obter o estado do novo recurso para o cliente.
Mike
Faça sentido para mim. Nunca usei o cabeçalho Content-Location antes.
Darrel Miller
se o cliente for um humano com um navegador, retornar 201 com o cabeçalho Location não faz sentido. O usuário não saberá o que fazer com ele. se o cliente for um robô, ele pode ser programado para saber como lidar com ele - como um acompanhamento GET no Local.
irreputável
3
@irreputable: Eu acredito que REST foi feito para projetar APIs, onde A não significa um Agente de Usuário que procura algum HTML para renderizar.
Hermes