Grok2API Media Storage Support: Local Filesystem Implementation Explained

Grok2API stores generated media exclusively on the local filesystem using the LocalStore type, supporting JPEG, PNG, WebP, and GIF formats with atomic writes and path traversal protection.

The chenyme/grok2api repository implements a self-contained media storage system designed for generated images. Unlike distributed systems that rely on object storage services, Grok2API media storage is intentionally limited to the local filesystem, providing a simple, atomic, and secure storage mechanism without external dependencies.

Local Filesystem Architecture

The storage implementation centers on the LocalStore type defined in backend/internal/infra/media/local_store.go. This design prioritizes data integrity and security through several deliberate architectural constraints.

Root-Based Security Model

All media files are confined within a designated root directory supplied during store initialization. The NewLocalStore(root) constructor enforces this boundary, preventing path traversal attacks by validating that all file operations remain within the specified directory hierarchy. This approach ensures that the application cannot accidentally—or maliciously—write files outside the intended storage location.

Atomic Commit Mechanism

To prevent data corruption during concurrent writes, the implementation utilizes an atomic commit pattern. When saving images, the system first writes data to a temporary file and then uses os.Link to atomically link the file to its final destination. This guarantees no-replace semantics for identical IDs, ensuring that existing files are never partially overwritten and that concurrent save operations for the same identifier result in deterministic behavior.

Supported Image Formats

The store validates MIME types against a strict whitelist before persisting data. The imageExtension function maps accepted types to file extensions:

  • JPEG → .jpg
  • PNG → .png
  • WebP → .webp
  • GIF → .gif

Any request with a non-supported MIME type is rejected before filesystem operations begin, preventing the storage of arbitrary or potentially malicious file types.

Storage API Implementation

The LocalStore struct implements the media.Store interface, serving as the sole concrete storage backend in the current codebase. The HTTP handler in backend/internal/transport/http/media/handler.go injects this implementation, receiving image data from clients and delegating persistence operations to the store.

To initialize a local store, applications supply a root directory path:

import (
    "context"
    "io/ioutil"
    "log"

    localmedia "github.com/chenyme/grok2api/main/backend/internal/infra/media"
)

func exampleSave() {
    // Create a store rooted at "./media"
    store, err := localmedia.NewLocalStore("./media")
    if err != nil {
        log.Fatalf("cannot create store: %v", err)
    }

    // Load image data (e.g., from an HTTP request)
    data, _ := ioutil.ReadFile("sample.png")

    // Store the image – `id` must be a unique identifier (e.g., UUID)
    key, err := store.SaveImage(context.Background(), "a1b2c3d4e5", "image/png", data)
    if err != nil {
        log.Fatalf("save failed: %v", err)
    }

    // `key` is the storage key that can be later used to retrieve the file
    log.Printf("image stored as %s", key)
}

Performing CRUD Operations

The LocalStore provides a complete lifecycle API for media assets, with each method checking request contexts for cancellation and enforcing path validation rules.

Saving Images with SaveImage

The SaveImage method handles the atomic persistence workflow. It accepts a context, unique identifier, MIME type, and byte slice, returning a storage key that can be used for subsequent retrieval. The method validates the MIME type against the supported extensions map before attempting filesystem operations.

Retrieving Media with Open

To access stored content, the Open method returns an io.ReadCloser for streaming or reading the file data:

func exampleOpen(key string) {
    store, _ := localmedia.NewLocalStore("./media")
    rc, err := store.Open(context.Background(), key)
    if err != nil {
        log.Fatalf("open failed: %v", err)
    }
    defer rc.Close()
    // `rc` implements io.ReadCloser – read or stream the image as needed
}

Deleting Assets with Delete

The Delete method removes the stored file associated with the provided key, handling context cancellation checks and returning errors if the file does not exist or cannot be removed:

func exampleDelete(key string) {
    store, _ := localmedia.NewLocalStore("./media")
    if err := store.Delete(context.Background(), key); err != nil {
        log.Fatalf("delete failed: %v", err)
    }
}

HTTP Integration and Domain Models

The transport layer in backend/internal/transport/http/media/handler.go bridges incoming HTTP requests to the storage backend. Domain models in backend/internal/domain/media/asset.go represent stored media assets through the storage key abstraction, while backend/internal/domain/media/job.go defines background jobs that may generate media and subsequently utilize the store.

Unit tests in backend/internal/infra/media/local_store_test.go cover the complete save, open, and delete operation lifecycle, ensuring reliability across concurrent access patterns.

Summary

  • Grok2API supports only local filesystem storage via the LocalStore implementation in backend/internal/infra/media/local_store.go.
  • Security is enforced through root-based directory confinement, preventing path traversal attacks.
  • Atomic writes prevent data corruption using temporary files and os.Link operations.
  • Only four image formats are accepted: JPEG, PNG, WebP, and GIF.
  • No cloud backends (S3, GCS, Azure Blob) are currently implemented; extending support would require implementing the media.Store interface.

Frequently Asked Questions

Does Grok2API support cloud storage like Amazon S3 or Google Cloud Storage?

No. The current codebase only implements the LocalStore type for filesystem storage. While the media.Store interface theoretically supports alternative backends, no concrete implementations for S3, GCS, or Azure Blob exist in the repository. To use cloud storage, developers must implement the media.Store interface with their chosen provider.

What image formats can Grok2API store?

Grok2API accepts JPEG, PNG, WebP, and GIF formats exclusively. The imageExtension function in backend/internal/infra/media/local_store.go maps these MIME types to their respective file extensions (.jpg, .png, .webp, .gif). Requests with unsupported MIME types are rejected before filesystem writes occur.

How does Grok2API prevent file path traversal attacks?

The storage system validates all paths against a root directory supplied during NewLocalStore initialization. This design ensures that all file operations—writes, reads, and deletes—are confined to the specified directory tree, preventing the application from accessing or modifying files outside the intended storage location regardless of input validation.

Is media storage persistent across container restarts?

Yes, because LocalStore persists data directly to the host filesystem. However, in containerized environments, persistence requires mounting a volume to the root directory path provided to NewLocalStore. Without proper volume mounts, container restarts will result in data loss since the storage is local to the container's filesystem by default.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →