Design de API de transferência de ficheiros: boas práticas RESTful
Projete API robustas de transferência de ficheiros seguindo as boas práticas RESTful. Autenticação, limitação de pedidos, envios multipart e tratamento de erros.
Uma API REST de transferência de ficheiros bem concebida expõe cinco ou seis recursos (sessões, partes, partilhas, transferências, revogações), usa a semântica HTTP de forma honesta (POST para criar, PUT para fragmentos idempotentes, DELETE para revogação), e delega o movimento real de bytes para URLs de armazenamento pré-assinados para que o servidor nunca se torne o gargalo de largura de banda. A autenticação usa tokens bearer de curta duração sobre TLS 1.3, os limites de taxa diferenciam criação de leituras de metadados, os carregamentos fragmentados seguem o padrão tus de retomada ou a semântica multipart do S3, e os erros seguem o RFC 7807 Problem Details para que os clientes possam agir programaticamente.
Modelar o Recurso em Torno de Ações, Não de Ficheiros
Um erro comum é modelar a API como uma árvore de ficheiros. Os serviços de transferência de ficheiros são melhor modelados como três recursos:
/sessions— um carregamento em curso, criado por POST, populado via PUTs de fragmentos/shares— uma transferência concluída e endereçável com uma expiração e um orçamento de transferências/downloads— handles de acesso assinados e de curta duração para obter os bytes
As sessões tornam-se partilhas via uma ação complete; as partilhas expiram por tempo ou por orçamento de transferências. As revogações são PATCH numa partilha ou DELETE com um token de revogação. Sem substantivos para "ficheiro" ou "pasta" — esses são detalhes de implementação do armazenamento, não o contrato público.
Esta estrutura mantém a superfície da API pequena (menos de 10 endpoints), mapeia-se claramente para o cache HTTP (as partilhas têm Cache-Control: private, max-age=60; as transferências têm no-store), e permite substituir o backend de armazenamento sem quebrar os clientes.
Padrões de Autenticação e Autorização
Para APIs orientadas ao utilizador, emita JWTs de curta duração (TTL de 15 minutos) assinados com EdDSA, e renove-os via um cookie seguro HttpOnly. Coloque o token em Authorization: Bearer, nunca em strings de consulta onde é registado.
Para comunicação máquina-a-máquina, a assinatura de pedidos HMAC-SHA256 supera os tokens bearer porque prova a posse de uma chave sem a enviar. O AWS SigV4 é o design de referência:
Authorization: HEX4-HMAC-SHA256
Credential=AKIA.../20261202/eu/transfer/hex4_request,
SignedHeaders=host;x-hex-date;x-hex-content-sha256,
Signature=...
Para URLs de transferência pré-assinadas, os TTLs devem ser de minutos, não de horas. Uma janela de 15 minutos equilibra a usabilidade com o risco de um URL vazado ser reencaminhado. Inclua um bloqueio por IP apenas se conseguir tolerar quebrar utilizadores por trás de CGNAT — geralmente não consegue.
Carregamentos Fragmentados e Semântica Multipart
Existem dois protocolos credíveis para carregamentos fragmentados retomáveis: tus (rascunho IETF, cabeçalhos Upload-Offset e Upload-Length) e multipart do S3 (PartNumber, UploadId, ETag). Escolha um e comprometa-se. Inventar o seu próprio protocolo parece tentador e acaba mal quando percebe que precisa de gerir escritas parciais, fragmentos fora de ordem e sessões abandonadas.
O padrão tus em forma REST:
POST /sessions -> 201, Location: /sessions/abc
HEAD /sessions/abc -> 200, Upload-Offset: 104857600
PATCH /sessions/abc -> 204, corpo = próximo fragmento
POST /sessions/abc/complete -> 201, Location: /shares/xyz
DELETE /sessions/abc -> 204
Limites de tamanho de fragmento: mínimo de 5 MB para corresponder ao multipart do S3, máximo de 100 MB para manter o custo de nova tentativa limitado, padrão de 8 MB. Rejeite fragmentos que não se alinhem com o desvio anunciado com HTTP 409 Conflict mais um documento Problem que explica o desvio esperado.
Limitação de Taxa que Reflete Abuso Real
Os limites de taxa precisam de variar pelo custo do endpoint:
POST /sessions: 20 por IP por hora (caro — aloca armazenamento)PATCH /sessions/:id: 10.000 por hora por sessão (barato — escreve bytes)GET /shares/:id: 1.000 por IP por hora (consulta de metadados)GET /shares/:id/download: 100 por IP por hora (custo de egress)
Aplique limites na edge (Cloudflare, Fastly) para proteção de base, e uma segunda camada na aplicação (express-rate-limit, @fastify/rate-limit do Fastify) para controlo de picos. Retorne 429 com Retry-After em segundos. Inclua cabeçalhos de limite de taxa também nas respostas bem-sucedidas:
RateLimit-Limit: 20
RateLimit-Remaining: 17
RateLimit-Reset: 2843
Seguir o rascunho IETF RateLimit permite que clientes bem-comportados se auto-regulem em vez de serem bloqueados.
Respostas de Erro sobre as quais os Clientes Podem Agir
O RFC 7807 Problem Details é o padrão. Cada erro retorna Content-Type: application/problem+json:
{
"type": "https://api.example.com/errors/chunk-offset-mismatch",
"title": "Incompatibilidade de desvio de fragmento",
"status": 409,
"detail": "O servidor esperava o desvio 5242880, recebeu 4194304.",
"expected_offset": 5242880,
"session_id": "abc123"
}
O URI type deve ser documentado e estável; é nisso que os clientes fazem correspondência de padrões. title é genérico; detail é específico. Os campos personalizados acrescentam contexto acionável por máquina. Nunca exponha stack traces, caminhos de ficheiros ou IDs internos nos erros.
Mapeie os códigos de estado HTTP honestamente: 400 para entrada mal formada, 401 para autenticação em falta, 403 para autenticado-mas-não-autorizado, 404 apenas quando o recurso nunca existiu (use 410 Gone para partilhas expiradas), 413 para payloads acima da quota, 429 para limites de taxa, 500 para bugs, 503 para manutenção.
Negociação de Conteúdo e Streaming
Os endpoints de carregamento devem aceitar application/octet-stream e exigir Content-Length. Rejeite multipart/form-data para carregamentos de fragmentos — acrescenta overhead de análise e não beneficia ninguém. Aceite Content-Range para escritas parciais no estilo tus.
Os endpoints de transferência devem suportar pedidos HTTP Range (RFC 7233) para transferências retomáveis:
GET /shares/xyz/blob
Range: bytes=104857600-209715199
-> 206 Partial Content
Content-Range: bytes 104857600-209715199/2147483648
Isto é o que permite aos browsers retomar uma transferência de 2 GB após uma interrupção de Wi-Fi. A maioria dos armazenamentos compatíveis com S3 serve pedidos Range nativamente — a sua API apenas tem de reencaminhar ou pré-assinar.
Versionamento Sem Acumular Dívida
Versione via o caminho URL (/v1/sessions) e não via cabeçalhos. O versionamento por caminho é visível nos registos, pode ser colocado em cache e é mais fácil de depurar do que Accept: application/vnd.example.v1+json. Mantenha a v1 suportada durante pelo menos 24 meses após o lançamento da v2. Adicione campos livremente (os clientes devem ignorar campos desconhecidos); nunca remova ou renomeie campos numa versão estável.
Quando são necessárias alterações incompatíveis, execute v1 e v2 em paralelo durante 12 meses, inclua um cabeçalho Sunset nas respostas v1 conforme o RFC 8594, e publique guias de migração com exemplos reais antes/depois.
Observabilidade e Capacidade de Depuração
Cada resposta deve incluir um ID de correlação (X-Request-ID) retomado do pedido ou gerado. Registe o ID, o IP do cliente (com hash se for sensível à privacidade), o endpoint, o estado e a duração em JSON estruturado. Não registe os corpos dos pedidos — é assim que as chaves de cifração acabam no Datadog.
Emita métricas por endpoint: contagem de pedidos, latência p50/p95/p99, taxa de erros, bytes de entrada, bytes de saída. Alerte sobre picos de latência p99 e taxa de 5xx acima do valor base. Os rastreios via OpenTelemetry dão-lhe o fluxo de pedidos através da API, do armazenamento e da base de dados.
A API do HexaTransfer segue os padrões acima — recursos pequenos, carregamentos de fragmentos no estilo tus, erros Problem Details, transferências pré-assinadas de 15 minutos, cabeçalhos RateLimit. Experimente em hexatransfer.com — gratuito, sem conta necessária, máximo de 10 GB.
Documentação que Corresponde à Realidade
Publique uma especificação OpenAPI 3.1 juntamente com a API e mantenha-a no mesmo repositório que o código do servidor para que a divergência de esquema seja um problema de revisão de PR e não uma surpresa em produção. Gere pelo menos um SDK (TypeScript ou Python) a partir da especificação e use-o nos seus próprios exemplos — os bugs do SDK revelam rapidamente os bugs da especificação. Inclua exemplos curl para cada endpoint, um início rápido que carregue um ficheiro real em menos de 20 linhas, e uma página que documente especificamente cada URI de type de erro. Uma API que os programadores podem integrar numa tarde chegará a 10 vezes mais produtos do que uma que requer uma semana de engenharia inversa.
Envie arquivos grandes com segurança e criptografia de ponta a ponta
Transfira arquivos de até 10 GB gratuitamente com criptografia de ponta a ponta. Sem necessidade de conta. Seus arquivos são criptografados no navegador antes do envio — ninguém mais pode lê-los.
Enviar um arquivo