Ir para o conteúdo
HexaTransfer
Voltar ao blog
Analises tecnicas

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