# 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, [create your Cloudflare API token](https://sst.dev/docs/cloudflare/#credentials).

---

## 1. Create a project

Let’s start by creating our app.

```
mkdir my-worker && cd my-worker

npm init -y
```

---

#### Init SST

Now let’s initialize SST in our app.

```
npx sst@latest init

npm install
```

Select the defaults and pick **Cloudflare**. This’ll create a `sst.config.ts` file in your project root.

---

#### Set the Cloudflare credentials

Set the token and account ID in your shell or `.env` file.

```
export CLOUDFLARE_API_TOKEN=aaaaaaaa_aaaaaaaaaaaa_aaaaaaaa

export 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.
