Hako (箱)
Hako is a fast and lightweight file storage service written in Go. It provides both HTTP REST and gRPC endpoints for uploading and retrieving files, while securely storing file metadata in a PostgreSQL database.
Architecture
Hako follows a Hexagonal / Adapters Architecture to ensure a clean separation of concerns:
- Core Domain: Defines the core business entities (
File).
- Ports: Defines interfaces for external dependencies (
FileRepository, FileStorage).
- Services: Implements business logic and orchestrates domain operations (
FileService).
- Adapters: Implements the ports using specific technologies (e.g., PostgreSQL for the database via
pgx/v5 + sqlb, and local OS filesystem for storage).
Prerequisites
- Go 1.25+
- Docker & Docker Compose
- Protobuf Compiler (
protoc for generating gRPC bindings)
Getting Started
1. Run the Development Server
Start the API and trigger automated database migrations using Docker Compose:
make dev
This command will:
- Spin up the
api container using air for automatic hot-reloading on code changes.
- Spin up the
migrate container to automatically apply PostgreSQL schemas and migrations via /migrations/run-migrations.sh.
By default, the HTTP API is exposed on port 8030 and the gRPC API is exposed on port 8031.
2. Generate Protobuf Bindings
If you modify the gRPC definition in proto/hako/v1/hako.proto, regenerate the Go bindings by running:
make proto
Endpoints
HTTP REST API
GET /health
- Simple healthcheck endpoint.
POST /files
- Upload files via
multipart/form-data.
- Returns a JSON response containing the generated file paths.
GET /file/{filename}
- Retrieves and downloads the file payload from storage.
GET /file/info/{uuid}
- Retrieves JSON metadata about the file, including its original filename, size, and timestamp.
gRPC API
Hako exposes the HakoService for efficient chunked streaming and retrieval:
rpc PostFiles(stream FileUploadRequest) returns (FileUploadResponse)
- Accepts a file stream via chunks and saves it locally.
rpc GetFileInfo(GetFileInfoRequest) returns (GetFileInfoResponse)
- Retrieves file metadata based on a given UUID.