2. Antes de tudo
• Para organizar ainda mais nosso projeto
• Vamos adicionar o script de inicialização no package.json
• "start": "nodemon src/main.js“
• Para executar é só:
• npm start
3. Executando
npm start
> aula3@1.0.0 start
C:Usersbrunodevtap2019.1aula3
> nodemon src/main.js
[nodemon] 1.18.10
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node src/main.js`
body-parser deprecated undefined extended:...
Aplicação no ar em http://localhost:3000
4. Logging de Requisições
• Vamos utilizar o pacote Morgan
• https://github.com/expressjs/morgan
• Como será que instala ?
• npm i morgan --save
• Como usar ?
• Importar o módulo:
• const morgan = require('morgan')
• Escolher o formato: combined, common, dev, short, tiny
• app.use(morgan('combined’))
• É só isso!
5. Morgan
• Formatos predefinidos:
• combined
• :remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status
:res[content-length] ":referrer" ":user-agent"
• common
• :remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status
:res[content-length]
• dev
• :method :url :status :response-time ms - :res[content-length]
• short
• :remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] -
:response-time ms
• tiny
• :method :url :status :res[content-length] - :response-time ms
6. Morgan
• Por padrão, os logs são mostrados na saída padrão
• Para redirecionar os logs para um arquivo:
• É preciso importar os módulos fs (file system) e path
• const fs = require('fs')
• const path = require('path’)
• Depois, cria-se um stream de saída para o arquivo de logging:
• var logStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a’ })
• Configura o Morgan:
• app.use(morgan('combined', { stream: logStream }))
8. Saída
::1 - GET / HTTP/1.1 200 293 - 59.417 ms
::1 - GET /images/logo.jpg HTTP/1.1 304 - - 3.229 ms
::1 - GET /css/styles.css HTTP/1.1 304 - - 4.025 ms
::1 - GET /favicon.ico HTTP/1.1 200 3 - 1.049 ms
::1 - GET /livros HTTP/1.1 304 - - 1.093 ms
::1 - GET /favicon.ico HTTP/1.1 304 - - 0.700 ms
9. Logging de Código
• Existem vários pacotes
• Os mais usados são:
• Debug – Pacote simples, baseado em workspaces
• Winston – Pacote voltado para aplicações, contendo níveis de logging
• Trace – Logging para aplicações distribuídas, contendo microservices
10. Debug
• Instalação:
• npm i debug --save
• Uso:
• const debug = require('debug')(‘testes’);
• debug(‘produto = %o’, produto);
• Executando:
• DEBUG=testes node app.js
• Vantagens:
• Bom para testes (debugging)
• Na execução normal nenhuma saída é mostrada
• É possível utilizar vários workspaces para exibir saídas diferentes
11. Debug
• Sintaxe: debug(‘mensagem %fmt1 %fmt2’, valor1, valor2);
• Formatadores:
• %O – Objeto (em várias linhas)
• %o – Objeto (em uma única linha)
• %s - String
• %d - Número
• %j - JSON
• %% - Caractere de porcentagem (%)
12. Winston
• Logging de eventos da aplicação
• Suporte a vários níveis de logging
• Instalação:
• npm i winston --save
• Uso:
• const winston = require('winston’);
• winston.log('info', 'Hello log files!’, {someKey: 'some-value’});
• Sintaxe:
• winston.log(NIVEL, MENSAGEM, VALORES);
13. Winston
• Níveis de Severidade (RFC5424):
• error: 0
• warn: 1
• info: 2
• verbose: 3
• debug: 4
• silly: 5
• Um logger exibe mensagens de um nível menor ou igual ao seu
• Ex1. um logger com nível error exibe apenas mensagens error
• Ex2. um logger com nível silly exibe mensagens de todos os níveis
14. Winston
• Criando um logger:
const logger = winston.createLogger({
level: 'info',
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'meuslogs.log' })
]
});
15. Winston
• Criando um logger:
const logger = winston.createLogger({
level: 'silly',
transports: [
new winston.transports.Console({ level: 'silly' }),
new winston.transports.File({level: 'error' , filename: 'erros.log' }),
new winston.transports.File({filename: 'combinado.log' }),
]
});
16. Winston
• Criando um logger:
const logger = winston.createLogger({
level: 'info',
transports: [
new winston.transports.File({level: 'error' , filename: 'erros.log' }),
new winston.transports.File({filename: 'combinado.log' }),
]
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console());
}
17. No nosso projeto
• Vamos criar uma pasta config
• Dentro dela, vamos criar um script "logger.js"
• Esse script irá criar e configurar um logger, esse objeto poderá ser
utilizado em qualquer ponto da aplicação que precise registrar o que
está acontecendo
20. Saída
::1 - POST /livros HTTP/1.1 200 55 - 300.231 ms
::1 - GET /livros HTTP/1.1 200 57 - 1.747 ms
{"message":"Procurando o indice do livro com id 0","level":"info"}
::1 - GET /livros/0 HTTP/1.1 200 55 - 5.824 ms
::1 - GET /favicon.ico HTTP/1.1 304 - - 1.058 ms
{"message":"Procurando o indice do livro com id 3","level":"info"}
{"message":"Nao foi encontrado livro com id 3","level":"error"}
::1 - GET /livros/3 HTTP/1.1 200 - - 2.386 ms
::1 - GET /favicon.ico HTTP/1.1 304 - - 1.034 ms
22. Trace (PM2)
• Ferramenta paga
• Provê visualizações dos logs (organiza em árvores, cria gráficos, etc)
• Emite notificações (ex. em caso de exceções)
25. JWT – Como funciona ?
1. Você faz login
1. Se o login estiver correto, status 200, retorna um objeto com o token
2. Se o login estiver errado, status 500, retorna mensagem de erro
2. Tenta acessar uma URL segura
1. Verifica se no cabeçalho tem um atributo Authorization no formato:
Authorization: Bearer <token>
2. Se não tiver, status 401, mensagem de que não tem o token
3. Se tiver o token, tenta verificar ele
1. Não foi possível verificar o token, status 400, mensagem de erro
2. Token verificado, adiciona o payload do token no request e permite a entrada
26. Lista de códigos de status HTTP
• 200 – Sucesso
• 400 – Requisição inválida
• 401 – Não autorizado
• 402 – Pagamento necessário
• 403 – Proibido
• 404 – Não encontrado
• 500 – Erro interno do servidor
27. Implementando autenticação com JWT
• Primeiro passo, instalar o pacote jsonwebtoken:
• npm i jsonwebtoken --save
• Na pasta config, vamos criar um script "constantes.js"
• Vamos criar na pasta controllers um script "autorizacao.js"
• Vamos criar uma pasta "util" e um script "seguranca.js"
• Por fim, vamos dizer quais rotas de "livros.js" são seguras ou não.
37. Para a próxima aula
• Valendo pontos na primeira avaliação
• O projeto valerá 5 pontos
• Os outros 5 pontos restantes serão um somatório das atividades propostas em sala
• Com base nos exemplos das últimas aulas, faça um sistema com Node e
Express que:
• possua pelos menos dois perfis de usuário (ex. ADMIN e USER);
• tenha rotas públicas, rotas que todos os perfis autenticados possam acessar e todas
que apenas um perfil possa acessar (dica, use os dados do payload);
• armazena os dados de um recurso e dos usuários em um arquivo.