Ga naar inhoud
HexaTransfer
Terug naar blog
Technische verdiepingen

API-ontwerp voor bestandsoverdracht: RESTful beste praktijken

Ontwerp robuuste API's voor bestandsoverdracht volgens RESTful beste praktijken. Authenticatie, snelheidsbeperking, multipart-uploads en foutafhandeling.

Een goed ontworpen bestandsoverdracht-REST-API stelt vijf of zes resources bloot (sessies, onderdelen, shares, downloads, intrekkingen), gebruikt HTTP-semantiek eerlijk (POST voor aanmaken, PUT voor idempotente stukken, DELETE voor intrekking) en verplaatst de werkelijke bytestroom naar presigned opslag-URL's zodat uw server nooit de bandbreedtebegrenzing wordt. Authenticatie gebruikt kortlevende bearer-tokens over TLS 1.3, snelheidslimieten differentiëren tussen aanmaken en metadatalezen, chunked uploads volgen het tus.io-hervattingspatroon of S3-multipart-semantiek, en fouten volgen RFC 7807 Problem Details zodat clients er programmatisch op kunnen reageren. De Autoriteit Persoonsgegevens (AP) verwacht dat u passende maatregelen treft om onbevoegde toegang tot persoonsgegevens te voorkomen — een goed API-ontwerp is een van die maatregelen.

Modelleer het resource-model rond acties, niet bestanden

Een veelgemaakte fout is het modelleren van de API als een bestandsstructuur. Bestandsoverdrachtsservices zijn beter te modelleren als drie resources:

  • /sessions — een lopende upload, aangemaakt via POST, gevuld via chunk-PUT's
  • /shares — een voltooide, adresseerbare overdracht met een vervaldatum en downloadbudget
  • /downloads — kortlevende, ondertekende toegangshandvatten voor het ophalen van bytes

Sessies worden shares via een complete-actie; shares verlopen via tijd of downloadbudget. Intrekkingen zijn PATCH op een share of DELETE met een intrekkingstoken. Geen zelfstandige naamwoorden voor "bestand" of "map" — dat zijn implementatiedetails van de opslag, niet uw publieke contract.

Deze vorm houdt het API-oppervlak klein (onder de tien eindpunten), past netjes bij HTTP-caching (shares zijn Cache-Control: private, max-age=60; downloads zijn no-store), en laat u opslagbackends wisselen zonder clients te breken.

Authenticatie- en autorisatiepatronen

Voor gebruikergerichte API's geeft u kortlevende JWT's uit (TTL van 15 minuten) ondertekend met EdDSA, en vernieuwt u die via een veilige HttpOnly-cookie. Zet het token in Authorization: Bearer, nooit in querystrings waar het wordt gelogd.

Voor machine-to-machine-communicatie slaat HMAC-SHA256-aanvraagondertekening bearer-tokens omdat het sleutelbezit bewijst zonder de sleutel te versturen. AWS SigV4 is het referentieontwerp:

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

Voor presigned download-URL's gelden TTL's van minuten, niet uren. Een venster van 15 minuten balanceert bruikbaarheid tegen het risico van een gelekte URL die wordt doorgestuurd. Voeg een IP-vergrendeling toe alleen als u kunt verdragen dat gebruikers achter CGNAT worden geblokkeerd — meestal kunt u dat niet.

Chunked uploads en multipart-semantiek

Er bestaan twee geloofwaardige protocollen voor hervattbare chunked uploads: tus.io (IETF-draft, Upload-Offset- en Upload-Length-headers) en S3-multipart (PartNumber, UploadId, ETag). Kies één en houd u eraan. Een eigen protocol uitvinden ziet er verleidelijk uit en eindigt slecht zodra u merkt dat u partiële schrijfacties, stukken buiten volgorde en verlaten sessies moet afhandelen.

Het tus-patroon in REST-vorm:

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

Stukgroottegrenzen: minimaal 5 MB om overeen te komen met S3-multipart, maximaal 100 MB om de herprobeerkost begrensd te houden, standaard 8 MB. Wijs stukken af die niet aansluiten op de aangekondigde offset met HTTP 409 Conflict plus een Problem-document dat de verwachte offset uitlegt.

Snelheidsbeperking die echte misbruikpatronen weerspiegelt

Snelheidslimieten moeten variëren op basis van eindpuntkosten:

  • POST /sessions: 20 per IP per uur (duur — alloceert opslag)
  • PATCH /sessions/:id: 10.000 per uur per sessie (goedkoop — schrijft bytes)
  • GET /shares/:id: 1.000 per IP per uur (metadataopzoek)
  • GET /shares/:id/download: 100 per IP per uur (egresskosten)

Pas limieten toe aan de rand (Cloudflare, Fastly) voor basisbeveiliging, en een tweede laag in de applicatie (express-rate-limit, Fastify's @fastify/rate-limit) voor burst-controle. Retourneer 429 met Retry-After in seconden. Neem snelheidslimiettellers ook op in succesvolle antwoorden:

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

Het IETF RateLimit-draft volgen laat goedbedoelende clients hun tempo aanpassen in plaats van geblokkeerd te worden.

Foutantwoorden waarop clients kunnen handelen

RFC 7807 Problem Details is de standaard. Elke fout retourneert Content-Type: application/problem+json:

{
  "type": "https://api.example.com/errors/chunk-offset-mismatch",
  "title": "Stukoffset-mismatch",
  "status": 409,
  "detail": "Server verwachtte offset 5242880, ontving 4194304.",
  "expected_offset": 5242880,
  "session_id": "abc123"
}

De type-URI moet gedocumenteerd en stabiel zijn — dat is waar clients op matchen. title is generiek; detail is specifiek. Aangepaste velden voegen machine-bruikbare context toe. Lek nooit stacktracering, bestandspaden of interne ID's in fouten.

Wijs HTTP-statuscodes eerlijk toe: 400 voor misvormde invoer, 401 voor ontbrekende authenticatie, 403 voor geauthenticeerd-maar-ongeautoriseerd, 404 alleen wanneer de resource nooit heeft bestaan (gebruik 410 Gone voor verlopen shares), 413 voor payloads boven quotum, 429 voor snelheidslimieten, 500 voor bugs, 503 voor onderhoud.

Content-onderhandeling en streaming

Upload-eindpunten accepteren application/octet-stream en vereisen Content-Length. Wijs multipart/form-data af voor chunk-uploads — dat voegt parseeroverhead toe en helpt niemand. Accepteer Content-Range voor tus-stijl partiële schrijfacties.

Download-eindpunten ondersteunen HTTP Range-verzoeken (RFC 7233) voor hervattbare downloads:

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

Dit is wat browsers in staat stelt een download van 2 GB te hervatten na een wifi-onderbreking. De meeste S3-compatibele opslagsystemen serveren Range-verzoeken native — uw API hoeft ze alleen door te sturen of te presignen.

Versiebeheer zonder schulden op te bouwen

Versie via het URL-pad (/v1/sessions) niet via headers. Padversie is zichtbaar in logs, cacheerbaar en gemakkelijker te debuggen dan Accept: application/vnd.example.v1+json. Ondersteun v1 minimaal 24 maanden nadat v2 is uitgebracht. Voeg vrij velden toe (clients moeten onbekende velden negeren); verwijder of hernoem nooit velden in een stabiele versie.

Bij onvermijdelijke wijzigingen draait u v1 en v2 twaalf maanden parallel, geeft u een Sunset-header mee bij v1-antwoorden conform RFC 8594 en publiceert u migratiegidsen met echte voor-en-na-voorbeelden.

Waarneembaarheid en debuggeerbaarheid

Elk antwoord bevat een correlatie-ID (X-Request-ID) gekopieerd van het verzoek of gegenereerd. Log de ID, client-IP (gehasht als privacygevoelig), eindpunt, status en duur in gestructureerd JSON. Log aanvraagbodies niet — zo belanden versleutelingssleutels in Datadog.

Emit statistieken per eindpunt: aanvraagaantal, p50/p95/p99-latentie, foutpercentage, bytes in, bytes uit. Waarschuw bij p99-latentiepieken en 5xx-percentage boven basislijn. Traces via OpenTelemetry geven u de aanvraagstroom over API, opslag en database.

HexaTransfer's API volgt de bovenstaande patronen — compacte resources, tus.io-stijl chunk-uploads, Problem Details-fouten, presigned downloads van 15 minuten, RateLimit-headers. Probeer het op https://hexatransfer.com — gratis, geen account vereist, maximaal 10 GB.

Documentatie die de werkelijkheid weerspiegelt

Publiceer een OpenAPI 3.1-specificatie naast de API en bewaar die in dezelfde repository als de servercode zodat schemadrift een PR-reviewkwestie is, geen productieverrassing. Genereer minimaal één SDK (TypeScript of Python) uit de specificatie en gebruik die in uw eigen voorbeelden — SDK-bugs onthullen snelle specificatiebugs. Neem curl-voorbeelden op voor elk eindpunt, een quickstart die een echt bestand uploadt in minder dan twintig regels, en een pagina die elke fout-type-URI documenteert. Een API die ontwikkelaars in een middag kunnen integreren, verschijnt in tien keer zoveel producten als één die een week van reverse-engineering vergt.

Verstuur grote bestanden veilig met end-to-end-versleuteling

Draag bestanden tot 10 GB gratis over met end-to-end-versleuteling. Geen account nodig. Uw bestanden worden in uw browser versleuteld voordat ze worden geüpload — niemand anders kan ze lezen.

Een bestand verzenden