🚀 Oferta especial: 60% OFF no CrazyStack - Últimas vagas!Garantir vaga →

Aula 4: ElysiaJS - Servidor Base e Middlewares

Módulo 2⏱️ 25 minutos📚 Intermediário

🎯 Objetivo da Aula

Nesta aula vamos criar a estrutura base do servidor ElysiaJS com os middlewares essenciais: CORS, CSRF e Autenticação. Esta é a fundação do projeto Restaurantix.

📋 O que vamos construir

  • Servidor ElysiaJS básico
  • Middleware de CORS
  • Middleware de CSRF
  • Middleware de Autenticação
  • Tratamento de erros global

🚀 Criando o Servidor Base

1. Estrutura do Projeto

Primeiro, vamos criar a estrutura de pastas do nosso projeto:

mkdir restaurantix
cd restaurantix
bun init -y

# Estrutura de pastas
mkdir -p src/http/routes
mkdir -p src/application/infra/db
touch src/http/server.ts
touch src/http/auth.ts
touch src/http/csrf.ts

2. Instalando Dependências

bun add elysia @elysiajs/cors @elysiajs/jwt @elysiajs/cookie
bun add drizzle-orm drizzle-kit postgres
bun add @paralleldrive/cuid2 dayjs resend zod
bun add -d @types/pg

3. Middleware de CSRF

Vamos criar o middleware de proteção CSRF:

// src/http/csrf.ts
import { Elysia } from "elysia";
import { cookie } from "@elysiajs/cookie";
import { createId } from "@paralleldrive/cuid2";

export const csrf = new Elysia({ name: "csrf" })
  .use(cookie())
  .derive(({ cookie, set }) => {
    return {
      csrfToken: () => {
        if (!cookie.csrfToken) {
          const token = createId();
          cookie.csrfToken = {
            value: token,
            httpOnly: true,
            secure: process.env.NODE_ENV === "production",
            sameSite: "strict",
            maxAge: 60 * 60 * 24 * 7, // 7 days
          };
          return token;
        }
        return cookie.csrfToken.value;
      },
    };
  })
  .macro(({ onBeforeHandle }) => ({
    csrf: (enabled: boolean = true) => {
      if (!enabled) return;
      
      onBeforeHandle(({ cookie, headers, error }) => {
        const token = cookie.csrfToken?.value;
        const headerToken = headers["x-csrf-token"];
        
        if (!token || token !== headerToken) {
          return error(403, "Invalid CSRF token");
        }
      });
    },
  }));

4. Middleware de Autenticação

Agora o middleware de autenticação JWT:

// src/http/auth.ts
import { Elysia } from "elysia";
import { jwt } from "@elysiajs/jwt";
import { cookie } from "@elysiajs/cookie";

export const auth = new Elysia({ name: "auth" })
  .use(
    jwt({
      name: "jwt",
      secret: process.env.JWT_SECRET || "your-secret-key",
    })
  )
  .use(cookie())
  .derive(({ jwt, cookie }) => {
    return {
      getCurrentUser: async () => {
        const token = cookie.auth;
        if (!token) {
          throw new Error("Unauthorized");
        }
        
        const payload = await jwt.verify(token);
        if (!payload) {
          throw new Error("Unauthorized");
        }
        
        return payload as { sub: string };
      },
      signUser: async (userId: string) => {
        return await jwt.sign({ sub: userId });
      },
    };
  })
  .macro(({ onBeforeHandle }) => ({
    isSignedIn: (enabled: boolean = true) => {
      if (!enabled) return;
      
      onBeforeHandle(async ({ getCurrentUser, error }) => {
        try {
          await getCurrentUser();
        } catch {
          return error(401, "Unauthorized");
        }
      });
    },
  }));

5. Servidor Principal

Agora vamos criar o servidor principal com os middlewares:

// src/http/server.ts
import { Elysia } from "elysia";
import { cors } from "@elysiajs/cors";
import { auth } from "./auth";
import { csrf } from "./csrf";

const app = new Elysia()
  .use(cors())
  .use(csrf)
  .use(auth)
  .get("/", () => ({ message: "Restaurantix API" }))
  .onError(({ error, code, set }) => {
    console.error(error);
    switch (code) {
      case "VALIDATION":
        set.status = error.status;
        return error.toResponse();
      default:
        set.status = 500;
        console.error(error);
        return new Response(null, { status: 500 });
    }
  });

app.listen(3000, () => {
  console.log("Server is running on port 3000");
});

6. Testando o Servidor

# Executar o servidor
bun run src/http/server.ts

# Testar em outro terminal
curl http://localhost:3000
# Resposta: {"message":"Restaurantix API"}

🎯 Próximos Passos

Na próxima aula, vamos começar a adicionar as rotas do sistema, começando pelas rotas de autenticação e CSRF token.

💡 Dica: Os middlewares são executados na ordem que são registrados. CORS primeiro, depois CSRF, depois Auth.

✅ Checkpoint: Você agora tem um servidor ElysiaJS funcionando com middlewares de segurança configurados!