StorageStorage ServicesBunny

Bunny

Bunny Storage

Just need ad-hoc uploads? Wrap this adapter in the Files facade for a one-liner API. The reference below shows direct adapter usage and Bunny-specific limitations (no presigned PUT, no signed-read URL).

Overview

The Bunny Storage adapter wraps @bunny.net/storage-sdk. Writes go through the Storage API with an AccessKey header; reads go through BunnyStorageSDK.file.get(...).data() for server-side fetches or, when a Pull Zone hostname is configured via publicBaseUrl, through that public origin.

Bunny Storage does not expose presigned upload URLs or signed-read URL primitives, so this adapter follows the same pattern as UploadThing: public reads via a configured CDN base URL, server-side writes via the SDK.

Installation

npm install @bunny.net/storage-sdk
yarn add @bunny.net/storage-sdk
pnpm add @bunny.net/storage-sdk

Usage

import { BunnyStorage } from "@visulima/storage/provider/bunny";

const storage = new BunnyStorage({
    zone: process.env.BUNNY_STORAGE_ZONE!,
    accessKey: process.env.BUNNY_STORAGE_ACCESS_KEY!,
    region: "de", // BunnyStorageSDK.regions.StorageRegion.*
    publicBaseUrl: "https://cdn.example.com",
});

Configuration

Credentials

OptionEnv (visulima)Env (SDK alias)
zoneBUNNY_STORAGE_ZONESTORAGE_ZONE
accessKeyBUNNY_STORAGE_ACCESS_KEYSTORAGE_ACCESS_KEY
regionBUNNY_STORAGE_REGIONSTORAGE_REGION

BUNNY_ACCESS_KEY is also accepted as an alias for accessKey. Region must be one of the values in BunnyStorageSDK.regions.StorageRegion (e.g. "de", "uk", "ny", "la", "sg", "se", "br", "jh", "syd").

Pre-built client

import * as BunnyStorageSDK from "@bunny.net/storage-sdk";
import { BunnyStorage } from "@visulima/storage/provider/bunny";

const client = BunnyStorageSDK.zone.connect_with_accesskey(
    BunnyStorageSDK.regions.StorageRegion.Falkenstein,
    process.env.BUNNY_STORAGE_ZONE!,
    process.env.BUNNY_STORAGE_ACCESS_KEY!,
);

const storage = new BunnyStorage({
    client,
    publicBaseUrl: "https://cdn.example.com",
});

When client is passed, zone, accessKey, and region are ignored.

publicBaseUrl

getReadUrl() joins publicBaseUrl with the object key. Without publicBaseUrl, the adapter throws METHOD_NOT_ALLOWED from getReadUrl() — the raw Storage API URL requires an AccessKey header and cannot be handed out to clients.

Configure a Bunny Pull Zone (or any CDN/proxy fronting the Storage Zone) and pass its hostname:

new BunnyStorage({
    /* … */
    publicBaseUrl: "https://my-pull-zone.b-cdn.net",
});

URL Generation

getReadUrl(key, options?)

  • Returns ${publicBaseUrl}/${key} when publicBaseUrl is set.
  • Throws METHOD_NOT_ALLOWED when publicBaseUrl is unset.
  • Throws METHOD_NOT_ALLOWED when responseContentDisposition is supplied — Bunny Storage and Pull Zone URLs have no equivalent override.
  • expiresIn is accepted but not consumed by the adapter; downstream Pull-Zone token-signing (if any) is the caller's responsibility.

getUploadUrl(key)

Throws METHOD_NOT_ALLOWED. Bunny Storage has no presigned PUT primitive — writes must go through the Storage API with an AccessKey header. Upload server-side via storage.write() or proxy through your application.

Features

  • SHA256 checksum hint — when part.checksum is provided with checksumAlgorithm: "sha256", it is forwarded as sha256Checksum to the Bunny SDK so the server can verify the upload.
  • Soft deletedelete() swallows FILE_NOT_FOUND errors so removing a missing key is idempotent.
  • Public-URL mintinggetReadUrl() joins publicBaseUrl + key synchronously when a Pull Zone is configured.
  • raw escape hatchstorage.raw exposes the connected StorageZone for advanced SDK calls (BunnyStorageSDK.file.list, etc.).

Limitations

  • No native server-side copy() — implemented as download + re-upload.
  • No presigned upload URLs (getUploadUrl() throws METHOD_NOT_ALLOWED).
  • No signed-read URLs — getReadUrl() requires publicBaseUrl and ignores expiresIn.
  • No responseContentDisposition override — Bunny Storage / Pull Zone URLs cannot bind a Content-Disposition response header.
  • list() paginates client-side over a flat directory listing — large prefixes round-trip the full directory.
  • Custom metadata and cacheControl upload options are not supported (configure cache behavior on the Pull Zone instead).
Support

Contribute to our work and keep us going

Community is the heart of open source. The success of our packages wouldn't be possible without the incredible contributions of users, testers, and developers who collaborate with us every day.Want to get involved? Here are some tips on how you can make a meaningful impact on our open source projects.

Ready to help us out?

Be sure to check out the package's contribution guidelines first. They'll walk you through the process on how to properly submit an issue or pull request to our repositories.

Submit a pull request

Found something to improve? Fork the repo, make your changes, and open a PR. We review every contribution and provide feedback to help you get merged.

Good first issues

Simple issues suited for people new to open source development, and often a good place to start working on a package.
View good first issues