Cloudflare Workers with SST
We are going to build an API with a Cloudflare Worker, add an R2 bucket for file uploads, and deploy it using SST.
Before you get started, make sure to Create your Cloudflare API token.
1. Create a project
Let’s start by creating our app.
mkdir my-worker && cd my-workernpm init -yInit SST
Now let’s initialize SST in our app.
npx sst@latest initnpm installSelect the defaults and pick Cloudflare. This’ll create a sst.config.ts file in your project root.
Set the Cloudflare API token
You can save your Cloudflare API token in a .env file or just set it directly.
export CLOUDFLARE_API_TOKEN=aaaaaaaa_aaaaaaaaaaaa_aaaaaaaaexport CLOUDFLARE_DEFAULT_ACCOUNT_ID=aaaaaaaa_aaaaaaaaaaaa_aaaaaaaa2. Add a Worker
Let’s add a Worker. Update your sst.config.ts.
async run() { const worker = new sst.cloudflare.Worker("MyWorker", { handler: "./index.ts", url: true, });
return { api: worker.url, };}We are enabling the Worker URL, so we can use it as our API.
3. Add an R2 Bucket
Let’s add an R2 bucket for file uploads. Update your sst.config.ts.
const bucket = new sst.cloudflare.Bucket("MyBucket");Add this above the Worker component.
Link the bucket
Now, link the bucket to our Worker.
const worker = new sst.cloudflare.Worker("MyWorker", { handler: "./index.ts", link: [bucket], url: true,});4. Upload a file
We want our API to upload a file to the R2 bucket if you make a PUT request to it. Create an index.ts file and add the following.
export default { async fetch(req: Request) { if (req.method == "PUT") { const key = crypto.randomUUID(); await Resource.MyBucket.put(key, req.body, { httpMetadata: { contentType: req.headers.get("content-type"), }, }); return new Response(`Object created with key: ${key}`); } },};Import the SDK.
import { Resource } from "sst";5. Download a file
We want to download the last uploaded file if you make a GET request to the API. Add this to the fetch function in your index.ts file.
if (req.method == "GET") { const first = await Resource.MyBucket.list().then( (res) => res.objects.toSorted( (a, b) => a.uploaded.getTime() - b.uploaded.getTime(), )[0], ); const result = await Resource.MyBucket.get(first.key); return new Response(result.body, { headers: { "content-type": result.httpMetadata.contentType, }, });}We are getting a list of the files in the files in the bucket with Resource.MyBucket.list() and we are getting a file for the given key with Resource.MyBucket.get().
Start dev mode
Start your app in dev mode.
npx sst devThis will give you the URL of your API.
+ Complete api: https://start-cloudflare-jayair-myworkerscript.sst-15d.workers.devTest your app
Let’s try uploading a file from your project root. Make sure to use your API URL.
curl --upload-file package.json https://start-cloudflare-jayair-myworkerscript.sst-15d.workers.devNow head over to https://start-cloudflare-jayair-myworkerscript.sst-15d.workers.dev in your browser and it’ll load the file you just uploaded.
6. Deploy your app
Finally, let’s deploy your app!
npx sst deploy --stage productionYou can use any stage name here but it’s good to create a new stage for production.