Skip to content

sharify-labs/zephyr

Repository files navigation

Zephyr

The upload service for the Sharify platform.

Zephyr works alongside other Sharify components:

  • Canvas: Serves uploaded content to end users
  • Spine: Web panel backend for user/content management
  • Sharify-Go: Go SDK for programmatic uploads
  • Sharify-Desktop: Cross-platform desktop app

Note: This project is not actively maintained and should not be used in a production environment.

What it does

Zephyr handles all the core upload functionality for Sharify - creating uploads, managing storage, user authentication, and serving the REST API that everything else talks to.
When you upload content to Sharify (via the web panel, desktop app, API, etc.), it ultimately ends up hitting Zephyr.

Key Features

  • Processing uploads (images, files, pastes, redirects)
  • Storing everything in Cloudflare R2 with Redis caching
  • User authentication via API tokens or JWT (for web panel)
  • Managing upload metadata and expiration
  • Bulk operations like deleting multiple uploads

How requests flow

API Request → Authentication → Validation → Store in R2 → Save to Database → Return URL

The interesting parts:

  • Storage keys are SHA-512 hashes of hostname + secret to avoid collisions
  • EXIF data is stripped from PNG/JPEG images for privacy
  • Byte data is prefixed with a type byte (0x00=image, 0x01=file, etc.) before storage
  • Expired temporary uploads get cleaned up automatically every 15 minutes

API endpoints

All endpoints need authentication via Authorization header:

Upload Management

# Create upload
POST /api/v1/uploads
Content-Type: multipart/form-data

# List uploads with filtering
GET /api/v1/uploads?page=1&limit=20&types=image,file&sortBy=date&order=desc

# Edit upload metadata  
PATCH /api/v1/uploads/{storage_key}
Content-Type: multipart/form-data

# Bulk delete uploads
DELETE /api/v1/uploads
Content-Type: application/json
Body: ["storage_key_1", "storage_key_2"]

Domain Management

# List available domains for user
GET /api/v1/hosts

Upload Types

Type Content Use Case
Image PNG, JPEG, GIF, WebP Screenshots, photos (EXIF stripped)
File Any binary content Documents, archives, executables
Paste Plain text Code snippets, logs, notes
Redirect URL strings Link shortening with custom domains

Request Parameters

Creating Uploads

# Required (choose one)
[email protected]              # File upload
paste_content="code here"    # Text content  
long_url="https://..."       # URL to shorten

# Optional metadata
title="My Upload"                  # Display name
host="myname.example.com"          # Custom subdomain
secret="custom-path"               # Custom URL path (a-Z, 0-9, -, _)
expiration="2024-12-31T23:59:59Z"  # ISO 8601 datetime
duration="72"                      # Hours until expiration

Filtering Uploads

# Pagination & Sorting
?page=1&limit=50&sortBy=date&order=desc

# Content Filtering
?types=image,file         # Filter by upload type
?hosts=i.example.com      # Filter by hostname
?mimes=image/jpeg         # Filter by MIME type
?secrets=abc123,def456    # Filter by specific secrets

Storage Format

All content in R2 is prefixed with a single byte type indicator:

R2 Object: [type_byte][content_data]

Type Indicators:
0x00 = Image
0x01 = File  
0x02 = Paste
0x03 = Redirect

This helps us determine how to serve the data on the front-end.

Development Setup

  1. Set up Redis and MariaDB with Docker:
docker run --name=zephyr_mysql -e MYSQL_ROOT_PASSWORD=zephyr -e MYSQL_DATABASE=zephyr -p 3306:3306 -d mariadb
docker run --name=zephyr_redis -d -p 6379:6379 redis redis-server --requirepass "zephyr"
  1. Copy environment configuration:
cp .env.example .env
  1. Configure required services (Redis, database, R2 credentials)

  2. Run the server:

make run

About

The upload service powering Sharify

Resources

License

Stars

Watchers

Forks