Seu Primeiro Servidor Express
Agora que nosso ambiente está configurado, vamos criar nosso primeiro servidor HTTP com Express e TypeScript. Express é o framework web mais popular do Node.js, conhecido por sua simplicidade e flexibilidade.
Instalando Express
# Express e seus tiposnpm install expressnpm install -D @types/expressHello World com Express
Crie o arquivo src/app.ts:
import express, { Application, Request, Response } from 'express'; const app: Application = express(); // Middleware para parsear JSONapp.use(express.json()); // Rota raizapp.get('/', (req: Request, res: Response) => { res.json({ message: 'Bem-vindo à API E-commerce!', version: '1.0.0', timestamp: new Date().toISOString(), });}); // Rota de health checkapp.get('/health', (req: Request, res: Response) => { res.json({ status: 'ok', uptime: process.uptime(), memory: process.memoryUsage(), });}); export default app;Agora crie src/server.ts:
import app from './app'; const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`🚀 Servidor rodando em http://localhost:${PORT}`); console.log(`📝 Ambiente: ${process.env.NODE_ENV || 'development'}`);});Execute:
npm run devAcesse http://localhost:3000 no navegador ou use curl:
curl http://localhost:3000# {"message":"Bem-vindo à API E-commerce!","version":"1.0.0",...}Entendendo Express
Application
O objeto app é a instância principal do Express:
import express, { Application } from 'express'; const app: Application = express(); // app.use() - Adiciona middlewares// app.get() - Define rota GET// app.post() - Define rota POST// app.listen() - Inicia o servidorRequest e Response
Toda rota recebe dois objetos principais:
app.get('/users/:id', (req: Request, res: Response) => { // Request - Informações da requisição console.log(req.method); // 'GET' console.log(req.path); // '/users/123' console.log(req.params.id); // '123' console.log(req.query); // { page: '1', limit: '10' } console.log(req.body); // Corpo da requisição (POST/PUT) console.log(req.headers); // Headers da requisição // Response - Métodos para responder res.status(200); // Define status code res.json({ data: 'valor' }); // Envia JSON res.send('texto'); // Envia texto res.redirect('/outra-rota'); // Redireciona});Tipando Request e Response
Para máxima segurança de tipos, podemos tipar o body, params e query:
import { Request, Response } from 'express'; // Tipos personalizadosinterface CreateUserBody { name: string; email: string; password: string;} interface UserParams { id: string;} interface ListUsersQuery { page?: string; limit?: string; search?: string;} // Rota tipadaapp.post('/users', ( req: Request<{}, {}, CreateUserBody>, res: Response) => { const { name, email, password } = req.body; // TypeScript sabe que name, email, password são strings}); app.get('/users/:id', ( req: Request<UserParams>, res: Response) => { const { id } = req.params; // TypeScript sabe que id é string}); app.get('/users', ( req: Request<{}, {}, {}, ListUsersQuery>, res: Response) => { const { page = '1', limit = '10', search } = req.query;});Estrutura de Resposta Padronizada
É uma boa prática padronizar suas respostas:
// src/utils/response.tsexport interface ApiResponse<T = unknown> { success: boolean; data?: T; message?: string; errors?: string[]; meta?: { page?: number; limit?: number; total?: number; };} export function successResponse<T>(data: T, message?: string): ApiResponse<T> { return { success: true, data, message, };} export function errorResponse(message: string, errors?: string[]): ApiResponse { return { success: false, message, errors, };} export function paginatedResponse<T>( data: T[], page: number, limit: number, total: number): ApiResponse<T[]> { return { success: true, data, meta: { page, limit, total }, };}Usando nas rotas:
import { successResponse, errorResponse } from './utils/response'; app.get('/users/:id', async (req: Request, res: Response) => { const user = await findUser(req.params.id); if (!user) { return res.status(404).json( errorResponse('Usuário não encontrado') ); } res.json(successResponse(user, 'Usuário encontrado'));});Organizando Rotas
À medida que a aplicação cresce, organize as rotas em arquivos separados:
// src/routes/user.routes.tsimport { Router, Request, Response } from 'express'; const router = Router(); // GET /usersrouter.get('/', (req: Request, res: Response) => { res.json({ users: [] });}); // GET /users/:idrouter.get('/:id', (req: Request, res: Response) => { res.json({ user: { id: req.params.id } });}); // POST /usersrouter.post('/', (req: Request, res: Response) => { res.status(201).json({ user: req.body });}); // PUT /users/:idrouter.put('/:id', (req: Request, res: Response) => { res.json({ user: { id: req.params.id, ...req.body } });}); // DELETE /users/:idrouter.delete('/:id', (req: Request, res: Response) => { res.status(204).send();}); export default router;// src/routes/index.tsimport { Router } from 'express';import userRoutes from './user.routes';import productRoutes from './product.routes'; const router = Router(); router.use('/users', userRoutes);router.use('/products', productRoutes); export default router;// src/app.tsimport express from 'express';import routes from './routes'; const app = express(); app.use(express.json());app.use('/api', routes); export default app;Agora suas rotas ficam organizadas:
GET /api/users
POST /api/users
GET /api/users/:id
PUT /api/users/:id
DELETE /api/users/:id
Middlewares Essenciais
Adicione middlewares comuns:
npm install cors helmet morgannpm install -D @types/cors @types/morgan// src/app.tsimport express from 'express';import cors from 'cors';import helmet from 'helmet';import morgan from 'morgan';import routes from './routes'; const app = express(); // Segurança - Define headers HTTP segurosapp.use(helmet()); // CORS - Permite requisições de outros domíniosapp.use(cors({ origin: process.env.FRONTEND_URL || 'http://localhost:3001', credentials: true,})); // Logger de requisiçõesapp.use(morgan('dev')); // Parser de JSONapp.use(express.json({ limit: '10mb' })); // Parser de URL encodedapp.use(express.urlencoded({ extended: true })); // Rotasapp.use('/api', routes); export default app;O que cada middleware faz?
| Middleware | Função |
|---|---|
helmet | Adiciona headers de segurança (XSS, CSRF, etc) |
cors | Permite requisições cross-origin |
morgan | Loga requisições no console |
express.json | Parseia body JSON |
express.urlencoded | Parseia form data |
Testando com REST Client
Instale a extensão REST Client no VS Code e crie requests.http:
### Health CheckGET http://localhost:3000/health ### Listar UsuáriosGET http://localhost:3000/api/users ### Criar UsuárioPOST http://localhost:3000/api/usersContent-Type: application/json { "name": "João Silva", "email": "joao@email.com", "password": "123456"} ### Buscar UsuárioGET http://localhost:3000/api/users/1 ### Atualizar UsuárioPUT http://localhost:3000/api/users/1Content-Type: application/json { "name": "João Silva Atualizado"} ### Deletar UsuárioDELETE http://localhost:3000/api/users/1Clique em "Send Request" acima de cada requisição para testar.
Exercício Prático
Crie as seguintes rotas para produtos:
// GET /api/products - Listar produtos// POST /api/products - Criar produto// GET /api/products/:id - Buscar produto por ID// PUT /api/products/:id - Atualizar produto// DELETE /api/products/:id - Deletar produtoResumo
Nesta aula aprendemos:
- ✅ Criar servidor Express com TypeScript
- ✅ Tipar Request e Response
- ✅ Padronizar respostas da API
- ✅ Organizar rotas em arquivos separados
- ✅ Usar middlewares essenciais
- ✅ Testar rotas com REST Client
Na próxima aula, vamos nos aprofundar em Rotas e Middlewares! 🎯