HTTP API Reference
HTTP API Reference
Section titled “HTTP API Reference”Stowry provides a REST API for object storage operations. All endpoints support presigned URL authentication.
Base URL
Section titled “Base URL”http://localhost:5708Authentication
Section titled “Authentication”Requests require presigned URL authentication unless public_read or public_write is enabled. See Authentication for details.
Endpoints
Section titled “Endpoints”List Objects
Section titled “List Objects”Store mode only. Not available in static or SPA modes.
List objects with optional prefix filtering and pagination.
GET /Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
prefix | string | - | Filter objects by path prefix |
limit | int | 100 | Maximum objects per page (1-1000) |
cursor | string | - | Pagination cursor from previous response |
Response: 200 OK
{ "items": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "path": "photos/vacation.jpg", "content_type": "image/jpeg", "etag": "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e", "file_size_bytes": 1048576, "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:30:00Z" } ], "next_cursor": "MjAyNC0wMS0xNVQxMDozMDowMFp8cGhvdG9zL3ZhY2F0aW9uLmpwZw=="}Example:
# List all objectscurl "http://localhost:5708/"
# List with prefixcurl "http://localhost:5708/?prefix=photos/"
# Paginatecurl "http://localhost:5708/?limit=10&cursor=MjAyNC0wMS0..."Get Object
Section titled “Get Object”Download an object by path.
GET /{path}Path Parameters:
| Parameter | Description |
|---|---|
path | Object path (e.g., photos/vacation.jpg) |
Response Headers:
| Header | Description |
|---|---|
Content-Type | MIME type of the object |
ETag | Object hash (SHA256) |
Content-Length | Object size in bytes |
Last-Modified | Last modification time |
Response: 200 OK with file content
Errors:
| Status | Error Code | Description |
|---|---|---|
| 400 | invalid_path | Invalid path format |
| 404 | not_found | Object not found |
Example:
# Download objectcurl -O http://localhost:5708/photos/vacation.jpgServer Mode Behavior:
- Store: Returns exact path or 404 (JSON)
- Static: Tries exact →
{path}.html→{path}/index.html→ 404 (HTML) - SPA: Falls back to
/index.htmlfor client-side routing
Head Object
Section titled “Head Object”Retrieve object metadata without downloading the file body.
HEAD /{path}Path Parameters:
| Parameter | Description |
|---|---|
path | Object path (e.g., photos/vacation.jpg) |
Response Headers:
| Header | Description |
|---|---|
Content-Type | MIME type of the object |
ETag | Object hash (SHA256), quoted |
Content-Length | Object size in bytes |
Last-Modified | Last modification time |
Accept-Ranges | Indicates byte-range support |
Conditional Headers:
| Header | Description |
|---|---|
If-None-Match | Returns 304 Not Modified if ETag matches (weak comparison per RFC 9110) |
If-Modified-Since | Returns 304 Not Modified if object hasn’t changed since the given time |
If-None-Match takes precedence over If-Modified-Since per RFC 7232.
Response: 200 OK (empty body)
Errors:
| Status | Error Code | Description |
|---|---|---|
| 304 | - | Not modified (conditional request) |
| 400 | invalid_path | Invalid path format |
| 404 | not_found | Object not found |
Example:
# Get metadatacurl -I http://localhost:5708/photos/vacation.jpg
# Conditional request (ETag)curl -I -H 'If-None-Match: "a591a6d..."' http://localhost:5708/photos/vacation.jpg
# Conditional request (time)curl -I -H "If-Modified-Since: Wed, 15 Jan 2024 10:30:00 GMT" http://localhost:5708/photos/vacation.jpgServer Mode Behavior:
Same fallback logic as GET — applies static and SPA mode path resolution. Returns 404 HTML in static mode.
Upload Object
Section titled “Upload Object”Store mode only. Returns
405 Method Not Allowedin static and SPA modes.
Upload or overwrite an object.
PUT /{path}Path Parameters:
| Parameter | Description |
|---|---|
path | Object path (e.g., photos/vacation.jpg) |
Request Headers:
| Header | Required | Description |
|---|---|---|
Content-Type | No | MIME type (auto-detected if not provided) |
If-Match | No | Conditional update — ETag must match; returns 412 if object doesn’t exist (per RFC 9110 §13.1.1) |
Request Body: Raw file content
Response: 200 OK
{ "id": "550e8400-e29b-41d4-a716-446655440000", "path": "photos/vacation.jpg", "content_type": "image/jpeg", "etag": "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e", "file_size_bytes": 1048576, "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:30:00Z"}Errors:
| Status | Error Code | Description |
|---|---|---|
| 400 | invalid_path | Invalid path format |
| 412 | precondition_failed | ETag mismatch (If-Match) |
| 500 | internal_error | Server error |
Example:
# Upload filecurl -X PUT \ -H "Content-Type: image/jpeg" \ --data-binary @vacation.jpg \ http://localhost:5708/photos/vacation.jpg
# Conditional updatecurl -X PUT \ -H "If-Match: a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e" \ --data-binary @vacation.jpg \ http://localhost:5708/photos/vacation.jpgDelete Object
Section titled “Delete Object”Store mode only. Returns
405 Method Not Allowedin static and SPA modes.
Soft delete an object (marks for deletion but doesn’t remove immediately).
DELETE /{path}Path Parameters:
| Parameter | Description |
|---|---|
path | Object path (e.g., photos/vacation.jpg) |
Response: 204 No Content
Errors:
| Status | Error Code | Description |
|---|---|---|
| 400 | invalid_path | Invalid path format |
| 404 | not_found | Object not found |
Example:
curl -X DELETE http://localhost:5708/photos/vacation.jpgNote: Deleted objects remain in storage until stowry cleanup is run.
Error Response Format
Section titled “Error Response Format”All errors return JSON:
{ "error": "error_code", "message": "Human-readable error message"}Path Validation
Section titled “Path Validation”Valid paths must:
- Be relative (no leading
/) - Contain no path traversal (
..) - Contain no empty segments (
//) - Contain no invalid characters (
\ ? # ~) - Be valid UTF-8
- Have no trailing slashes
Valid paths:
file.txtphotos/vacation.jpgdata/2024/01/report.pdf
Invalid paths:
/file.txt(leading slash)../secret.txt(path traversal)folder//file.txt(empty segment)file?.txt(invalid character)
Content Type Detection
Section titled “Content Type Detection”If Content-Type header is not provided on upload, Stowry detects it from the file extension:
| Extension | Content Type |
|---|---|
.html | text/html |
.css | text/css |
.js | application/javascript |
.json | application/json |
.png | image/png |
.jpg, .jpeg | image/jpeg |
.gif | image/gif |
.svg | image/svg+xml |
.pdf | application/pdf |
| (unknown) | application/octet-stream |
Pagination
Section titled “Pagination”List responses use cursor-based pagination:
- Make initial request:
GET /?limit=10 - If
next_cursoris present in response, there are more results - Request next page:
GET /?limit=10&cursor={next_cursor} - Repeat until
next_cursoris empty or null
Benefits:
- Consistent results during concurrent modifications
- Efficient for large datasets
- No offset skipping issues