Cloudflare Workers with SST
Create and deploy a Cloudflare Worker as an API 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 -y
Init SST
Now let’s initialize SST in our app.
npx sst@latest initnpm install
Select 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_aaaaaaaa
2. 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 dev
This will give you the URL of your API.
+ Complete api: https://start-cloudflare-jayair-myworkerscript.sst-15d.workers.dev
Test 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.dev
Now 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 production
You can use any stage name here but it’s good to create a new stage for production.