Comments (10)
Bem legal, ter esta tarefa para padronizar! criar algo inicial para ir modelando o lançamento e tratamento de erros.
Eu gostaria de apresentar aqui uma linha um pouco relacionado com isto, mas é mais abrangente, é o OpenAPI que tambem tem seu estilo de exibir os erros.
Por exemplo,
Vamos dizer que ao tentar obter uma Notícia via ID. E que este ID não existe na base:
- A camada de serviço pode lançar um DoesntExistError
- A camada de API captura e transforma em um 404 como uma mensagem amigável.
{
"detail": "Tabnews ID: 42 not found!",
"status": 404,
"title": "Not Found",
"type": "...."
}
Eu tentei criar uma versão bem inicial do OpenAPI para o tabnews, pensando mais nos status_code e input/output.
Segue abaixo:
- Versão para visualização (HEROKU): https://tabnewspy.herokuapp.com/api/ 🚀
- Tem os endpoints para milestone 2/3
## Validate it at: https://apitools.dev/swagger-parser/online/
openapi: 3.0.2
info:
version: 0.1.0
title: Tabnews (side project) API Backend
description: API and database for auth, users and news
contact:
name: Tabnews
email: [email protected]
url: https://tabnews-web.vercel.app/
servers:
- url: https://tabnewspy.herokuapp.com/api/
description: Development
paths:
/api/version:
get:
operationId: api.api_version
summary: Returns the API version
tags:
- Status
responses:
200:
description: Success
/api/auth/login:
post:
operationId: api.auth.login
summary: User login to get a JWT Token
tags:
- Auth
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- email
- password
properties:
email:
type: string
example: [email protected]
password:
type: string
example: "@bC1234"
responses:
200:
description: JWT Access Token
content:
application/json:
schema:
type: object
properties:
user:
$ref: "#/components/schemas/User"
token:
type: string
example: Encripted.JWT.Token
refresh_token:
type: string
example: Another.Encripted.JWT.Token.With.Long.Expiration
400:
description: Bad request. You must send an email and password
401:
description: Email or password is not valid
/api/auth/github/login:
get:
operationId: api.auth.github_login
description: Login github
tags:
- Auth
responses:
302:
description: Redirect to the authorization
/api/auth/github/authorize:
get:
operationId: api.auth.github_authorize
description: Token
tags:
- Auth
responses:
302:
description: Redirect to the frontend
/api/tabnews:
get:
operationId: api.tabnews.list_tabnews
summary: Returns the latest tabnews
tags:
- Tabnews
responses:
200:
description: The lastest Tabnews
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Tabnews"
post:
operationId: api.tabnews.create_tabnews
summary: Create a new Tabnews
tags:
- Tabnews
security:
- jwtAuth: [tabnews:create]
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- title
properties:
title:
type: string
example: 101 facts that prove the Earth is flat
minLength: 12
description:
type: string
example: Despite being a maiority, in absolute terms, few people know the real truth...
responses:
201:
description: Tabnews created succesfully
content:
application/json:
schema:
$ref: "#/components/schemas/Tabnews"
400:
description: Invalid data to create a Tabnews
401:
description: No Authorization
403:
description: No Permission
components:
securitySchemes:
jwtAuth:
type: oauth2
x-tokenInfoFunc: services.token.check_token_info
flows:
authorizationCode:
tokenUrl: "url"
authorizationUrl: "url"
schemas:
User:
type: object
properties:
id:
type: integer
example: 1
name:
type: string
example: John Doe
email:
type: string
example: [email protected]
Author:
type: object
properties:
id:
type: integer
example: 1
name:
type: string
example: John Doe
avatar:
type: string
example: http://example.com/img/avatar/jose_thumb.png
nullable: true
Tabnews:
type: object
properties:
id:
type: integer
example: 42
title:
type: string
example: Python is a great option for backend and APIs
description:
type: string
nullable: true
author:
$ref: "#/components/schemas/Author"
created_at:
type: string
format: date-time
example: 2021-01-11T11:32:28Z
p.s:
- Este YAML pode ser alterado online com este editor: https://editor.swagger.io/
- Sei que a sugestão é não usar JWT, este YAML está com JWT, mas deve ser uma alteração pequena para usar autenticação via session/cookie
- Pode notar que as permissões são com base em recursos ao invés de role
Também tentei integrar no Next-JS o OpenAPI, mas falhei miseravelmente:
https://github.com/jellydn/next-swagger-doc 😞
Dai acabei fazendo com uma stack que tenho mais conhecimento, então esta versão rodando no Heroku foi feita com Python/Flask
from tabnews.com.br.
Excelente pergunta @rhandrade ! Nós devemos usar os status code sim ao retornar a request no controller 👍 então como você já pode deduzir pelo status code se a request teve sucesso ou não, acho redundante colocar uma propriedade/flag a mais na resposta. Incusive a maioria das bibliotecas que consomem endpoints http vão escolher continuar ou jogar um erro dependendo do status code retornado.
O exemplo que coloquei é meio mock, mas sobre a parte de faltar alguns campos ali, a gente poderia usar o 400 Bad Request
que é o mais comum... ou o 422 Unprocessable Entity
que não é tão comum, mas é bem específico nessa condição, olha a descrição que legal:
The 422 (Unprocessable Entity) status code means the server
understands the content type of the request entity (hence a
415(Unsupported Media Type) status code is inappropriate), and the
syntax of the request entity is correct (thus a 400 (Bad Request)
status code is inappropriate) but was unable to process the contained
instructions. For example, this error condition may occur if an XML
request body contains well-formed (i.e., syntactically correct), but
semantically erroneous, XML instructions.
from tabnews.com.br.
Que maneiro @huogerac. Achei a ideia de usar a OpenAPI sensacional por ela já ser um padrão para descrever APIs bem difundido. Quanto ao exemplo que você deu talvez não seria necessário colocar o status code dentro do objeto, como o @filipedeschamps tinha comentado na minha dúvida...
Esses dias tava fuçando na API beta do OpenAI e curti o modo como eles retornam os erros, deixo um exemplo abaixo. A requisição nesse caso retornou um status code 404 com o seguinte objeto:
{
"error": {
"code": null,
"message": "Engine not found",
"param": null,
"type": "invalid_request_error"
}
}
from tabnews.com.br.
Criei um PR #129 como proposta da padronização dos erros utilizando o onErrorHandler
do next-connect
. Creio que a sugestão que o @filipedeschamps funciona muito bem, tanto nos casos de erros singulares, como nos erros múltiplos.
from tabnews.com.br.
Show @filipedeschamps, agora consegui entender melhor essa questão. Vlw 👍
from tabnews.com.br.
Olá pessoal! Essa issue foi resolvida no PR #131 certo? o que acham de fecharmos para focar nas pendências ainda existentes?
from tabnews.com.br.
Show @filipedeschamps... Pelo que entendi identificaríamos os erros pelo status code da requisição. Ai fiquei com uma dúvida.
No exemplo que você deu o erro ocorreu devido a uma regra da aplicação. Nesses casos devemos responder com um status 200, indicando que o servidor processou a requisição e por algum motivo deu erro e incluir uma flag dentro da resposta mostrando que teve um erro (tipo um "success": false
), ou usamos os status 4xx para indicar isso, como um 400, por exemplo?
Sempre fico em dúvida nessa parte, porque fico tentado encontrar o melhor status code para descrever o problema retornado. No exemplo que você deu e olhando a definição do http status code, talvez o status 400 não seria a melhor opção, visto que o servidor conseguiu entender a requisição. 🤔
from tabnews.com.br.
Show pessoal, estou voltando nessa thread :)
Sobre um objeto de erro singular, como é feito no caso onde é preciso retornar múltiplos erros? Por exemplo numa validação de um formulário em que mais de 1 campo pode não passar na validação?
Mas sobre o OpenAPI num geral, ele é uma descrição de como a API funciona, e também define os padrões de resposta, e com isso consegue gerar documentação, correto? To pesquisando a respeito. Quem usa, fala muito bem, mas não to conseguindo achar uma adoção massiva ao ponto de me sentir confortável em colocar essa abstração em cima das respostas. Mas vou estudar mais a respeito 👍
Em paralelo, vejo também que é uma camada que dá para colocar por cima depois, e no estágio atual do projeto, podemos mudar qualquer interface pública que quisermos 🤝
from tabnews.com.br.
@filipedeschamps Acredito que quando forem muitos erros poderíamos retornar um array contendo vários objetos erros, cada qual com o erro que aconteceu.
O Laravel tem uma proposta semelhante se não estou enganado, no qual temos um objeto errors, no qual cada propriedade é um campo que causou o erro e o valor é um array contendo com todos os erros de validação para aquele campo.
Sobre a OpenAPI eu entendi isso ai tbm.
from tabnews.com.br.
Show @rhandrade o custom error consegue esperar um array de erros e retornar no errors
um array 👍
@brunofamiliar corretíssimo e valeu pelo toque! Fechando a issue 😍
from tabnews.com.br.
Related Issues (20)
- Não é possível editar ou apagar um conteúdo usando apenas o teclado HOT 1
- Tela de Insight dos Posts e Perfil HOT 1
- Pesquisa de conteúdo HOT 1
- Bloquear cadastro com senhas fracas HOT 7
- Marcar um comentário como resposta? HOT 7
- Melhorar a Exibição de Erros de Autenticação HOT 4
- Melhorar processamento dos comentários HOT 2
- havera uma versão em inglês ? HOT 2
- Implementação do pubsubhubbub na RSS
- Adicionar funcionalidade de Favoritar os posts HOT 1
- Tabnews: múltiplos logins associados ao mesmo endereço Gmail. Detalhes na descrição. HOT 3
- Mensagem de erro ao tentar publicar novo conteúdo HOT 7
- Encerramento da parceria com a Vercel HOT 21
- Campo `description` em algumas páginas causa resultados inadequados no Google HOT 3
- Posso implementar a opção de Login com github? HOT 2
- Latex em publicações HOT 1
- Página de anúncio tem link para o próprio anúncio HOT 2
- Limitar anúncios ativos por usuário HOT 10
- Implementação de categorização de posts HOT 1
- Forçar usuário a comentar quando tentar negativar post HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from tabnews.com.br.