Devo retornar um status HTTP 400 (Solicitação incorreta) se um parâmetro estiver sintaticamente correto, mas violar uma regra de negócios?


56

Digamos que eu tenho um ponto de extremidade REST que usa um número inteiro como parâmetro:

/makeWaffles?numberOfWaffles=3

Nesse caso, quero que o número seja positivo, porque não posso fazer um número negativo de waffles (e solicitar 0 waffles é uma perda de tempo). Então, eu quero rejeitar qualquer solicitação que não contenha um número inteiro positivo. Também quero rejeitar uma solicitação que exceda um número inteiro máximo (digamos que agora seja MAX_INTEGER).

No caso de alguém solicitar um número não positivo de waffles, devo retornar um status HTTP 400 (Solicitação incorreta)? Meu pensamento inicial é sim: não é um número válido para mim concluir a solicitação. No entanto, o RFC não menciona regras de negócios como um motivo para lançá-lo:

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 é percebido como 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).

Uma regra de negócios não se enquadra em nenhum desses três exemplos. É sintaticamente correto, está emoldurado corretamente e não é um roteamento de solicitação enganoso.

Portanto, devo retornar um status HTTP 400 (Solicitação incorreta) se um parâmetro estiver sintaticamente correto, mas violar uma regra de negócios? Ou existe um status mais apropriado para retornar?



Respostas:


38

Essa é uma ótima pergunta, e ainda altamente relevante, dado o contexto histórico (e as definições aparentemente contraditórias) dos códigos de retorno HTTP. Mesmo entre as respostas a esta pergunta há definições conflitantes. Isso pode ser esclarecido movendo-se cronologicamente.

RFC 2616 (junho de 1999)

10.4.1 400 Solicitação incorreta

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.

A partir deste RFC, esse código de status aplicava-se especificamente apenas a solicitações sintaticamente inválidas. Houve uma lacuna nos códigos de status para validação semântica. Assim, quando a RFC 4918 apareceu, um novo código nasceu.

RFC 4918 (junho de 2007)

11.2 422 Entidade não processável

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) é inapropriado) e a sintaxe da entidade solicitada está correta (portanto, 400 (Solicitação incorreta) ) código de status é inadequado), mas não conseguiu processar as instruções contidas. 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.

422 Entidade não processável foi criada para preencher a lacuna da validação semântica na especificação original dos códigos de status 4xx. No entanto, outra RFC relevante surgiu em 2014, que generalizou 400 para não ser mais específica à sintaxe .

RFC 7231 (junho de 2014, obsoleta explicitamente a RFC 2616)

6.5.1 400 Solicitação incorreta

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 é percebido como 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).

Observe que a descrição 422 diz que o motivo 400 é inapropriado porque 400 (a partir da RFC 2616) deve ser retornado apenas para sintaxe de solicitação incorreta. No entanto, a partir da RFC 7231, a definição estrita de erro de sintaxe não se aplica mais a 400 .

Voltando à pergunta em questão: Embora o 422 seja tecnicamente mais específico, nesse contexto, pude ver 400 ou 422 sendo usados ​​para validação semântica dos parâmetros da API. Eu hesito em usar 422 em minhas próprias APIs porque a definição de 422 está tecnicamente desatualizada neste momento (embora eu não saiba se isso é oficialmente reconhecido em qualquer lugar). O artigo mencionado na resposta de Fran, que incentiva o uso do 422, foi escrito em 2012, dois anos antes da RFC 7231 esclarecer o HTTP 400. Certifique-se de padronizar um ou outro.


42

Eu li a primeira resposta e realmente não concordo com isso porque, pelo menos na minha leitura, uma solicitação ruim (400) significa: "Eu não posso nem lidar com sua solicitação porque algo está fundamentalmente errado". E eu encontrei este post que justifica o retorno de um 422.

da IETF

422 Entidade não processável (WebDAV; RFC 4918) A solicitação foi bem formada, mas não pôde ser seguida devido a erros semânticos

Parece uma resposta mais apropriada, pois sua solicitação é bem-formada, mas não passa nas regras de validação.


5
Ouvi isso descrito como "400 significa má sintaxe, 422 significa má semântica".
Cbojar

33
Todos os códigos x00 são códigos genéricos "pegar todos". Um 400 não é inapropriado , apenas menos específico .
Jack

11
Boa resposta, mas a resposta dada pelo @GoFree faz mais sentido para mim.
Ewerton

2
Existe um argumento muito forte para o retorno de códigos que todos conhecem. Absolutamente todo mundo precisará procurar 422, e aposto que a maioria ainda não saberá o que fazer com isso.
26418 sylvanaar

9

Não você não deveria. Os códigos HTTP destinam-se à camada HTTP do seu aplicativo. As regras de negócios têm uma camada completamente diferente e são específicas do aplicativo, portanto, você precisa criar seu próprio "protocolo".

Imagine um apocalipse e você precisa mudar do protocolo HTTP para usar o Pigeons. Os pombos não têm códigos de retorno, portanto, você precisará alterar sua camada de negócios para acomodar isso. Mas sua empresa realmente não mudou de forma alguma, portanto você não precisa alterar a camada de negócios. Ele mostra um forte acoplamento entre essas duas camadas (transporte e negócios).

Voltar à pergunta: O que você deve fazer é retornar "200 OK" com um corpo que descreva o que aconteceu com a solicitação. A especificação diz claramente isso:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1 .

200 OK

A solicitação foi bem sucedida. As informações retornadas com a resposta dependem do método usado na solicitação , por exemplo

POST uma entidade que descreve ou contém o resultado da ação;

Sua solicitação HTTP foi bem-sucedida? Sim, o servidor da web sabe o que fazer com essa solicitação (por exemplo, repasse para a parte do servidor do seu aplicativo). O servidor da Web passa essa solicitação para a parte do servidor do seu aplicativo, que recebe os dados POST, os processa (os valida no seu caso) e retorna uma resposta normal (no corpo de uma resposta HTTP) para a parte do cliente do seu aplicativo . Esta resposta da parte do servidor do aplicativo pode ser "Ótimo, os dados que você me enviou são válidos" ou "Sinto muito, os dados que você enviou não são válidos". E cabe ao seu cliente parte do aplicativo entender o que significa a resposta.

PS: "400 Solicitação incorreta" significa que o servidor da Web não entendeu o que você deseja dele. Isso significa que a parte do servidor do seu aplicativo nem sequer recebeu a solicitação. Ou pelo menos é isso que significa :-)

EDIT : Acabei de perceber, que você está fazendo solicitação GET, não POST. Essa é uma péssima idéia, pois GET não deve alterar o estado do aplicativo. GET deve simplesmente recuperar dados do servidor. Mas, na sua solicitação, você está realmente alterando o estado do aplicativo, portanto, você deve realmente usar o POST.


11
Sim, retornar 404 nesse caso é bom. Não estou dizendo que o servidor sempre deve enviar 200 OK com uma explicação no corpo.
GoFree

Melhor explicação que eu vi até agora. Eu tenho essa mesma pergunta e parece que toda a palavra pensa differente de mim e você @GoFree
Ewerton

@GoFree Esta é uma resposta muito boa para repensar o design da API. Mas não é o caso, que usamos HTTP e seu código de resposta como parte eminente da camada de regras de negócios quando usamos uma API REST?
Thomas Lauria

11
@ Thomas Lauria Ainda não vi uma implementação adequada da API RESTFUL. No entanto, hoje a API REST é uma palavra de ordem, então toda empresa precisa usá-la (a palavra, não a tecnologia) sem realmente entender o conceito por trás dela. Então, sim, está sendo usado de maneira errada em todos os lugares. O que os programadores geralmente criam não é uma API REST, mas uma API HTTP ou API OVER HTTP. Na verdade, uma das poucas boas implementações RESTFUL é o próprio HTTP :)
GoFree 15/02

11
Usar 200-OK é especialmente lógico se o aplicativo incluir um campo "erro" no corpo da resposta para descrever erros no nível de negócios, como valor de entrada muito alto ou muito baixo ou ausente, produto em falta etc.
Roland

8

Sim, a entrada que não segue o contrato implícito do nó de extremidade é "algo percebido como um erro do cliente" e deve retornar 400.

As exceções são se a regra de negócios estiver relacionada à segurança (então 401 Unauthorizedou 403 Forbiddenseria melhor). Como alternativa, se enviar um 400 vazasse informações sobre a existência de algo e, em seguida, a 404 Not Foundpoderá ser mais apropriado.


-3

Não temos certeza de que todos concordariam, mas estamos usando o 409 - Conflict. Muitos afirmam que o 409 é mais um conflito com o estado do sistema, mas aceitamos a interpretação de que um conflito de valores de dados fora do intervalo aceito é corrigível pelo solicitante e um uso aceitável de 409. 422 Eu acho que seria razoável conforme a solicitação está formado corretamente, mas não pode ser processado conforme solicitado. Opino no entanto, se você não deseja implementar uma série de respostas, apenas dar 400 ainda é aceitável.


5
409 significa "o estado em que você está tentando colocar isso está em conflito com o estado em que outro cliente está tentando colocar isso", é para bloquear gravações simultâneas (usando ETags, por exemplo)
Jack
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.