Last active
July 9, 2017 01:46
-
-
Save khaosdoctor/1c04a71a60b72bed7797585a04a0d351 to your computer and use it in GitHub Desktop.
Example script for medium article
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const logger = require('knoblr') | |
const mongoose = require('mongoose') | |
const Koa = require('koa') | |
const jwt = require('koa-jwt') | |
const parser = require('koa-body')() | |
const cors = require('../shared/configs/cors') | |
const ServerException = require('../shared/errors/ServerException') | |
/** | |
* Realiza a conexão no banco de dados | |
* | |
* @returns {Promise} Conexão do mongoose | |
* @inner | |
* @private | |
* @func connect | |
*/ | |
function connect () { // Conecta no Database e inicia o servidor Koa | |
mongoose.Promise = global.Promise // Substitui a lib de promises do mongo (obrigatório) | |
const mongoOptions = { // Habilita o keepalive para não fazer as conexões com o mongo em todas as chamadas | |
useMongoClient: true, | |
server: { | |
socketOptions: { | |
keepAlive: 120 | |
} | |
}, | |
replSet: { | |
socketOptions: { | |
keepAlive: 120 | |
} | |
} | |
} | |
return mongoose.connect(process.env.MONGODB_URI + process.env.MONGODB_NAME, mongoOptions) // Temos estas variáveis por causa do arquivo .env que foi carregado no index.js | |
} | |
/** | |
* Instancia um novo servidor do Koa | |
* | |
* @returns {Koa} Servidor do Koa | |
* @inner | |
* @private | |
* @func createServer | |
*/ | |
function createServer () { // Cria um servidor novo do Koa | |
logger.info(`Mongo conectado`) | |
const server = new Koa() | |
// O Koa trabalha com eventos, pois retorna uma instancia do HTTPClient do Node, então temos que ouvir estes eventos | |
server.on('error', (err, ctx) => { // Ouve o evento de erro | |
logger.error(`Server Error: ${err}`) | |
ctx.status = 500 | |
}) | |
return server | |
} | |
/** | |
* Seta o servidor com os middlewares | |
* | |
* @param {Koa} server Servidor do Koa | |
* @returns {Koa} Servidor do koa com middlewares | |
* @inner | |
* @private | |
* @func setupMiddlewares | |
*/ | |
function setupMiddlewares (server) { // Note que estamos trazendo o Server da função anterior como parâmetro | |
server.use(cors()) // Precisamos utilizar o CORS (Cross Origin Resource Sharing) para poder acessar externamente quando em produção | |
server.use((ctx, next) => { // Se o token não for válido retorna 401 | |
return next().catch((err) => { // Executa o próximo middleware, que é o JWT, se falhar o usuário é inválido | |
if (err.status === 401) { | |
logger.warn(`Acesso não autorizado de ${ctx.host} a rota ${ctx.url}`) | |
ctx.status = 401 | |
ctx.body = 'Unauthorized' | |
} else { | |
throw err | |
} | |
}) | |
}) | |
server.use(parser) // Parseia o body das requisições com payload (PUT, POST, PATCH) | |
return server | |
} | |
/** | |
* Seta o uso do middleware de JWT | |
* | |
* @param {Koa} server Servidor Koa | |
* @returns {Koa} Servidor koa | |
* @inner | |
* @private | |
* @func setupAuth | |
*/ | |
function setupAuth (server) { | |
server.use(jwt({ // Usa o middleware de JWT com as credenciais necessárias para decodificar o mesmo | |
secret: new Buffer(process.env.CLIENT_SECRET, 'base64'), | |
audience: process.env.CLIENT_ID | |
}) | |
.unless({ path: [/^\/status/] })) // A Não ser que a rota seja de status, ai não precisa de segurança porque ela é pública | |
return server | |
} | |
/** | |
* Registra todas as rotas no Koa | |
* @func registerRoutes | |
* @inner | |
* @private | |
*/ | |
function registerRoutes (server) { | |
const routes = require('glob') // Busca os arquivos de rotas | |
.sync(require('path') | |
.join(__dirname, './routes/**/*.js')) // Obtém todos os nomes de arquivos da pasta routes que terminam em '.js' | |
routes.forEach(route => { // Para cada rota | |
server.use(require(route).route) // Registra ela no servidor Koa | |
logger.info(`Rota ${route.split('/').pop().split('.').shift()} registrada`) // Informa o sysadmin através de um log | |
}) | |
return server | |
} | |
/** | |
* Inicia o listener do server | |
* | |
* @param {Koa} server Servidor Koa | |
* @returns void | |
* @inner | |
* @private | |
* @func startServer | |
*/ | |
function startServer (server) { | |
return server.listen(process.env.PORT, () => { // Inicia o servidor | |
logger.info(`Alfred pronto na porta ${process.env.PORT}`) | |
}) | |
} | |
// Chama todas as funções em ordem e retorna um unico objeto pronto para uso | |
const alfred = () => connect() // Objeto final instanciado da API | |
.then(createServer) | |
.then(setupMiddlewares) | |
.then(setupAuth) | |
.then(registerRoutes) | |
.then(startServer) | |
.catch((error) => { // Erro de conexão | |
logger.error(`Erro de conexão de banco de dados => ${error}`) | |
throw new ServerException(error, null) | |
}) | |
module.exports = alfred |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment