Caesar Drive

Learn how to abstract cloud storage services using the Caesar Drive package.

Overview

The Caesar Drive package provides an abstraction over cloud storage services. Currently, it supports only S3. This guide will walk you through setting up Caesar Drive, validating environment variables, and utilizing the package within your controllers.

Setting Up Caesar Drive

Step 1: Install the Dependency

First, download the Caesar Drive package dependency:

go get -u github.com/caesar-rocks/drive

Step 2: Validate Environment Variables

Before you set up Caesar Drive, ensure that the necessary environment variables are validated. You can do this in the ./config/env.go file:

package config

import (
	"github.com/caesar-rocks/core"
	"github.com/caesar-rocks/orm"
)

// EnvironmentVariables is a struct that holds all the environment variables that need to be validated.
type EnvironmentVariables struct {
	S3_KEY      string `validate:"required"`
	S3_SECRET   string `validate:"required"`
	S3_REGION   string `validate:"required"`
	S3_ENDPOINT string `validate:"required"`
	S3_BUCKET   string `validate:"required"`

	// Other environment variables...
}

func ProvideEnvironmentVariables() *EnvironmentVariables {
	return core.ValidateEnvironmentVariables[EnvironmentVariables]()
}

Step 3: Add Drive Configuration

Next, create a ./config/drive.go file to configure the Drive service:

package config

import (
	"github.com/caesar-rocks/drive"
)

func ProvideDrive(env *EnvironmentVariables) *drive.Drive {
	return drive.NewDrive(map[string]drive.FileSystem{
		"s3": &drive.S3{
			Key:      env.S3_KEY,
			Secret:   env.S3_SECRET,
			Region:   env.S3_REGION,
			Endpoint: env.S3_ENDPOINT,
			Bucket:   env.S3_BUCKET,
		},
	})
}

Step 4: Register Drive as a Provider

Finally, register the Drive service as a provider in your ./config/app.go file:

package config

import (
	"myapp/app/repositories"

	"github.com/caesar-rocks/core"
)

func ProvideApp() *core.App {
	app := core.NewApp(&core.AppConfig{
		Addr: ":8080",
	})

	// Register environment variables and drive as providers
	app.RegisterProviders(
		ProvideEnvironmentVariables,
		ProvideDrive,
		// Other providers...
	)

	// Other invokers...
	return app
}

Using Caesar Drive in Controllers

Once your Drive service is set up, you can use it within your controllers. Here’s an example illustrating how to handle file uploads to S3:

File Upload Controller

Define a controller to handle file uploads:

package controllers

import (
	"bytes"
	"io"
	"net/http"

	caesar "github.com/caesar-rocks/core"
	"github.com/caesar-rocks/drive"
)

type FileUploadController struct {
	drive *drive.Drive
}

func NewFileUploadController(drive *drive.Drive) *FileUploadController {
	return &FileUploadController{drive: drive}
}

func (c *FileUploadController) UploadFile(ctx *caesar.CaesarCtx) error {
	err := ctx.Request.ParseMultipartForm(10 << 20) // 10 MB
	if err != nil {
		return caesar.NewError(http.StatusBadRequest, "Invalid file upload request")
	}

	file, _, err := ctx.Request.FormFile("file")
	if err != nil {
		return caesar.NewError(http.StatusBadRequest, "Failed to retrieve file from request")
	}
	defer file.Close()

	buf := bytes.NewBuffer(nil)
	_, err = io.Copy(buf, file)
	if err != nil {
		return caesar.NewError(http.StatusInternalServerError, "Failed to read file")
	}

	err = c.drive.Use("s3").Put("uploads/file", buf.Bytes())
	if err != nil {
		return caesar.NewError(http.StatusInternalServerError, "Failed to upload file to S3")
	}

	return ctx.SendText("File uploaded successfully!", http.StatusOK)
}

Registering Routes

Register the controller methods in your application's route configuration:

package config

import (
	"myapp/app/controllers"
	"myapp/app/repositories"
	caesar "github.com/caesar-rocks/core"
)

func RegisterRoutes(
	drive *drive.Drive,
	fileUploadController *controllers.FileUploadController,
) *caesar.Router {
	router := caesar.NewRouter()

	router.Post("/upload", fileUploadController.UploadFile)

	return router
}

In the ProvideApp() function from ./config/app.go, ensure that RegisterRoutes is called with the correct parameters:

func ProvideApp() *core.App {
	app := core.NewApp(&core.AppConfig{
		Addr: ":8080",
	})

	env := ProvideEnvironmentVariables()
	drive := ProvideDrive(env)

	// Register routes
	router := RegisterRoutes(drive)
	app.SetRouter(router)

	// Register other providers and invokers...

	return app
}

Summary

The Caesar Drive package provides a convenient abstraction over cloud storage services, making it easy to work with providers like S3. By following the steps outlined in this guide, you can set up and use Caesar Drive in your application, ensuring smooth handling of file storage operations.