Skip to content

TUS Protocol Compliance

Compliance status against the TUS resumable upload protocol v1.0.0.

Extensions

Extension Status Notes
core ✅ Implemented POST / HEAD / PATCH, offset tracking, version negotiation
creation ✅ Implemented Upload creation via POST with Upload-Length
creation-with-upload ✅ Implemented Initial data in POST body (Content-Type: application/offset+octet-stream)
termination ✅ Implemented Upload deletion via DELETE
checksum ✅ Implemented SHA1 (Upload-Checksum header); Tus-Checksum-Algorithm: sha1 advertised in OPTIONS
expiration ✅ Implemented Upload-Expires in POST / HEAD / PATCH responses; periodic server-side cleanup
concatenation ❌ Not implemented Combining parallel partial uploads

Version Negotiation

Requirement Status
Client sends Tus-Resumable on all non-OPTIONS requests
Server returns Tus-Resumable on all responses
Server returns 412 on version mismatch
Server skips version check for OPTIONS
Server advertises supported versions in Tus-Version (OPTIONS)

Core Protocol — Server

Requirement Status Notes
POST creates new upload, returns 201 + Location
POST returns 400 on missing/invalid Upload-Length
POST returns 400 on negative Upload-Length
POST returns 413 when upload exceeds Tus-Max-Size
HEAD returns 200 with Upload-Offset + Upload-Length
HEAD includes Cache-Control: no-store
HEAD returns 404 for unknown upload
PATCH appends data, returns 204 + updated Upload-Offset
PATCH returns 415 on wrong Content-Type Must be application/offset+octet-stream
PATCH returns 409 on Upload-Offset mismatch
PATCH returns 400 on negative Upload-Offset
PATCH returns 400 if chunk would exceed Upload-Length
PATCH returns 460 on checksum mismatch Non-standard but widely used
PATCH returns 410 on expired upload
OPTIONS returns 204 with server capabilities
OPTIONS includes Tus-Checksum-Algorithm Reports sha1
DELETE removes upload, returns 204
DELETE returns 404 for unknown upload
Malformed Content-Length header → 400
Negative Content-Length400
Upload-Metadata larger than 4 KB → 400 DoS protection
Invalid base64 in Upload-Metadata400
Socket read timeout (Slowloris protection) TusHTTPRequestHandler.setup() applies request_timeout (default 30s)

Core Protocol — Client

Requirement Status Notes
Sends Tus-Resumable: 1.0.0 on all requests
POST to create upload with Upload-Length
HEAD to get current offset before resuming
PATCH with Upload-Offset and correct Content-Type
Content-Length: 0 in DELETE request
Configurable timeout on all urlopen() calls Default 30s
Catches URLError (network-level) alongside HTTPError
Exponential backoff with cap (max 60s)
SHA1 checksum via Upload-Checksum header Optional
Cross-session URL persistence (fingerprint-based) FileURLStorage
Full-file fingerprint (not just first 64 KB) SHA-256 of entire content
409 on concurrent offset conflict (atomic CAS) UPDATE ... WHERE offset = ?; returns 409 if row not updated
409 received → HEAD re-sync before retry Client fetches current offset and re-seeks before retrying chunk

Not Implemented

Feature Notes
concatenation extension Combining multiple partial uploads
X-HTTP-Method-Override For environments blocking PATCH/DELETE
Upload-Defer-Length Deferred length (part of creation extension)
Multiple TUS version support Only 1.0.0 supported

Error Response Reference

Status Meaning Trigger
400 Bad Request Missing/invalid header, negative offset, chunk overflow, oversized metadata
404 Not Found Unknown upload ID
409 Conflict Upload-Offset mismatch or concurrent write conflict
410 Gone Upload has expired
412 Precondition Failed Unsupported TUS version
413 Payload Too Large Exceeds Tus-Max-Size
415 Unsupported Media Type Wrong Content-Type in PATCH
460 Checksum Mismatch SHA1 verification failed

References