bunnystorage

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2025 License: MIT Imports: 10 Imported by: 0

README

🐇 Bunny.net Edge Storage Go Library

This is a new Library for using the Bunny.net Object Storage Service in Go. It has been heavily inspired by James Pond`s bunnystorage-go.

❓ Why another library?

I wrote this because of a open PR implementing Bunny.net as Object Storage in JuiceFS and the maintainers were a bit hesitant merging code with many homebrew dependencies. This is using just three battletested dependencies (fasthttp, uuid, logrus) and is about 200 lines of library code, excluding tests.

  • The E2E test coverage is currently at about 80%
  • Simple to use
  • Uses valyala/fasthttp under the hood to achive much better performance than other libraries.
  • Implements Undocumented Describe funtion which allows to retrieve metadata for single, non-directory files.
  • Implements HTTP Range Downloads for downloading segments of objects

🦾 Getting Started

go get github.com/l0wl3vel/bunny-storage-go-sdk
import "net/url"
import "github.com/l0wl3vel/bunny-storage-go-sdk"

endpoint, err := endpoint.Parse("https://la.storage.bunnycdn.com/mystoragezone/")
if err != nil	{
    panic(err)
}
bunnyclient = bunnystorage.NewClient(endpoint, password)

content := make([]byte, 1048576)
// Fill content with data

// The last argument controls if a checksum is included in the request
err := bunnyclient.Upload("foo/bar.txt", content, true)
if err != nil 	{
	panic(err)
}

Developing

# Install pre-commit from https://pre-commit.com/

pre-commit install --install-hooks

# Make your changes

# Run the E2E tests
BUNNY_PASSWORD=<insert password> BUNNY_ENDPOINT=https://storage.bunnycdn.com/<zone-name> go test ./... -v
pre-commit run --all-files

# Commit your changes
git commit

🤔 Further Ideas

[] Implement Pull Zone support

🚀 Performance

It is fast. The use-case built this library around is for a JuiceFS storage backend, which requires low latency and high throughput. Using the other Bunny.net library which uses net/http I got around 200⬇️ 400⬆️ MiB/s from Hetzner Nürnberg to the Bunny Edge PoP.

With this library after moving to fasthttp I was able to achive 1 GB/s upload and 600 Mbit/s download.

❤️ Thanks to

  • James Pond for creating the original bunnystorage-go library, which allowed me to start prototyping my work on JuiceFS immediately
  • Bunny.net for creating an awesome performing and attractively priced object storage solution

Disclaimer

This is a community implementation of the Bunny.net Storage API. It is not sponsored or endorsed by BunnyWay d.o.o.

Documentation

Index

Constants

View Source
const ENDPOINT_FALKENSTEIN_DE = "storage.bunnycdn.com"
View Source
const ENDPOINT_JOHANNESBURG_SA = "jh.storage.bunnycdn.com"
View Source
const ENDPOINT_LONDON_UK = "uk.storage.bunnycdn.com"
View Source
const ENDPOINT_LOS_ANGELES_US = "la.storage.bunnycdn.com"
View Source
const ENDPOINT_NEW_YORK_US = "ny.storage.bunnycdn.com"
View Source
const ENDPOINT_SAO_PAULO_BR = "br.storage.bunnycdn.com"
View Source
const ENDPOINT_SINGAPORE_SG = "sg.storage.bunnycdn.com"
View Source
const ENDPOINT_STOCKHOLM_SE = "se.storage.bunnycdn.com"
View Source
const ENDPOINT_SYDNEY_SYD = "syd.storage.bunnycdn.com"

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	*fasthttp.Client
	// contains filtered or unexported fields
}

func NewClient

func NewClient(endpoint url.URL, password string) Client

Initialize a new bunnystorage-go client with default settings. Endpoint format is https://<region endpoint>/<Storage Zone Name> e.g. https://la.storage.bunnycdn.com/mystoragezone/

func (*Client) Delete

func (c *Client) Delete(path string, isPath bool) error

Delete a file or a directory. If the path to delete is a directory, set the isPath flag to true

func (*Client) Describe added in v0.0.5

func (c *Client) Describe(path string) (Object, error)

Describes an Object. EXPERIMENTAL. The official Java SDK uses it, but the DESCRIBE HTTP method used is not officially documented.

func (*Client) Download

func (c *Client) Download(path string) ([]byte, error)

Downloads a file from a path.

func (*Client) DownloadPartial added in v0.0.7

func (c *Client) DownloadPartial(path string, rangeStart int64, rangeEnd int64) ([]byte, error)

Downloads a byte range of a file. Uses the semantics for HTTP range requests. If you want to avoid passing buffers directly for performance, use DownloadPartialWithReaderCloser

https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests

func (*Client) List

func (c *Client) List(path string) ([]Object, error)

Lists files from a directory.

func (*Client) Upload

func (c *Client) Upload(path string, content []byte, generateChecksum bool) error

Uploads a file to the relative path. generateChecksum controls if a checksum gets generated and attached to the upload request. Returns an error.

func (*Client) WithLogger

func (c *Client) WithLogger(l resty.Logger) *Client

Add a custom logger. The logger has to implement the resty.Logger interface

type Object

type Object struct {
	GUID            string `json:"Guid,omitempty"`
	StorageZoneName string `json:"StorageZoneName,omitempty"`
	Path            string `json:"Path,omitempty"`
	ObjectName      string `json:"ObjectName,omitempty"`
	Length          int    `json:"Length,omitempty"`
	LastChanged     string `json:"LastChanged,omitempty"`
	ServerID        int    `json:"ServerId,omitempty"`
	ArrayNumber     int    `json:"ArrayNumber,omitempty"`
	IsDirectory     bool   `json:"IsDirectory,omitempty"`
	UserID          string `json:"UserId,omitempty"`
	ContentType     string `json:"ContentType,omitempty"`
	DateCreated     string `json:"DateCreated,omitempty"`
	StorageZoneID   int    `json:"StorageZoneId,omitempty"`
	Checksum        string `json:"Checksum,omitempty"`
	ReplicatedZones string `json:"ReplicatedZones,omitempty"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL