Pular para conteúdo

Sprint 4 - Visualização de Resposta

Nesse módulo iremos apenas criar endpoints que possibilitem a visualização dos feedbacks recebidos aos colaboradores e PDMs, para tanto iremos remapear as entidades já existentes em outros módulos para fazer a query correta e exibir ao usuário

API Gateway NodeJS

Principais Funcionalidades

  • Roteamento de solicitações para os microsserviços apropriados
  • Validação de JWT
  • Transformação de solicitações/respostas
  • Balanceamento de carga (quando configurado)

Biblioteca Usada para Proxy de Solicitações

Utilizamos a biblioteca http-proxy-middleware para proxy de solicitações. Esta biblioteca fornece uma maneira flexível de encaminhar solicitações HTTP para outros servidores.

Principais benefícios da http-proxy-middleware:

  1. Fácil de configurar e implementar
  2. Suporta várias opções para reescrita de caminho, modificação de solicitações e tratamento de erros
  3. Funciona bem com Express.js
  4. Permite integração de middleware personalizado

Como Adicionar um Endpoint

Para adicionar um novo endpoint à API Gateway:

  1. Abra o arquivo src/app.ts.
  2. Adicione uma nova configuração de proxy usando a função createProxyMiddleware:
app.use('/novo-servico', createProxyMiddleware({
  target: 'http://novo-servico:8080',
  changeOrigin: true,
  pathRewrite: {
    '^/novo-servico': '',
  },
}));

Substitua '/novo-servico' pelo caminho desejado e 'http://novo-servico:8080' pela URL do serviço real.

Nota

O pathRewrite é uma funcionalidade da biblioteca http-proxy-middleware que permite modificar o caminho da URL de uma solicitação antes que ela seja encaminhada para o servidor de destino. Isso é útil quando você deseja ocultar ou alterar partes do caminho original, garantindo que o servidor de destino receba um formato de URL apropriado. Por exemplo, ao usar pathRewrite para substituir um caminho específico por uma string vazia, você pode tornar a solicitação mais limpa e compatível com a estrutura interna do microsserviço, facilitando o roteamento e a integração entre diferentes serviços na arquitetura de microsserviços.

Principais Diferenças em Relação ao Nginx

Embora tanto nossa API Gateway em Node.js quanto o Nginx (configurado em gateway/nginx.conf) possam atuar como proxies reversos, existem algumas diferenças principais:

  1. Flexibilidade: A API Gateway em Node.js permite maior controle programático e implementação de lógica personalizada em JavaScript/TypeScript.

  2. Validação de JWT: Nossa API Gateway realiza a validação de JWT no código Node.js, enquanto o Nginx exigiria módulos adicionais ou serviços externos para isso.

  3. Configuração Dinâmica: A gateway em Node.js pode ser facilmente atualizada e reconfigurada sem reiniciar, enquanto o Nginx geralmente requer um reload para alterações na configuração.

  4. Desempenho: O Nginx é geralmente mais eficiente para tarefas simples de proxy, mas nossa gateway em Node.js oferece mais flexibilidade para operações complexas.

  5. Balanceamento de Carga: Embora ambos possam realizar balanceamento de carga, o Nginx possui mais recursos integrados para isso, enquanto nossa gateway em Node.js exigiria implementação adicional.

Validação de JWT

A validação de JWT é realizada na API Gateway para garantir que apenas solicitações autenticadas cheguem aos serviços de backend. Veja como funciona:

  1. O middleware validateJwt em src/app.ts intercepta todas as solicitações.
  2. Ele verifica a presença de um JWT no cabeçalho Authorization.
  3. Se um token estiver presente, ele é verificado usando a biblioteca jsonwebtoken.
  4. Se o token for válido, a solicitação prossegue; caso contrário, é rejeitada com uma resposta 401 Não Autorizado.

Mudando o Filtro no Backend Java

A partir do momento em que o Node passa a validar o topken JWT ele irá parar de enviar o mesmo ao backend, e passa a enviar apenas o payload do usuário como parte dos headers, observe abaixo:

app.use((req: Request, res: Response, next: NextFunction) => {
    const token = req.headers['authorization']?.split(' ')[1]; // Pega o token do header

    jwt.verify(token, SECRET_KEY, {issuer: ISSUER}, (err: any, decoded: any) => {
        // Adiciona o payload do token ao header 'claims'
        req.headers['x-user'] = JSON.stringify(decoded['user']); // Converte o payload para string

        next(); // Token válido, continue para a próxima função/middleware
    });
});

const proxyEvents: OnProxyEvent = {
    proxyReq: (proxyReq, req, res) => {
        proxyReq.setHeader("x-user", req.headers['x-user'] || "")
    }
}

app.use('/users', createProxyMiddleware({
    // outras opções
    on: proxyEvents, // passa o consumidor de eventos que irá repassar o payload de usuario para o backend
    // outras opções
}));

No Java devemos então mudar as forma em que validamos o usuário logado. Para isso já temos o filtro correto implementado na lib de segurança, basta passar nos microservices e mudar a anotação de @EnableJwtSecurity para @EnableUserClaimsSecurity, o restante da segurança mantém-se igual

Serviço de Visualização de Respostas de Feedback Em Python

Visão Geral

Este serviço atua como um Backend for Frontend (BFF) para visualização de respostas de feedback. Ele utiliza FastAPI como framework web e Peewee como ORM.

Conceito de Backend for Frontend (BFF)

Um Backend for Frontend (BFF) é um padrão arquitetural onde um serviço backend dedicado é criado para atender a uma aplicação frontend ou cliente específica. Neste caso, nosso BFF é adaptado para a visualização de respostas de feedback.

Benefícios do BFF: - Otimizado para necessidades específicas do frontend - Melhoria no desempenho ao agregar múltiplas chamadas de backend - Mais fácil de manter e evoluir junto com o frontend

Integração do FastAPI e Peewee

Configurando o FastAPI

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Bem-vindo ao BFF de Visualização de Respostas de Feedback"}

Modelos Peewee

Crie seus modelos Peewee em models.py:

from peewee import *

database = PostgresqlDatabase('sua_base_de_dados', user='seu_usuario', password='sua_senha', host='seu_host')

class BaseModel(Model):
    class Meta:
        database = database

class FeedbackResponse(BaseModel):
    id = AutoField()
    content = TextField()
    created_at = DateTimeField()
    # Adicione outros campos conforme necessário

Endpoints do FastAPI com Peewee

from fastapi import FastAPI, Depends, HTTPException
from .models import FeedbackResponse

app = FastAPI()

@app.get("/feedback-responses/")
async def get_feedback_responses():
    responses = FeedbackResponse.select()
    return [{"id": r.id, "content": r.content, "created_at": r.created_at} for r in responses]

Autenticação e Autorização de Usuários

Será necessário capturar o payload do usuário repassado pelo gateway no cabeçalho x-user, isso se torna simples no fastapi pelo uso do obejto Header e o obejto Depends

Para capturar dados do usuário do cabeçalho x-user e realizar a autorização:

from fastapi import Header, HTTPException

async def get_current_user(x_user: str = Header(None)):
    if not x_user:
        raise HTTPException(status_code=401, detail="O cabeçalho X-Users está ausente")
    # Analise o cabeçalho x-users e extraia informações do usuário
    # Implemente sua lógica para validar o acesso do usuário
    return {"user_id": "user_id_extraido"}

@app.get("/rota-protegida/")
async def protected_route(current_user: dict = Depends(get_current_user)):
    # Esta rota agora está protegida e acessível apenas para usuários autenticados
    return {"message": f"Olá, usuário {current_user['user_id']}"}

Poetry para Gerenciamento de Dependências

Poetry é uma ferramenta para gerenciamento de dependências e empacotamento em Python. Ela permite que você declare as bibliotecas das quais seu projeto depende e gerenciará (instalar/atualizar) elas para você.

Guia de referências

  1. Refinamento Técnico NodeJS
  2. Refinamento Técnico Nginx
  3. FastApi
  4. Api Gateway
  5. NodeJS Express

Referências