Como construir uma API RESTful com Edge Functions e Edge SQL
Este guia demonstra como construir uma API RESTful completa para gerenciamento de tarefas usando Azion Edge Functions e Edge SQL. Você aprenderá a implementar operações CRUD (Create, Read, Update, Delete) completas na edge, fornecendo endpoints de API rápidos e escaláveis globalmente.
Requisitos
Antes de começar, certifique-se de ter:
- Uma conta na Azion
- Azion CLI instalada e configurada
- Node.js versão 18 ou superior
- Gerenciador de pacotes pnpm instalado
- Edge SQL habilitado em sua conta Azion
- Conhecimento básico de JavaScript, APIs REST e SQL
- Uma instância Edge SQL configurada e funcionando
Primeiros passos
Passo 1: Configure seu ambiente de desenvolvimento
- Clone o repositório de exemplo de tarefas RESTful:
git clone https://github.com/egermano/edge-functions-examples.gitcd edge-functions-examples/packages/restful-tasks
- Instale as dependências do projeto:
pnpm install
- Revise a estrutura do projeto para entender a implementação:
ls -la
Você deve ver os arquivos principais incluindo a implementação da Edge Function, schema SQL e arquivos de configuração.
Passo 2: Configure a conexão Edge SQL
- Crie um arquivo
.env
baseado no exemplo:
cp .env.example .env
- Edite o arquivo
.env
para incluir sua configuração Edge SQL:
# Configuração Edge SQLEDGE_SQL_CONNECTION_STRING=sua_string_de_conexao_edge_sqlDATABASE_NAME=tasks_db
- Obtenha os detalhes de conexão Edge SQL do Console Azion > Edge SQL.
Passo 3: Configure o schema do banco de dados
- Conecte-se à sua instância Edge SQL e crie a tabela de tarefas:
CREATE TABLE IF NOT EXISTS tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, completed BOOLEAN DEFAULT FALSE, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);
- Opcionalmente, insira alguns dados de exemplo para teste:
INSERT INTO tasks (title, completed) VALUES ('Completar documentação da API', FALSE), ('Testar deploy da edge function', FALSE), ('Revisar configurações de segurança', TRUE);
Passo 4: Compile o projeto
Compile sua Edge Function para deployment:
pnpm build
Este comando compila sua Edge Function e a prepara para deployment na rede edge da Azion.
Passo 5: Teste localmente
Antes de fazer o deploy, teste sua API localmente:
pnpm dev
Isso inicia um servidor de desenvolvimento local onde você pode testar todos os endpoints da API.
Endpoints da API
A API RESTful de Tarefas fornece os seguintes endpoints:
GET /tasks
Recupera todas as tarefas do banco de dados.
Resposta:
{ "tasks": [ { "id": 1, "title": "Completar documentação da API", "completed": false, "created_at": "2023-01-01T10:00:00Z", "updated_at": "2023-01-01T10:00:00Z" } ]}
GET /tasks/
Recupera uma tarefa específica por ID.
Resposta:
{ "task": { "id": 1, "title": "Completar documentação da API", "completed": false, "created_at": "2023-01-01T10:00:00Z", "updated_at": "2023-01-01T10:00:00Z" }}
POST /tasks
Cria uma nova tarefa.
Corpo da requisição:
{ "title": "Título da nova tarefa", "completed": false}
Resposta:
{ "task": { "id": 4, "title": "Título da nova tarefa", "completed": false, "created_at": "2023-01-01T12:00:00Z", "updated_at": "2023-01-01T12:00:00Z" }}
PUT /tasks/
Atualiza uma tarefa existente.
Corpo da requisição:
{ "title": "Título da tarefa atualizada", "completed": true}
Resposta:
{ "task": { "id": 1, "title": "Título da tarefa atualizada", "completed": true, "created_at": "2023-01-01T10:00:00Z", "updated_at": "2023-01-01T14:00:00Z" }}
DELETE /tasks/
Exclui uma tarefa por ID.
Resposta:
{ "message": "Tarefa excluída com sucesso"}
Deploy na Azion
Passo 1: Autentique-se na Azion
- Faça login na sua conta Azion via CLI:
azion login
- Siga os prompts de autenticação para conectar sua CLI com sua conta Azion.
Passo 2: Configure a conexão Edge SQL
- Crie secrets para sua conexão com o banco de dados:
azion create secret EDGE_SQL_CONNECTION_STRING
- Quando solicitado, digite sua string de conexão Edge SQL.
Passo 3: Faça o deploy da Edge Function
Faça o deploy de sua API RESTful na rede edge da Azion:
azion deploy
O processo de deploy irá:
- Fazer upload do código da sua Edge Function
- Configurar a edge application
- Configurar regras de roteamento para todos os endpoints da API
- Configurar conexões com o banco de dados
- Fornecer um domínio único
Passo 4: Acesse sua API
Após o deploy, você receberá um domínio como https://xxxxxxx.map.azionedge.net
. Sua API RESTful estará disponível nesta URL em alguns minutos após a propagação do DNS.
Entendendo a implementação
Estrutura da Edge Function
A Edge Function da API RESTful inclui:
- Configuração do router: Manipulação de diferentes métodos HTTP e rotas
- Conexão com banco de dados: Conectando ao Edge SQL
- Operações CRUD: Implementação de operações create, read, update, delete
- Tratamento de erros: Gerenciamento de erros de banco de dados e requisição
- Formatação de resposta: Retorno de respostas JSON consistentes
Exemplo de operações de banco de dados
Veja como as operações de banco de dados são implementadas:
// Obter todas as tarefasasync function getAllTasks() { const query = 'SELECT * FROM tasks ORDER BY created_at DESC'; const result = await database.query(query); return result.rows;}
// Criar uma nova tarefaasync function createTask(title, completed = false) { const query = ` INSERT INTO tasks (title, completed) VALUES (?, ?) RETURNING * `; const result = await database.query(query, [title, completed]); return result.rows[0];}
// Atualizar uma tarefaasync function updateTask(id, updates) { const { title, completed } = updates; const query = ` UPDATE tasks SET title = ?, completed = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? RETURNING * `; const result = await database.query(query, [title, completed, id]); return result.rows[0];}
Principais benefícios
- Performance: Processamento de API na edge reduz latência
- Escalabilidade: Escala automaticamente com a demanda
- Distribuição global: Localizações edge fornecem cobertura mundial
- Consistência de dados: Edge SQL garante conformidade ACID
- Eficiência de custo: Acesso e transferência de dados otimizados
Testando sua API RESTful
Passo 1: Teste operações CRUD
- Criar tarefas: Teste endpoint POST /tasks
- Ler tarefas: Teste endpoints GET /tasks e GET /tasks/
- Atualizar tarefas: Teste endpoint PUT /tasks/
- Excluir tarefas: Teste endpoint DELETE /tasks/
Passo 2: Teste tratamento de erros
- Dados inválidos: Teste com corpos de requisição malformados
- Recursos inexistentes: Teste com IDs de tarefa inválidos
- Erros de banco de dados: Teste tratamento de erros para problemas de conexão
- Erros de validação: Teste lógica de validação de entrada
Passo 3: Testes de performance
- Tempos de resposta: Meça tempos de resposta da API
- Requisições simultâneas: Teste múltiplas requisições simultâneas
- Performance do banco de dados: Monitore performance de consultas SQL
- Teste de carga: Teste com altos volumes de requisições
Exemplo de uso da API
Usando cURL
# Obter todas as tarefascurl -X GET https://seu-dominio.map.azionedge.net/tasks
# Criar uma nova tarefacurl -X POST https://seu-dominio.map.azionedge.net/tasks \ -H "Content-Type: application/json" \ -d '{"title": "Aprender Azion Edge Functions", "completed": false}'
# Atualizar uma tarefacurl -X PUT https://seu-dominio.map.azionedge.net/tasks/1 \ -H "Content-Type: application/json" \ -d '{"title": "Título da tarefa atualizada", "completed": true}'
# Excluir uma tarefacurl -X DELETE https://seu-dominio.map.azionedge.net/tasks/1
Usando JavaScript fetch
// Obter todas as tarefasconst tasks = await fetch('/tasks').then(r => r.json());
// Criar uma nova tarefaconst newTask = await fetch('/tasks', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: 'Nova tarefa', completed: false })}).then(r => r.json());
// Atualizar uma tarefaconst updatedTask = await fetch('/tasks/1', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: 'Tarefa atualizada', completed: true })}).then(r => r.json());
Recursos avançados
Adicionando autenticação
Implemente autenticação para proteger sua API:
async function authenticateRequest(request) { const authHeader = request.headers.get('Authorization'); if (!authHeader || !authHeader.startsWith('Bearer ')) { throw new Error('Autenticação necessária'); }
const token = authHeader.substring(7); return await validateToken(token);}
Validação de entrada
Adicione validação abrangente de entrada:
function validateTaskData(data) { const errors = [];
if (!data.title || typeof data.title !== 'string') { errors.push('Título é obrigatório e deve ser uma string'); }
if (data.title && data.title.length > 255) { errors.push('Título deve ter menos de 255 caracteres'); }
if (data.completed !== undefined && typeof data.completed !== 'boolean') { errors.push('Completed deve ser um boolean'); }
return errors;}
Paginação
Implemente paginação para grandes conjuntos de dados:
async function getTasksPaginated(page = 1, limit = 10) { const offset = (page - 1) * limit; const query = ` SELECT * FROM tasks ORDER BY created_at DESC LIMIT ? OFFSET ? `; const tasks = await database.query(query, [limit, offset]);
const countQuery = 'SELECT COUNT(*) as total FROM tasks'; const totalResult = await database.query(countQuery); const total = totalResult.rows[0].total;
return { tasks: tasks.rows, pagination: { page, limit, total, totalPages: Math.ceil(total / limit) } };}
Solução de problemas
Problemas comuns e soluções
- Erros de conexão com banco de dados: Verifique credenciais Edge SQL e string de conexão
- Endpoint da API não encontrado: Verifique configuração de roteamento e deployment
- Erros SQL: Valide schema do banco de dados e sintaxe de consulta
- Problemas de performance: Otimize consultas SQL e indexação do banco de dados
Dicas de debugging
- Habilite logging: Adicione logging abrangente para debugging
- Teste localmente: Use servidor de desenvolvimento local para isolar problemas
- Monitore performance: Rastreie tempos de resposta da API e consultas de banco de dados
- Tratamento de erros: Implemente respostas de erro adequadas e códigos de status
Próximos passos
- Implemente filtragem e ordenação avançadas
- Adicione atualizações em tempo real com WebSockets
- Integre com provedores de autenticação
- Implemente rate limiting e cache da API
- Adicione documentação abrangente da API com OpenAPI/Swagger