Expand description
Contains all HTTP endpoint handlers.
This module documents the request and response shape of every route; see the crate documentation for the layers a request passes through before reaching a handler.
Scopes are encoded in the URL path using Matrix URI syntax: org=123;project=456. An
underscore (_) represents empty scopes.
§Object Endpoints
All object operations live under the /v1/ prefix:
| Method | Path | Description |
|---|---|---|
POST | /v1/objects/{usecase}/{scopes}/ | Insert with server-generated key |
GET | /v1/objects/{usecase}/{scopes}/{*key} | Retrieve object |
HEAD | /v1/objects/{usecase}/{scopes}/{*key} | Retrieve metadata only |
PUT | /v1/objects/{usecase}/{scopes}/{*key} | Insert or overwrite with key |
DELETE | /v1/objects/{usecase}/{scopes}/{*key} | Delete object |
POST | /v1/objects:batch/{usecase}/{scopes}/ | Batch operations (multipart) |
Object metadata travels in request and response headers; see
objectstore_types::metadata for the mapping.
§Resumable Upload Endpoints
A resumable upload transfers a single object across several requests. The client opens a session, declaring the object’s total size and metadata upfront, and then sends the payload as a sequence of chunks at increasing byte offsets. If a chunk fails, the client can ask the server which offset it holds and continue from there, so an interrupted transfer resumes where it stopped instead of starting over. Clients are still encouraged to send the whole payload in a single request, as that’s the most efficient and reliable approach. The server knows the total size from the session, so it recognizes the chunk carrying the last byte and completes the upload itself.
Resumable uploads use the object endpoints above, selected by a query parameter:
upload_type=resumable opens a session, and session=<token> addresses it from then on.
Session creation returns an opaque token encoded once as unpadded base64url; that value can be
placed directly in the session query parameter.
The object is named by the request path as usual, and objectstore_types::resumable
holds the protocol types.
| Method | Path | Description |
|---|---|---|
POST | /v1/objects/{usecase}/{scopes}/?upload_type=resumable | Create session (server-generated key) |
PUT | /v1/objects/{usecase}/{scopes}/{*key}?upload_type=resumable | Create session (user-provided key) |
PUT | /v1/objects/{usecase}/{scopes}/{*key}?session=<token> | Upload a chunk, or query the offset |
DELETE | /v1/objects/{usecase}/{scopes}/{*key}?session=<token> | Cancel upload, discarding what was sent |
Session creation requires an Upload-Length header carrying the total size of the object
in bytes, takes the same metadata headers as a regular upload, and requires an empty body.
It answers 200 OK with {"key", "session"}; the session field is the token to use in
subsequent query parameters. Metadata is fixed at this point and does not change afterwards.
Chunk uploads and offset queries share one request shape, distinguished by the
Upload-Offset header: a byte offset submits the body as the chunk starting there, while
the * wildcard submits an empty body and asks which offset the server holds. Both answer
204 No Content with the authoritative Upload-Offset while bytes remain, and
201 Created with {"key"} once the upload is complete and the object is available through
the normal object endpoints. The session is terminal at that point.
The offset in the response may be lower than the end of the last chunk that was sent.
Backends can e.g. persist only aligned prefixes and discard the remainder, so clients must
always continue from the returned offset.
Every chunk requires Content-Length, even over HTTP/2, while creation and offset queries
must not carry a request body.
An offset query can finish pending backend publication work, so it requires write permission despite being read-shaped. Termination likewise needs write rather than delete permission: it releases an in-progress upload, not an object.
| Status | Meaning | Client action |
|---|---|---|
400 | Malformed session token, missing Upload-Length, nonempty offset query, or a chunk exceeding the declared length | Correct the request |
404 | The upload session is unknown or does not belong to this object | Start a new session or correct the request |
409 | A chunk’s offset does not match the authoritative offset | Query the offset and continue from there |
410 | The session expired or was canceled | Start a new session |
501 | The server declined the resumable upload session creation for the requested object | Fall back to a regular upload |
§Multipart Upload Endpoints
Multipart uploads are being replaced by resumable
uploads and will be removed once all consumers have
migrated. See objectstore_types::multipart for the protocol types.
| Method | Path | Description |
|---|---|---|
POST | /v1/objects:multipart/{usecase}/{scopes}/ | Initiate upload (server-generated key) |
PUT | /v1/objects:multipart/{usecase}/{scopes}/{*key} | Initiate upload (user-provided key) |
PUT | /v1/objects:multipart:parts/{usecase}/{scopes}/{*key} | Upload a part (upload_id, part_number query params) |
GET | /v1/objects:multipart:parts/{usecase}/{scopes}/{*key} | List uploaded parts (upload_id query param) |
POST | /v1/objects:multipart:complete/{usecase}/{scopes}/{*key} | Complete upload (upload_id query param) |
DELETE | /v1/objects:multipart/{usecase}/{scopes}/{*key} | Abort upload (upload_id query param) |
The initiate POST endpoint accepts both trailing-slash and non-trailing-slash forms.
The complete endpoint returns 200 OK immediately, with a streaming body that will
contain the error (if any) as JSON. Whitespace is sent in the streaming body to keep the
connection open. Clients must parse the body to determine the actual outcome, and not rely
on the status code.
§Internal Endpoints
Internal endpoints are exempt from authentication, rate limiting, and the web concurrency
limit so they remain available when the server is under load. is_internal_route
identifies them.
| Method | Path | Description |
|---|---|---|
GET | /health | Liveness probe (always returns 200) |
GET | /ready | Readiness probe (returns 503 when /tmp/objectstore.down exists, enabling graceful drain) |
GET | /keda | Prometheus text-format gauges for KEDA autoscaling (see KEDA Metrics) |
§Code Usage
Use routes to create a router with all endpoints.
Modules§
Functions§
- is_
internal_ route - Returns
truefor internal endpoints that are exempt from metrics and concurrency limits. - routes
- Returns a router with all objectstore HTTP endpoints mounted.