Use case
A drop box for your team
One route on your own domain, a token per person, and a code instead of a chat upload.
import { createBucket, createTransferHandler } from 's3nd'
const tokens = new Set(process.env.DROP_TOKENS!.split(','))
export const { GET, POST, DELETE } = createTransferHandler({
bucket: createBucket({ bucket: 'drop' }),
expiresIn: 24 * 3600,
raw: 'redirect', // downloads go straight from the bucket, presigned
authorize: (request) => tokens.has(request.headers.get('authorization')?.replace('Bearer ', '') ?? ''),
})
// $ s3nd --remote https://drop.example.com/api/transfers --token $TOKEN put ./deck.pdfThe situation
What is actually going on.
The problem
Files move around a team as chat uploads and email attachments, each one a copy on somebody else’s servers. Handing everyone the bucket keys is not an option, and a shared drive is a different kind of mess.
What s3nd does about it
Mount the transfer handler on a domain you own and pass an authorize function that checks a bearer token. Each person has a token, not a key. The CLI points at it with --remote, a browser uses the same four routes through the React hooks, and curl works too. Files land in your bucket under a code and expire on their own.
Worth watching
The things that are easy to get wrong.
Rate-limit the lookup
A code is a bearer token and forty bits is the whole secret. A rate limit on GET /:code is what makes guessing pointless.
raw: redirect for big files
With it, a download answers 302 with a presigned URL, so the bytes never transit your server twice. Without it they stream through, which is fine for small files and expensive for large ones.
doctor --remote as the smoke test
It round-trips a real transfer against the deployment and exits non-zero on failure. Put it in the deploy pipeline.
Related
Other shapes of the same primitive.
Put a file. Hand over the code.
Point it at the bucket you already pay for. Nothing to deploy, nothing to sign up for, nothing in the middle.
npm install -g @s3nd/clis3nd init --provider r2 --bucket drops3nd put ./anything.zip