Estou projetando um serviço Web RESTful usando WebApi e queria saber quais respostas HTTP e corpos de resposta devem retornar ao atualizar / criar objetos.
Por exemplo, eu posso usar o método POST para enviar algum JSON para o serviço da web e criar um objeto. É uma prática recomendada definir o status HTTP como criado (201) ou ok (200) e simplesmente retornar uma mensagem como "Novo funcionário adicionado" ou retornar o objeto que foi enviado originalmente?
O mesmo vale para o método PUT. Qual status HTTP é melhor usar e preciso retornar o objeto que foi criado ou apenas uma mensagem? Considerando o fato de que o usuário sabe qual objeto está tentando criar / atualizar de qualquer maneira.
Alguma ideia?
Exemplo:
Adicionar novo funcionário:
POST /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json
{
"Employee": {
"Name" : "Joe Bloggs",
"Department" : "Finance"
}
}
Atualizar funcionário existente:
PUT /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json
{
"Employee": {
"Id" : 1
"Name" : "Joe Bloggs",
"Department" : "IT"
}
}
Respostas:
Resposta com o objeto criado / atualizado
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"
}
}
Resposta com apenas uma mensagem:
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"
}
Resposta com apenas código de status:
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. É extremamente útil, especialmente porque mantém atômica a submissão de novos dados e a solicitação da versão atualizada.Respostas:
Como na maioria das coisas, isso depende. Sua troca é a facilidade de uso versus o tamanho da rede. Pode ser muito útil para os clientes verem o recurso criado. Pode incluir campos preenchidos pelo servidor, como o horário da última criação. Como você parece incluir o
id
invés de usarhateoas
, os clientes provavelmente desejam ver o ID do recurso que acabaram dePOST
editar.Se você não incluir o recurso criado, não crie uma mensagem arbitrária. Os campos 2xx e Local são informações suficientes para que os clientes tenham certeza de que sua solicitação foi tratada adequadamente.
fonte
Pessoalmente, eu sempre volto apenas
200 OK
.Para citar sua pergunta
Por que adicionar largura de banda extra (que talvez precise ser paga) para informar ao cliente o que ele já sabe?
fonte
200
/204 No Content
para evitar confundir jQuery e similares.@iswinky Eu sempre enviava de volta a carga no caso de POST e PUT.
No caso do POST, você pode criar a entidade com um ID interno ou um UUID. Portanto, faz sentido enviar de volta a carga útil.
Da mesma forma, no caso de PUT, você pode ignorar alguns campos do usuário (valores imutáveis, por exemplo) ou, no caso de um PATCH, os dados também podem ter sido alterados por outros usuários.
Enviar os dados de volta como foram mantidos é sempre uma boa ideia e definitivamente não prejudica. Se o chamador não precisar desses dados retornados, ele não os processará, mas consumirá apenas o statusCode. Caso contrário, eles podem usar esses dados como algo para atualizar a interface do usuário.
É apenas no caso de um DELETE que eu não enviaria a carga novamente e faria um 200 com um conteúdo de resposta ou um 204 sem um conteúdo de resposta.
Edit: Graças a alguns comentários abaixo, estou reformulando minha resposta. Ainda permaneço pela maneira como desenvolvo minhas APIs e envio respostas de volta, mas acho que faz sentido qualificar alguns dos meus pensamentos sobre design.
a) Quando digo devolver a carga útil, na verdade pretendi dizer devolver os dados do recurso, não a mesma carga que veio na solicitação. Ex: se você enviar uma carga útil de criação, no back-end posso criar outras entidades, como UUID e (talvez) carimbos de data e hora e algumas conexões (gráficas). Eu enviaria tudo isso de volta na resposta (não apenas a carga útil da solicitação como está - o que é inútil).
b) Eu não enviaria respostas de volta caso a carga útil fosse muito grande. Eu discuti isso nos comentários, mas o que eu gostaria de ressaltar é que eu tentaria o meu melhor para projetar minhas APIs ou meus recursos, de modo que não precise ter cargas úteis muito grandes. Eu tentaria dividir os recursos em entidades menores e gerenciáveis, de modo que cada recurso seja definido por 15 a 20 atributos JSON e não maiores.
No caso em que o objeto é muito grande ou o objeto pai está sendo atualizado, eu enviava de volta as estruturas aninhadas como hrefs.
O ponto principal é que eu definitivamente tentaria enviar de volta os dados que fazem sentido para o consumidor / interface do usuário processar imediatamente e ser realizado com uma ação de API atômica, em vez de precisar buscar mais 2-5 API apenas para atualizar a interface do usuário após criação / atualização dos dados.
As APIs de servidor para servidor podem pensar de maneira diferente sobre isso. Estou focando em APIs que proporcionam uma experiência do usuário.
fonte
Fazendo referência aos padrões RFC do link , você deve retornar o status 201 (criado) ao armazenar com êxito o recurso de solicitação usando Post. Na maioria dos aplicativos, o ID do recurso é gerado pelo próprio servidor, portanto, é uma boa prática retornar o ID do recurso criado. Retornar o objeto inteiro é a sobrecarga para a solicitação Post. A prática ideal é retornar o local da URL do recurso recém-criado.
Por exemplo, você pode consultar o exemplo a seguir que salva o Objeto do funcionário no banco de dados e retorna a URL do objeto de recurso recém-criado como resposta.
Este ponto de extremidade restante retornará a resposta como:
Status 201 - CREATED
Localização do cabeçalho → http: // localhost: 8080 / funcionários / 1
fonte
Eu tornaria uma carga útil no corpo do retorno condicional a um parâmetro HTTP.
Na maioria das vezes, é melhor retornar algum tipo de conteúdo de volta ao consumidor da API para evitar viagens de ida e volta desnecessárias (uma das razões pelas quais o GraphQL existe).
De fato, à medida que nossos aplicativos se tornam mais intensivos em dados e distribuídos, tento observar esta diretriz:
Minha orientação :
Sempre que houver um caso de uso que exija um GET imediatamente após um POST ou PUT, é o caso em que seria melhor simplesmente retornar algo na resposta POST / PUT.
Como isso é feito e que tipo de conteúdo retornar de um PUT ou POST, isso é específico do aplicativo. Agora, seria interessante se o aplicativo pudesse parametrizar o tipo de "conteúdo" no corpo da resposta (queremos apenas a localização do novo objeto, ou alguns dos campos, ou o objeto inteiro, etc.)
Um aplicativo pode definir um conjunto de parâmetros que um POST / PUT pode receber para controlar o tipo de "conteúdo" a ser retornado no corpo da resposta. Ou poderia codificar algum tipo de consulta do GraphQL como parâmetro (posso ver isso útil, mas também se tornar um pesadelo de manutenção).
De qualquer forma, parece-me que:
Então, 1) faça, mas 2) mantenha a simplicidade.
Outra opção que eu vi são pessoas criando pontos de extremidade alternativos (por exemplo, / customers para POST / PUT que não retornam nada no corpo e / customer_with_details para POST / PUT para / customers, mas que retornam algo no corpo de resposta).
Eu evitaria essa abordagem, no entanto. O que acontece quando você legitimamente precisa retornar diferentes tipos de conteúdo? Um ponto de extremidade por tipo de conteúdo? Não é escalável ou sustentável.
fonte