Erro de API REST retorna boas práticas [fechado]

623

Estou procurando orientação sobre boas práticas quando se trata de retornar erros de uma API REST. Estou trabalhando em uma nova API para que eu possa tomar qualquer direção no momento. Meu tipo de conteúdo é XML no momento, mas pretendo oferecer suporte a JSON no futuro.

Agora estou adicionando alguns casos de erro, como por exemplo, um cliente tenta adicionar um novo recurso, mas excedeu sua cota de armazenamento. Já estou lidando com certos casos de erro com códigos de status HTTP (401 para autenticação, 403 para autorização e 404 para URIs de solicitação incorreta). Examinei os abençoados códigos de erro HTTP, mas nenhum do intervalo 400-417 parece certo para relatar erros específicos de aplicativos. Então, no começo, fiquei tentado a retornar meu erro de aplicativo com 200 OK e uma carga XML específica (ou seja, pague-nos mais e você obterá o armazenamento de que precisa!), Mas parei para pensar sobre isso e parece que está ensaboado (/ encolher de ombros horrorizado). Além disso, parece que estou dividindo as respostas de erro em casos distintos, pois alguns são baseados no código de status http e outros são direcionados ao conteúdo.

Então, quais são as recomendações da indústria? Boas práticas (explique o porquê!) E também, de um cliente pov, que tipo de tratamento de erros na API REST facilita a vida do código do cliente?

Remus Rusanu
fonte
7
Apenas para esclarecer: não estou muito interessado em qual código de status HTTP específico retornar, mas se é uma boa prática REST combinar erros de carga útil com códigos de status HTTP ou é melhor confiar apenas na carga útil.
Remus Rusanu
3
O Manual de Design da API REST aborda esse tópico muito bem.
Remus Rusanu
12
A pergunta não pede opinião, mas orientações / recomendações e deve ser reaberta e usada como referência. Qual foi o ponto de perto em 2016 a questão, que foi criado em 2009, tem mais de 400 votos e nenhum de respostas existentes com base em opiniões
Michael Freidgeim
4
A maioria não mencionou, mas o uso dos códigos de erro HTTP pode levar a problemas relacionados à principal causa de um problema. HTTP é o protocolo de transporte e um 404 deve indicar que houve um problema com o nível de transporte URLon (por exemplo, caminho errado). Se o aplicativo não puder encontrar um conjunto de dados por seu ID, este é um erro no nível do aplicativo (não um erro no nível do transporte) e um 404, conforme sugerido por usuários tranqüilos do código de status http, pode levar a uma conclusão errada. Geralmente, não gosto da mistura de transporte e camada de aplicação ao usar os códigos de status.
SCI

Respostas:

220

Então, no começo, fiquei tentado a retornar meu erro de aplicativo com 200 OK e uma carga XML específica (ou seja, pague-nos mais e você obterá o armazenamento de que precisa!), Mas parei para pensar sobre isso e parece que está ensaboado (/ encolher de ombros horrorizado).

Eu não retornaria 200, a menos que realmente não houvesse nada de errado com a solicitação. De RFC2616 , 200 significa "a solicitação foi bem-sucedida".

Se a cota de armazenamento do cliente tiver sido excedida (por qualquer motivo), eu retornaria 403 (Proibido):

O servidor entendeu a solicitação, mas está se recusando a atendê-la. A autorização não ajudará e a solicitação NÃO DEVE ser repetida. Se o método de solicitação não foi HEAD e o servidor deseja tornar público o motivo pelo qual a solicitação não foi atendida, DEVE descrever o motivo da recusa na entidade. Se o servidor não desejar disponibilizar essas informações ao cliente, o código de status 404 (Não encontrado) poderá ser usado.

Isso informa ao cliente que a solicitação foi OK, mas que falhou (algo que um 200 não faz). Isso também oferece a oportunidade de explicar o problema (e sua solução) no corpo da resposta.

Que outras condições de erro específicas você tinha em mente?

Rich Apodaca
fonte
6
Devo incluir minha mensagem de erro detalhada no corpo, ou seja. um par de código / string XML? Como os clientes lidam melhor com isso? Por exemplo, eu sei que os clientes baseados em WebRequest em C # lançariam 'Bad Request' ou 'Forbidden' e não forneceriam o corpo da resposta.
Remus Rusanu
18
O corpo de um 403 "deve" conter os detalhes do erro. Se um cliente está preparado para usar as informações é outra história. Faz mais sentido que esse formato seja igual ao formato para todas as outras cargas úteis (por exemplo, XML, JSON).
Rich Apodaca
1
... e se os detalhes não forem retornados no 403, um 404 "pode" ser usado (mas não parece a melhor opção para mim).
Rich Apodaca
6
A opção 404 é para o evento em que um 403 possa revelar detalhes sobre o aplicativo que você não deseja que usuários não autorizados - se um usuário não administrativo atingir um URL somente para administrador, por exemplo, talvez não queira esse usuário saber que é um URL válido para administradores, etc. Nesse caso, porém, o 403 é totalmente apropriado.
Greg Campbell
16
Eu sinto que esta é uma resposta bastante inútil. Eu teria pensado que o aspecto mais importante é se os status devem ser usados ​​apenas ou se as informações de erro devem ser retornadas na carga útil, ou ambas, etc. E então COMO a informação deve ser adicionada na carga útil. O status específico usado é aprimorando apenas um aspecto específico da pergunta.
Manachi 26/02
584

Um ótimo recurso para escolher o código de erro HTTP correto para sua API: http://www.codetinkerer.com/2015/12/04/choosing-an-http-status-code.html

Um trecho do artigo:

Onde começar:

insira a descrição da imagem aqui

2XX / 3XX:

insira a descrição da imagem aqui

4XX:

insira a descrição da imagem aqui

5XX:

insira a descrição da imagem aqui

Omar Ali
fonte
1
422 É especificamente uma extensão WebDAV. Eu acho que não deveria estar aqui.
1213 Mario Mario
@Mario É idiomático nas APIs do Ruby on Rails retornar 422 em resposta às condições especificadas aqui. Muitas coisas boas seguindo essa abordagem já. Para que você substituiria os usos do 422?
Kelsey Hannan
regular old 400
Andbdrew
Obrigado. O que significa "Você está deixando a Internet com raiva?"?
RoutesMaps.com
@ Crimean.us google.com/search?q=define+rage-quit
Omar Ali
87

A principal opção é que você deseja tratar o código de status HTTP como parte da sua API REST ou não.

Ambas as formas funcionam bem. Concordo que, estritamente falando, uma das idéias do REST é que você use o código Status HTTP como parte da sua API (retorne 200 ou 201 para uma operação bem-sucedida e 4xx ou 5xx, dependendo de vários casos de erro). , não há polícia REST. Você pode fazer o que você quiser. Eu já vi APIs não REST muito mais flagrantes sendo chamadas "RESTful".

Neste ponto (agosto de 2015), recomendo que você use o código de status HTTP como parte da sua API. Agora é muito mais fácil ver o código de retorno ao usar estruturas do que era no passado. Em particular, agora é mais fácil ver o caso de retorno que não é de 200 e o corpo de respostas que não são de 200 do que no passado.

O código de status HTTP faz parte da sua API

  1. Você precisará escolher cuidadosamente códigos 4xx que atendam às suas condições de erro. Você pode incluir uma mensagem de descanso, xml ou texto sem formatação como a carga útil que inclui um subcódigo e um comentário descritivo.

  2. Os clientes precisarão usar uma estrutura de software que permita obter o código de status no nível HTTP. Geralmente capaz, nem sempre direto.

  3. Os clientes terão que distinguir entre códigos de status HTTP que indicam um erro de comunicação e seus próprios códigos de status que indicam um problema no nível do aplicativo.

O código de status HTTP NÃO faz parte da sua API

  1. O código de status HTTP sempre será 200 se seu aplicativo recebeu a solicitação e respondeu (casos de sucesso e erro)

  2. TODAS as suas respostas devem incluir informações sobre "envelope" ou "cabeçalho". Normalmente algo como:

    envelope_ver: 1.0
    status: # use os códigos que desejar. Reserve um código para o sucesso.
    msg: "ok" # Uma sequência humana que reflete o código. Útil para depuração.
    data: ... # Os dados da resposta, se houver.
  3. Esse método pode ser mais fácil para os clientes, pois o status da resposta está sempre no mesmo local (sem subcódigos necessários), sem limites nos códigos, sem necessidade de buscar o código de status no nível HTTP.

Aqui está um post com uma ideia semelhante: http://yuiblog.com/blog/2008/10/15/datatable-260-part-one/

Questões principais:

  1. Certifique-se de incluir números de versão para poder alterar posteriormente a semântica da API, se necessário.

  2. Documento...

Larry K
fonte
8
Ty. Opção 2 parece como o sabão em roupas de descanso embora ...
Remus Rusanu
138
Não, encapsular tudo através de um 200 não é tranquilo. Impede que os intermediários entendam o resultado de uma operação, o que mata qualquer forma de armazenamento em cache, oculta a semântica da operação e impõe a compreensão do conteúdo da mensagem para processar um erro, violando a restrição de mensagens independentes.
SerialSeb
13
O retorno de detalhes de erro com 200 pode não ser RESTful, mas, mesmo assim, é uma resposta útil (se você ignorar a observação "Os dois caminhos são tranquilos") ... O ponto mais importante pode ser que uma API RESTful pode não ser a melhor opção para o OP.
MB.
3
Parece haver um entendimento geral de que você pode fazer o que quiser com o protocolo HTTP e ainda ser "RESTy", isso é falso. Use o protocolo para o que está escrito, essa é uma das idéias principais do REST. Portanto, o código de status deve fazer parte do seu protocolo.
Ariel M.
O objetivo dos códigos de status é fornecer uma linguagem comum de entendimento entre diversas linguagens de programação, estruturas e abordagens. Os significados do código de status são quase universais: seu corpo personalizado - que inerentemente adiciona mais complexidade por meio da sintaxe personalizada que os consumidores da API precisam aprender - não é.
Kelsey Hannan
40

Lembre-se de que existem mais códigos de status do que os definidos nas RFCs HTTP / 1.1. O registro da IANA está em http://www.iana.org/assignments/http-status-codes . Para o caso que você mencionou, o código de status 507 parece correto.

Julian Reschke
fonte
3
Hmm, embora, à primeira vista, "507 Insufficient Storage" pareça ser apropriado, eu desconfio de usá-lo, pois ele se destina a uma extensão WebDAV (bastante específica) e não a um geral "ei, você está sem espaço" exceção. Ainda assim, suponho que você possa usá-lo.
Max
1
Não, não é específico para WebDAV. Há uma razão pela qual existe um registro para códigos de status HTTP.
Julian Reschke
26
Não concordo com 507esse propósito. Minha interpretação 507é que o servidor está sem espaço, não que a conta esteja sem espaço.
22313 Patrick
12
Eu concordo com o Patrick. 5xxerros são para erros relacionados ao servidor.
Sean
10
418: "Eu sou um bule de chá", implicando que o espaço de armazenamento é muito pequeno (como um bule de chá é pequeno) e não grande e, portanto, está sem espaço.
precisa saber é o seguinte
22

Como outros já apontaram, ter uma entidade de resposta em um código de erro é perfeitamente permitido.

Lembre-se de que os erros 5xx são do lado do servidor, ou seja, o cliente não pode alterar nada em sua solicitação para fazer com que a solicitação seja aprovada. Se a cota do cliente for excedida, isso definitivamente não é um erro do servidor, portanto, 5xx deve ser evitado.

SerialSeb
fonte
Eu discordo. A cota excedida seria um erro do servidor (5xx) porque: A solicitação do cliente é válida e teria sido bem-sucedida se estivesse dentro da cota, o que exclui as 400 séries.
Mikek3332002
4
Mas o servidor não fez nada de errado.
Charlie Schliesser
19

Existem dois tipos de erros. Erros de aplicativo e erros de HTTP. Os erros de HTTP servem apenas para informar ao seu manipulador AJAX que tudo correu bem e não deve ser usado para mais nada.

5xx erro de servidor

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates (RFC 2295 )
507 Insufficient Storage (WebDAV) (RFC 4918 )
509 Bandwidth Limit Exceeded (Apache bw/limited extension)
510 Not Extended (RFC 2774 )

2xx Success

200 OK
201 Created
202 Accepted
203 Non-Authoritative Information (since HTTP/1.1)
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status (WebDAV)

No entanto, a maneira como você cria os erros do aplicativo depende de você. O Estouro de Pilha, por exemplo, envia um objeto com response, datae messagepropriedades. A resposta que acredito conter trueou falseindicar se a operação foi bem-sucedida (geralmente para operações de gravação). Os dados contêm a carga útil (geralmente para operações de leitura) e a mensagem contém metadados adicionais ou mensagens úteis (como mensagens de erro quando responsehouver false).

aleemb
fonte
2
400 também é útil para indicar um problema no aplicativo cliente.
dolmen
19

Sei que é extremamente tarde para a festa, mas agora, no ano de 2013, temos alguns tipos de mídia para cobrir o tratamento de erros de uma maneira distribuída (RESTful) comum. Consulte "vnd.error", application / vnd.error + json ( https://github.com/blongden/vnd.error ) e "Detalhes do problema para APIs HTTP", application / problem + json ( https: // tools. ietf.org/html/draft-nottingham-http-problem-05 ).

Jørn Wildt
fonte
2
Obrigado pelos links. draft-Nottingham-http-problema é agora um padrão proposto: datatracker.ietf.org/doc/rfc7807
seanf
9

Acordado. A filosofia básica do REST é usar a infraestrutura da web. Os códigos de status HTTP são a estrutura do sistema de mensagens que permite que as partes se comuniquem sem aumentar a carga útil do HTTP. Eles já são códigos universais estabelecidos que transmitem o status da resposta e, portanto, para serem verdadeiramente RESTful, os aplicativos devem usar essa estrutura para comunicar o status da resposta.

Enviar uma resposta de erro em um envelope HTTP 200 é enganoso e força o cliente (consumidor da API) a analisar a mensagem, provavelmente de maneira não padronizada ou proprietária. Isso também não é eficiente - você forçará seus clientes a analisar a carga HTTP toda vez que entender o status de resposta "real". Isso aumenta o processamento, adiciona latência e cria um ambiente para o cliente cometer erros.

Kingz
fonte
3
Se você tem uma resposta bem-sucedida ou uma resposta de falha, provavelmente analisará a resposta. Se for um erro, você deseja analisá-lo para obter a mensagem de erro. As respostas de erro são geralmente pequenas e rápidas de analisar. Acho que não devemos nos preocupar em tentar otimizar para evitar a análise de respostas a erros. Você jogaria fora a resposta de erro sem analisá-la? Imprudente na minha opinião.
AgilePro 16/09
3
Se você receber um OK 200, poderá optar por não analisá-lo também, dependendo das regras de negócios. A questão não é se a analisamos o tempo todo ou não. O ponto é a intenção - qual é a intenção de 200 OK? Você está danificando a intenção enviando mensagens de erro agrupadas em 200 OK.
Kingz
1
"qual é a intenção de 200 OK?" - indicando o sucesso da camada de transporte. A solicitação foi recebida e respondida com êxito; havia apenas um problema específico do aplicativo que não tinha nada a ver com HTTP. +++ Ao contrário: enviar 404 no mundo REST significa que algo não foi encontrado, talvez o URL esteja errado ou o recurso a ser processado ou qualquer outra coisa não encontrada. Sem analisar a mensagem, você não pode. IMHO REST é apenas camadas conflitantes.
maaartinus
Conflação é a norma. Ele fornece uma sintaxe para lidar com a sua linha de raciocínio e libera você para se concentrar na camada de negócios. Concordou com o status de transporte mais tarde - esse era o objetivo em primeiro lugar - o REST não foi inventado / proposto simultaneamente com o HTTP - veio mais tarde e simplesmente decidiu usar a infraestrutura existente para representar os ESTADOS e suas ALTERAÇÕES.
Kingz
5

Por favor, atenha-se à semântica do protocolo. Use 2xx para respostas bem-sucedidas e 4xx, 5xx para respostas de erro - sejam suas exceções comerciais ou outras. Se o uso do 2xx para qualquer resposta fosse o caso de uso pretendido no protocolo, eles não teriam outros códigos de status em primeiro lugar.

rahil008
fonte
3

Não se esqueça dos erros 5xx, bem como dos erros de aplicativos.

Nesse caso, o que dizer de 409 (Conflito)? Isso pressupõe que o usuário possa resolver o problema excluindo os recursos armazenados.

Caso contrário, 507 (não totalmente padrão) também pode funcionar. Eu não usaria 200, a menos que você use 200 para erros em geral.

Kathy Van Stone
fonte
-2

Se a cota do cliente for excedida, é um erro do servidor, evite 5xx nesta instância.

anuidade fixa
fonte
3
Por que evitar os erros da série 5xx quando se trata de erros do servidor?
Mikek3332002
7
'quota de cliente excedida' não é um erro de servidor, é uma restrição de cliente e deve estar abaixo de 4xx.
MyGGaN