Resposta 400 vs 422 ao POST de dados

355

Estou tentando descobrir qual o código de status correto para retornar em diferentes cenários com uma API "semelhante a REST" na qual estou trabalhando. Digamos que eu tenha um ponto final que permita compras POST no formato JSON. Se parece com isso:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

O que devo retornar se o cliente me enviar "sales_tax" (em vez do esperado "imposto"). Atualmente, estou retornando um 400. Mas comecei a me questionar sobre isso. Eu realmente deveria estar retornando um 422? Quero dizer, é JSON (que é suportado) e é válido JSON, apenas não contém todos os campos obrigatórios.

David S
fonte
11
possível duplicata de lazer: erros de aplicativos de mapeamento para códigos de status HTTP
Anirudh Ramanathan

Respostas:

419

400 Solicitação incorreta agora parece ser o melhor código de status HTTP / 1.1 para o seu caso de uso.

No momento da sua pergunta (e da minha resposta original), a RFC 7231 não era uma coisa; Nesse ponto, opus-me 400 Bad Requestporque a RFC 2616 disse (com ênfase minha):

A solicitação não pôde ser entendida pelo servidor devido à sintaxe incorreta .

e a solicitação que você descreve é ​​JSON sintaticamente válido, envolto em HTTP sintaticamente válido e, portanto, o servidor não tem problemas com a sintaxe da solicitação.

No entanto, como apontado por Lee Saferite nos comentários , a RFC 7231, que obsoleta a RFC 2616, não inclui essa restrição :

O código de status 400 (Solicitação incorreta) indica que o servidor não pode ou não processará a solicitação devido a algo que é considerado um erro do cliente (por exemplo, sintaxe de solicitação malformada, enquadramento de mensagem de solicitação inválida ou roteamento de solicitação enganoso).


No entanto, antes dessa reformulação (ou se você quiser discutir sobre o RFC 7231 ser apenas um padrão proposto no momento), 422 Unprocessable Entitynão parece um código de status HTTP incorreto para o seu caso de uso, porque, como diz a introdução ao RFC 4918:

Embora os códigos de status fornecidos pelo HTTP / 1.1 sejam suficientes para descrever a maioria das condições de erro encontradas pelos métodos WebDAV, existem alguns erros que não se enquadram perfeitamente nas categorias existentes. Esta especificação define códigos de status extras desenvolvidos para métodos WebDAV (Seção 11)

E a descrição do422 diz:

O código de status 422 (Entidade não processável) significa que o servidor entende o tipo de conteúdo da entidade solicitada (portanto, um código de status 415 (Tipo de mídia não suportado) é inadequado) e a sintaxe da entidade solicitada está correta (portanto, 400 (Solicitação incorreta) ) código de status é inapropriado), mas não conseguiu processar as instruções contidas.

(Observe a referência à sintaxe; suspeito 7231 parcialmente obsoleto 4918 também)

Isso soa exatamente como a sua situação, mas, para o caso de haver alguma dúvida, continua dizendo:

Por exemplo, essa condição de erro pode ocorrer se um corpo de solicitação XML contiver instruções XML bem formadas (ou seja, sintaticamente corretas), mas semanticamente erradas.

(Substitua "XML" por "JSON" e acho que podemos concordar que essa é a sua situação)

Agora, alguns argumentarão que o RFC 4918 é sobre "Extensões HTTP para criação e versão distribuída na Web (WebDAV)" e que você (presumivelmente) não está fazendo nada que envolva o WebDAV, portanto, não deve usar nada disso.

Dada a escolha entre usar um código de erro no padrão original que explicitamente não cobre a situação, e um de uma extensão que descreve exatamente a situação, eu escolheria o último.

Além disso, a Seção 21.4 da RFC 4918 refere-se ao Registro de Código de Status HTTP (IANA Hypertext Transfer Protocol) , onde 422 podem ser encontrados.

Proponho que seja totalmente razoável que um cliente ou servidor HTTP use qualquer código de status desse registro, desde que o faça corretamente.


Mas a partir do HTTP / 1.1, o RFC 7231 tem tração, então use 400 Bad Request!

Kristian Glass
fonte
5
Sua resposta (422) faz sentido para mim. É também isso que o Rails ( respond_with ) usa quando um recurso não pode ser processado devido a erros de validação.
Tyler Rick
11
Observe o uso de 422 em especificações que não sejam do WebDAV aqui: tools.ietf.org/html/rfc5789#section-2.2
Andrey Shchekin
4
Apenas como uma atualização, o RFC 7231 tem uma descrição diferente para o código de resposta 400 que altera a semântica.
Lee Saferite 01/07/2015
5
Minhas desculpas - atualizei esta resposta para refletir a alteração nas RFCs e perdi alguma clareza; Vou tentar refatorar. É quase certamente seguro de usar 422, mas hoje em dia você deve usar 400.
Kristian Vidro
2
Eu ainda acho que as especificações poderiam ser muito mais claras. Os exemplos dados em são casos claros do cliente fazendo algo errado. A situação do OP também se enquadra nessa categoria. No entanto, há casos como "eu entendo o que você está perguntando, mas me recuso a fazê-lo porque há alguma regra comercial contra isso" não é tão claro. Não é exatamente culpa do cliente, portanto, um 403 pode realmente ser aplicado, de acordo com a mesma especificação: "No entanto, uma solicitação pode ser proibida por motivos não relacionados às credenciais". Eu preferiria ter códigos separados para coisas relacionadas à permissão vs "não pode ser feito" embora.
Thorarin 04/07/19
37

400 Solicitação incorreta é o código de status HTTP adequado para o seu caso de uso. O código é definido pelo HTTP / 0.9-1.1 RFC.

A solicitação não pôde ser entendida pelo servidor devido à sintaxe incorreta. O cliente não deve repetir o pedido sem modificações.

http://tools.ietf.org/html/rfc2616#section-10.4.1

422 Entidade não processável é definida pelo RFC 4918 - WebDav. Observe que há uma pequena diferença em comparação com 400, veja o texto citado abaixo.

Essa condição de erro pode ocorrer se um corpo de solicitação XML contiver instruções XML bem formadas (ou seja, sintaticamente corretas), mas semanticamente erradas.

Para manter a interface uniforme, você deve usar 422 apenas em um caso de respostas XML e também deve suportar todos os códigos de status definidos pela extensão Webdav, não apenas 422.

http://tools.ietf.org/html/rfc4918#page-78

Veja também a publicação de Mark Nottingham sobre códigos de status:

é um erro tentar mapear cada parte do seu aplicativo "profundamente" nos códigos de status HTTP; na maioria dos casos, o nível de granularidade que você deseja buscar é muito mais grosseiro. Em caso de dúvida, não há problema em usar os códigos de status genéricos 200 OK, 400 Solicitação incorreta e 500 Erro de serviço interno quando não houver um ajuste melhor .

Como pensar sobre códigos de status HTTP

filip26
fonte
4
O código 422 faz parte do registro da IANA iana.org/assignments/http-status-codes/http-status-codes.xhtml, portanto, qualquer IMHO não faz sentido. De qualquer forma, a API REST do Facebook e Twitter reinventa códigos próprios e não usa os padrões RFC / IANA. Então você pode fazer.
precisa saber é o seguinte
15
A Seção 11 especifica especificamente que elas são adicionadas a toda a especificação e não apenas dentro da especificação do WebDav:The following status codes are added to those defined in HTTP/1.1 [RFC2616].
Steve Tauber
8
Só porque o código é descrito como parte da especificação do WebDAV não significa que seja específico do WebDAV! Os códigos de status devem ser genéricos.
trate seus mods bem
33

Para refletir o status a partir de 2015:

Comportamentalmente, os códigos de resposta 400 e 422 serão tratados da mesma forma por clientes e intermediários, portanto, na verdade, não é diferença concreta que você use.

No entanto, eu esperaria ver 400 atualmente usados ​​mais amplamente e, além disso, os esclarecimentos fornecidos pelas especificações HTTPbis o tornam o mais apropriado dos dois códigos de status:

  • A especificação HTTPbis esclarece a intenção de 400 de não ser apenas para erros de sintaxe. A frase mais ampla "indica que o servidor não pode ou não processará a solicitação devido a algo que é considerado um erro do cliente" agora é usada.
  • 422 É especificamente uma extensão WebDAV e não é referenciada na RFC 2616 ou na especificação HTTPbis mais recente .

Por contexto, HTTPbis é uma revisão da especificação HTTP / 1.1 que tenta esclarecer áreas que são pouco claras ou inconsistentes. Quando atingir o status aprovado, substituirá o RFC2616.

Tom Christie
fonte
4
O 403 Proibido também não pode ser usado para esse contexto? Citação: O código de status 403 (Proibido) indica que o servidor entendeu a solicitação, mas se recusa a autorizá-la ... Se credenciais de autenticação foram fornecidas na solicitação, o servidor as considera insuficientes para conceder acesso .... No entanto, uma solicitação pode ser proibido por motivos não relacionados às credenciais. Portanto, parece que 403 pode ser usado para rejeitar solicitações fora da autenticação.
precisa saber é o seguinte
11
@garbagecollector observe que "rejeitado por motivos fora das credenciais "! = "rejeitado por motivos fora da autenticação ." Existem várias maneiras de autenticar alguém sem usar credenciais, especificamente.
Knetic
@garbagecollector no, credenciais significa autenticação ("quem é você"), que seria 401 em caso de falha. A autorização ("o que você pode fazer") seria 403 em caso de falha. Explicação completa aqui: stackoverflow.com/a/6937030/137948 Não se aplica à situação "campos ausentes" do OP, porque o erro seria o mesmo, independentemente de qual usuário o tenha tentado. Concordo que 400 é a resposta certa.
Will Sheppard
27

Estudo de caso: API do GitHub

https://developer.github.com/v3/#client-errors

Talvez copiar de APIs conhecidas seja uma boa idéia:

Existem três tipos possíveis de erros de cliente em chamadas de API que recebem corpos de solicitação:

O envio de JSON inválido resultará em uma resposta 400 Solicitação incorreta.

HTTP/1.1 400 Bad Request
Content-Length: 35

{"message":"Problems parsing JSON"}

Enviar o tipo errado de valores JSON resultará em uma resposta 400 Solicitação incorreta.

HTTP/1.1 400 Bad Request
Content-Length: 40

{"message":"Body should be a JSON object"}

O envio de campos inválidos resultará em uma resposta 422 Unprocessable Entity.

HTTP/1.1 422 Unprocessable Entity
Content-Length: 149

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Issue",
      "field": "title",
      "code": "missing_field"
    }
  ]
}
Ciro Santilli adicionou uma nova foto
fonte
Eu acho que essa é a resposta correta e compreensível.
LEMUEL ADANE
11
Não é possível votar mais. Gostaria que respostas mais votadas se referissem a esta. As especificações (RFC, IANA) falharam epicamente em fornecer definições claras e distinção entre os dois. Portanto, a resposta se resume às melhores práticas e o GitHub nos fornece uma.
Alex Klaus
15

Não há resposta correta, pois depende de qual é a definição de "sintaxe" para sua solicitação. O mais importante é que você:

  1. Use o (s) código (s) de resposta de forma consistente
  2. Inclua o máximo possível de informações adicionais no corpo da resposta para ajudar o (s) desenvolvedor (es) usando sua API a descobrir o que está acontecendo. =

Antes que todo mundo pule em cima de mim por dizer que não há resposta certa ou errada aqui, deixe-me explicar um pouco sobre como cheguei à conclusão.

Neste exemplo específico, a pergunta do OP é sobre uma solicitação JSON que contém uma chave diferente do esperado. Agora, o nome da chave recebido é muito semelhante, do ponto de vista da linguagem natural, à chave esperada, mas é estritamente diferente e, portanto, não é (geralmente) reconhecido por uma máquina como equivalente.

Como eu disse acima, o fator decisivo é o que se entende por sintaxe . Se a solicitação foi enviada com um Tipo de Conteúdo de application/json, sim, a solicitação é sintaticamente válida porque é uma sintaxe JSON válida, mas não é semanticamente válida, pois não corresponde ao esperado. (assumindo uma definição estrita do que torna a solicitação em questão semanticamente válida ou não).

Se, por outro lado, a solicitação foi enviada com um Tipo de Conteúdo personalizado mais específico como application/vnd.mycorp.mydatatype+jsonesse, talvez, especifique exatamente quais campos são esperados, então eu diria que a solicitação pode ser facilmente sintaticamente inválida, daí a resposta 400.

No caso em questão, como a chave estava errada, não o valor , ocorreu um erro de sintaxe se houvesse uma especificação para o que são chaves válidas. Se não houvesse especificação para chaves válidas ou o erro estivesse com um valor , seria um erro semântico .

cdeszaq
fonte
Resposta muito subestimada - obrigado pela explicação bem formulada.
puiu
Exatamente meus pensamentos sobre o assunto! Eu venho do background XML SOAP e o conceito de esquema acabou de chegar ao meu sangue e os documentos JSON, em vez de anunciar o esquema. Para mim, é se o servidor "entende" a solicitação ou não. Se o servidor não souber o que é "sales_tax", é simplesmente 400: "Não faço ideia do que você me enviou, mas definitivamente não é o que eu quero".
Aleksander Stelmaczonek
4

422 Entidade não processável explicada Atualizado em: 6 de março de 2017

O que é a entidade 422 não processável?

Um código de status 422 ocorre quando uma solicitação é bem formada, no entanto, devido a erros semânticos, ela não pode ser processada. Esse status HTTP foi introduzido na RFC 4918 e é mais especificamente voltado para extensões HTTP para Web Distributed Authoring and Versioning (WebDAV).

Existe alguma controvérsia por aí sobre se os desenvolvedores devem ou não devolver um erro 400 vs 422 aos clientes (mais sobre as diferenças entre os dois status abaixo). No entanto, na maioria dos casos, é acordado que o status 422 só deve ser retornado se você suportar os recursos do WebDAV.

Uma definição palavra por palavra do código de status 422 retirado da seção 11.2 na RFC 4918 pode ser lida abaixo.

O código de status 422 (Entidade não processável) significa que o servidor entende o tipo de conteúdo da entidade solicitada (portanto, um código de status 415 (Tipo de mídia não suportado) é inadequado) e a sintaxe da entidade solicitada está correta (portanto, 400 (Solicitação incorreta) ) código de status é inapropriado), mas não conseguiu processar as instruções contidas.

A definição continua a dizer:

Por exemplo, essa condição de erro pode ocorrer se um corpo de solicitação XML contiver instruções XML bem formadas (ou seja, sintaticamente corretas), mas semanticamente erradas.

Códigos de status 400 vs 422

Erros de solicitação incorretos usam o código de status 400 e devem ser retornados ao cliente se a sintaxe da solicitação estiver malformada, contiver enquadramento de mensagem de solicitação inválida ou se houver roteamento de solicitação enganoso. Esse código de status pode parecer bastante semelhante ao status da entidade 422 não processável, no entanto, uma pequena informação que os distingue é o fato de que a sintaxe de uma entidade solicitante para um erro 422 está correta, enquanto a sintaxe de uma solicitação que gera um número 400 erro está incorreto.

O uso do status 422 deve ser reservado apenas para casos de uso muito particulares. Na maioria dos outros casos em que ocorreu um erro do cliente devido à sintaxe malformada, o status 400 Bad Request deve ser usado.

https://www.keycdn.com/support/422-unprocessable-entity/

Clojurevangelist
fonte
1

Seu caso: HTTP 400 é o código de status correto para o seu caso da perspectiva REST, pois é sintaticamente incorreto para enviar em sales_taxvez de tax, embora seja um JSON válido. Isso normalmente é imposto pela maioria das estruturas do lado do servidor ao mapear o JSON para objetos. No entanto, existem algumas implementações REST que ignoram novas keyno objeto JSON. Nesse caso, uma content-typeespecificação personalizada para aceitar apenas campos válidos pode ser aplicada pelo lado do servidor.

Cenário ideal para 422:

Em um mundo ideal, 422 é preferível e geralmente aceitável para enviar como resposta se o servidor entender o tipo de conteúdo da entidade solicitante e a sintaxe da entidade solicitante estiver correta, mas não puder processar os dados porque são semanticamente errôneos.

Situações de 400 a mais de 422:

Lembre-se, o código de resposta 422 é um código de status HTTP estendido (WebDAV). Ainda existem alguns clientes HTTP / bibliotecas de front-end que não estão preparados para lidar com 422. Para eles, é tão simples quanto "HTTP 422 está errado, porque não é HTTP" . Da perspectiva do serviço, 400 não é muito específico.

Na arquitetura corporativa, os serviços são implantados principalmente em camadas de serviço como SOA, IDM etc. Eles geralmente atendem a vários clientes, desde um cliente nativo muito antigo até os clientes HTTP mais recentes. Se um dos clientes não manipular o HTTP 422, as opções são pedir ao cliente para atualizar ou alterar seu código de resposta para HTTP 400 para todos. Na minha experiência, isso é muito raro atualmente, mas ainda é uma possibilidade. Portanto, sempre é necessário um estudo cuidadoso da sua arquitetura antes de decidir sobre os códigos de resposta HTTP.

Para lidar com situações como essas, as camadas de serviço normalmente usam versioningou configurationsinalizam a configuração para que clientes estritos de conformidade com HTTP enviem 400 e 422 para o restante deles. Dessa forma, eles fornecem suporte de compatibilidade com versões anteriores para os consumidores existentes, mas ao mesmo tempo fornecem a capacidade para os novos clientes consumirem o HTTP 422.


A atualização mais recente do RFC7321 diz:

The 400 (Bad Request) status code indicates that the server cannot or
   will not process the request due to something that is perceived to be
   a client error (e.g., malformed request syntax, invalid request
   message framing, or deceptive request routing).

Isso confirma que os servidores podem enviar HTTP 400 por solicitação inválida. 400 não se refere mais apenas a erros de sintaxe ; no entanto, 422 ainda é uma resposta genuína, desde que os clientes possam lidar com isso.

YuVi
fonte
1

Em primeiro lugar, esta é uma pergunta muito boa.

400 Solicitação incorreta - Quando uma informação crítica está ausente da solicitação

por exemplo, o cabeçalho da autorização ou o cabeçalho do tipo de conteúdo. O que é absolutamente exigido pelo servidor para entender a solicitação. Isso pode diferir de servidor para servidor.

422 Entidade não processável - quando o corpo da solicitação não pode ser analisado.

Isso é menos grave que 400. A solicitação chegou ao servidor. O servidor reconheceu que a solicitação acertou na estrutura básica. Mas as informações no corpo da solicitação não podem ser analisadas ou entendidas.

por exemplo Content-Type: application/xml quando o corpo da solicitação é JSON.

Aqui está um artigo que lista os códigos de status e seu uso nas APIs REST. https://metamug.com/article/status-codes-for-rest-api.php


fonte
5
422 significa que a sintaxe é válida, mas o conteúdo não é. Enviar JSON onde XML é esperado significa que a sintaxe está incorreta; portanto, 400 é a resposta correta nesse caso.
Dirk
11
Exatamente como Dirk referido pedido 422 meios sintaticamente válido (pode ser analisado e entendido) mas semanticamente inválido
Jacek Obarymski
400: quando a solicitação não pode ser processada devido a sintaxe inválida (por exemplo, erro de análise); 422: quando a solicitação não pode ser processada devido a dados inválidos (por exemplo, erro de validação).
Kitanotori 23/08/19
Seu exemplo para 422 não é válido porque, enviando json com um tipo de mídia application / xml, o corpo automaticamente está sintaticamente incorreto e a resposta deve ser 400.
manemarron
-15

Você realmente deve retornar "200 OK" e, no corpo da resposta, incluir uma mensagem sobre o que aconteceu com os dados publicados. Cabe ao seu aplicativo entender a mensagem.

O problema é que os códigos de status HTTP são exatamente isso - códigos de status HTTP. E isso deve ter significado apenas na camada de transporte, não na camada de aplicação. A camada do aplicativo realmente nunca deve saber que o HTTP está sendo usado. Se você alternou sua camada de transporte de HTTP para Homing Pigeons, isso não deve afetar sua camada de aplicativo de forma alguma.

Deixe-me dar um exemplo não virtual. Digamos que você se apaixone por uma garota e ela te ama de volta, mas sua família se muda para um país completamente diferente. Ela fornece seu novo endereço de correio tradicional. Naturalmente, você decide enviar-lhe uma carta de amor. Então você escreve sua carta, coloca-a em um envelope, escreve o endereço dela no envelope, coloca um carimbo nele e envia. Agora vamos considerar esses cenários

  1. Você esqueceu de escrever o nome da rua. Você receberá uma carta fechada com uma mensagem escrita dizendo que o endereço está incorreto. Você estragou a solicitação e a agência postal receptora não pode lidar com isso. É o equivalente a receber "400 solicitações incorretas".
  2. Então você fixa o endereço e envia a carta novamente. Mas, devido a alguma má sorte, você digitou errado o nome da rua. Você receberá a carta novamente com uma mensagem dizendo que o endereço não existe. É o equivalente a receber "404 não encontrado".
  3. Você corrige o endereço novamente e, desta vez, consegue escrever o endereço corretamente. Sua garota recebe a carta e escreve de volta. É o equivalente a receber "200 OK". No entanto, isso não significa que você gostará do que ela escreveu em sua carta. Significa simplesmente que ela recebeu sua mensagem e tem uma resposta para você. Até você abrir o envelope e ler a carta dela, você não pode saber se ela sente muito a sua falta ou quer terminar com você.

Resumindo: retornar "200 OK" não significa que o aplicativo do servidor tenha boas notícias para você. Significa apenas que tem algumas novidades.

PS: O código de status 422 tem um significado apenas no contexto do WebDAV. Se você não estiver trabalhando com o WebDAV, 422 terá exatamente o mesmo significado padrão que qualquer outro código não padrão = que não é nenhum.

GoFree
fonte