Vai al contenuto
HexaTransfer
Torna al blog
Approfondimenti tecnici

Progettazione API per trasferimento file: pratiche RESTful

Progetta API robuste per il trasferimento file secondo le migliori pratiche RESTful. Autenticazione, limitazione delle richieste, upload multipart e gestione errori.

Il GDPR, in combinazione con le linee guida dell'ACN (Agenzia per la Cybersicurezza Nazionale), impone che le API che trattano dati personali usino protocolli crittografici aggiornati e gestiscano le credenziali in modo sicuro. Un'API REST ben progettata per il trasferimento file espone cinque o sei risorse (sessioni, parti, condivisioni, download, revoche), usa la semantica HTTP onestamente (POST per creare, PUT per blocchi idempotenti, DELETE per la revoca), e spinge il movimento effettivo dei byte verso URL di storage presegnati affinché il server non diventi mai il collo di bottiglia della banda. L'autenticazione usa token bearer a breve durata su TLS 1.3, i rate limit differenziano la creazione dalle letture di metadati, gli upload a blocchi seguono il protocollo tus.io ripristinabile o la semantica multipart S3, e gli errori seguono RFC 7807 Problem Details affinché i client possano agire su di essi a livello programmatico.

Modella le risorse attorno alle azioni, non ai file

Un errore comune è modellare l'API come un albero di file. I servizi di trasferimento file sono meglio modellati come tre risorse:

  • /sessions — un upload in corso, creato con POST, popolato tramite PUT dei blocchi
  • /shares — un trasferimento completato e indirizzabile con una scadenza e un budget di download
  • /downloads — handle di accesso firmati e di breve durata per recuperare i byte

Le sessioni diventano condivisioni tramite un'azione complete; le condivisioni diventano scadute tramite il tempo o il budget di download. Le revoche sono PATCH su una condivisione o DELETE con un token di revoca. Nessun sostantivo per "file" o "cartella" — questi sono dettagli implementativi dello storage, non il tuo contratto pubblico.

Questa forma mantiene la superficie dell'API piccola (sotto i 10 endpoint), si mappa in modo pulito alla cache HTTP (le condivisioni sono Cache-Control: private, max-age=60; i download sono no-store), e ti consente di cambiare i backend di storage senza rompere i client.

Pattern di autenticazione e autorizzazione

Per le API rivolte agli utenti, emetti JWT a breve durata (TTL di 15 minuti) firmati con EdDSA, e aggiorna tramite un cookie HttpOnly sicuro. Metti il token in Authorization: Bearer, mai nelle query string dove finisce nei log.

Per le connessioni machine-to-machine, la firma delle richieste HMAC-SHA256 batte i token bearer perché prova il possesso di una chiave senza inviarla. AWS SigV4 è il design di riferimento:

Authorization: HEX4-HMAC-SHA256 
  Credential=AKIA.../20261202/eu/transfer/hex4_request,
  SignedHeaders=host;x-hex-date;x-hex-content-sha256,
  Signature=...

Per gli URL di download presegnati, i TTL devono essere di minuti, non di ore. Una finestra di 15 minuti bilancia l'usabilità rispetto al rischio che un URL trapelato venga inoltrato. Includi un blocco IP solo se puoi tollerare di rompere gli utenti dietro CGNAT — di solito non puoi.

Upload a blocchi e semantica multipart

Esistono due protocolli validi per gli upload a blocchi ripristinabili: tus.io (bozza IETF, header Upload-Offset e Upload-Length) e S3 multipart (PartNumber, UploadId, ETag). Scegli uno e impegnati. Inventare il proprio protocollo sembra allettante e finisce male quando ci si rende conto di dover gestire scritture parziali, blocchi fuori ordine e sessioni abbandonate.

Il pattern tus in forma REST:

POST   /sessions              -> 201, Location: /sessions/abc
HEAD   /sessions/abc          -> 200, Upload-Offset: 104857600
PATCH  /sessions/abc          -> 204, body = blocco successivo
POST   /sessions/abc/complete -> 201, Location: /shares/xyz
DELETE /sessions/abc          -> 204

Limiti di dimensione dei blocchi: minimo 5 MB per corrispondere al multipart S3, massimo 100 MB per mantenere limitato il costo dei tentativi, default 8 MB. Rifiuta i blocchi che non si allineano con l'offset annunciato con HTTP 409 Conflict più un documento Problem che spiega l'offset atteso.

Rate limiting che riflette il vero abuso

I rate limit devono variare in base al costo dell'endpoint:

  • POST /sessions: 20 per IP per ora (costoso — alloca storage)
  • PATCH /sessions/:id: 10.000 per ora per sessione (economico — scrive byte)
  • GET /shares/:id: 1.000 per IP per ora (ricerca di metadati)
  • GET /shares/:id/download: 100 per IP per ora (costo di egress)

Applica i limiti al bordo (Cloudflare, Fastly) per la protezione di base, e un secondo strato a livello applicativo (express-rate-limit, @fastify/rate-limit di Fastify) per il controllo delle raffiche. Restituisci 429 con Retry-After in secondi. Includi gli header di rate limit anche sulle risposte di successo:

RateLimit-Limit: 20
RateLimit-Remaining: 17
RateLimit-Reset: 2843

Seguire la bozza IETF RateLimit consente ai client ben educati di regolare il proprio ritmo invece di essere bloccati.

Risposte di errore su cui i client possono agire

RFC 7807 Problem Details è lo standard. Ogni errore restituisce Content-Type: application/problem+json:

{
  "type": "https://api.esempio.com/errors/chunk-offset-mismatch",
  "title": "Mancata corrispondenza offset blocco",
  "status": 409,
  "detail": "Il server si aspettava l'offset 5242880, ricevuto 4194304.",
  "expected_offset": 5242880,
  "session_id": "abc123"
}

L'URI type deve essere documentato e stabile; è quello su cui i client fanno corrispondenza di pattern. title è generico; detail è specifico. I campi personalizzati aggiungono contesto interpretabile dalla macchina. Non rivelare mai stack trace, percorsi di file o ID interni negli errori.

Mappa i codici di stato HTTP onestamente: 400 per input malformato, 401 per autenticazione mancante, 403 per autenticato-ma-non-autorizzato, 404 solo quando la risorsa non è mai esistita (usa 410 Gone per le condivisioni scadute), 413 per i payload sopra la quota, 429 per i rate limit, 500 per i bug, 503 per la manutenzione.

Negoziazione del contenuto e streaming

Gli endpoint di upload devono accettare application/octet-stream e richiedere Content-Length. Rifiuta multipart/form-data per gli upload a blocchi — aggiunge overhead di parsing e non aiuta nessuno. Accetta Content-Range per le scritture parziali in stile tus.

Gli endpoint di download devono supportare le richieste HTTP Range (RFC 7233) per i download ripristinabili:

GET /shares/xyz/blob
Range: bytes=104857600-209715199
-> 206 Partial Content
   Content-Range: bytes 104857600-209715199/2147483648

Questo è ciò che consente ai browser di riprendere un download da 2 GB dopo un'interruzione Wi-Fi. La maggior parte degli store compatibili con S3 gestisce le richieste Range nativamente — la tua API deve solo inoltrarle o presegnarle.

Versionamento senza accumulare debiti

Versiona tramite il percorso URL (/v1/sessions) non tramite gli header. Il versionamento del percorso è visibile nei log, memorizzabile nella cache e più facile da debuggare rispetto a Accept: application/vnd.example.v1+json. Mantieni v1 supportato per almeno 24 mesi dopo il rilascio di v2. Aggiungi liberamente campi (i client devono ignorare quelli sconosciuti); non rimuovere mai o rinominare campi in una versione stabile.

Quando sono necessarie modifiche sostanziali, esegui v1 e v2 in parallelo per 12 mesi, includi un header Sunset sulle risposte v1 secondo RFC 8594, e pubblica guide di migrazione con esempi reali prima e dopo.

Osservabilità e debuggabilità

Ogni risposta deve includere un ID di correlazione (X-Request-ID) ripreso dalla richiesta o generato. Registra l'ID, l'IP del client (hashato se sensibile alla privacy), l'endpoint, lo stato e la durata in JSON strutturato. Non registrare i corpi delle richieste — è così che le chiavi di crittografia finiscono in Datadog.

Emetti metriche per endpoint: conteggio richieste, latenza p50/p95/p99, tasso di errore, byte in entrata, byte in uscita. Avvisa sugli spike di latenza p99 e sul tasso di errori 5xx sopra la baseline. Le trace tramite OpenTelemetry offrono il flusso delle richieste attraverso API, storage e database.

L'API di HexaTransfer segue gli schemi sopra — risorse brevi, upload a blocchi in stile tus, errori Problem Details, download presegnati di 15 minuti, header RateLimit. Prova su https://hexatransfer.com — gratuito, senza account, massimo 10 GB.

Documentazione che corrisponde alla realtà

Pubblica una specifica OpenAPI 3.1 insieme all'API e mantienila nello stesso repository del codice server affinché la deriva dello schema sia un problema di revisione PR invece che una sorpresa in produzione. Genera almeno un SDK (TypeScript o Python) dalla specifica e usalo nei tuoi esempi — i bug dell'SDK evidenziano i bug della specifica rapidamente. Includi esempi curl per ogni endpoint, un quickstart che carica un file reale in meno di 20 righe, e una pagina che documenta specificamente ogni URI type di errore. Un'API che gli sviluppatori possono integrare in un pomeriggio raggiungerà 10 volte più prodotti rispetto a una che richiede una settimana di reverse engineering.

Invia file di grandi dimensioni in modo sicuro con crittografia end-to-end

Trasferisci file fino a 10 GB gratuitamente con crittografia end-to-end. Nessun account necessario. I tuoi file vengono crittografati nel browser prima del caricamento — nessun altro può leggerli.

Invia un file