diff --git a/src/content/docs/r2/api/workers/workers-api-reference.mdx b/src/content/docs/r2/api/workers/workers-api-reference.mdx
index ac28aeb841de53..5b821914013d9b 100644
--- a/src/content/docs/r2/api/workers/workers-api-reference.mdx
+++ b/src/content/docs/r2/api/workers/workers-api-reference.mdx
@@ -3,7 +3,7 @@ pcx_content_type: reference
title: Workers API reference
---
-import { Type, MetaInfo, WranglerConfig } from "~/components";
+import { Type, MetaInfo, WranglerConfig, TabItem, Tabs } from "~/components";
The in-Worker R2 API is accessed by binding an R2 bucket to a [Worker](/workers). The Worker you write can expose external access to buckets via a route or manipulate R2 objects internally.
@@ -43,6 +43,8 @@ The following methods are available on the bucket binding object injected into y
For example, to issue a `PUT` object request using the binding above:
+
+
```js
export default {
async fetch(request, env) {
@@ -66,6 +68,30 @@ export default {
};
```
+
+
+```py
+from workers import WorkerEntrypoint, Response
+from urllib.parse import urlparse
+
+class Default(WorkerEntrypoint):
+ async def fetch(self, request):
+ url = urlparse(request.url)
+ key = url.path[1:]
+
+ if request.method == "PUT":
+ await self.env.MY_BUCKET.put(key, request.body)
+ return Response.new(f"Put {key} successfully!")
+ else:
+ return Response.new(
+ f"{request.method} is not allowed.",
+ status=405,
+ headers={"Allow": "PUT"}
+ )
+```
+
+
+
- `head`
- Retrieves the `R2Object` for the given key containing only object metadata, if the key exists, and `null` if the key does not exist.
diff --git a/src/content/docs/r2/api/workers/workers-api-usage.mdx b/src/content/docs/r2/api/workers/workers-api-usage.mdx
index 275de7831e82da..dcd90389ac4efc 100644
--- a/src/content/docs/r2/api/workers/workers-api-usage.mdx
+++ b/src/content/docs/r2/api/workers/workers-api-usage.mdx
@@ -194,6 +194,51 @@ export default {
}
}
```
+
+```py
+from workers import WorkerEntrypoint, Response
+from urllib.parse import urlparse
+
+
+class Default(WorkerEntrypoint):
+ async def fetch(self, request):
+ url = urlparse(request.url)
+ key = url.path[1:]
+
+ if request.method == "PUT":
+ await self.env.R2.put(
+ key,
+ request.body,
+ onlyIf=request.headers,
+ httpMetadata=request.headers,
+ )
+ return Response.new(f"Put {key} successfully!")
+ elif request.method == "GET":
+ obj = await self.env.R2.get(
+ key,
+ onlyIf=request.headers,
+ range=request.headers,
+ )
+
+ if obj is None:
+ return Response.new("Object Not Found", status=404)
+
+ # When no body is present, preconditions have failed
+ body = obj.body if hasattr(obj, "body") else None
+ status = 200 if hasattr(obj, "body") else 412
+
+ headers = {"etag": obj.httpEtag}
+ return Response.new(body, status=status, headers=headers)
+ elif request.method == "DELETE":
+ await self.env.R2.delete(key)
+ return Response.new("Deleted!")
+ else:
+ return Response.new(
+ "Method Not Allowed",
+ status=405,
+ headers={"Allow": "PUT, GET, DELETE"},
+ )
+```
@@ -214,6 +259,8 @@ For `PUT` and `DELETE` requests, you will make use of a new `AUTH_KEY_SECRET` en
For `GET` requests, you will ensure that only a specific file can be requested. All of this custom logic occurs inside of an `authorizeRequest` function, with the `hasValidHeader` function handling the custom header logic. If all validation passes, then the operation is allowed.
+
+
```js
const ALLOW_LIST = ["cat-pic.jpg"];
@@ -248,6 +295,39 @@ export default {
};
```
+
+
+```py
+from workers import WorkerEntrypoint, Response
+from urllib.parse import urlparse
+
+ALLOW_LIST = ["cat-pic.jpg"]
+
+# Check requests for a pre-shared secret
+def has_valid_header(request, env):
+ return request.headers.get("X-Custom-Auth-Key") == env.AUTH_KEY_SECRET
+
+def authorize_request(request, env, key):
+ if request.method in ["PUT", "DELETE"]:
+ return has_valid_header(request, env)
+ elif request.method == "GET":
+ return key in ALLOW_LIST
+ else:
+ return False
+
+class Default(WorkerEntrypoint):
+ async def fetch(self, request):
+ url = urlparse(request.url)
+ key = url.path[1:]
+
+ if not authorize_request(request, self.env, key):
+ return Response.new("Forbidden", status=403)
+
+ # ...
+```
+
+
+
For this to work, you need to create a secret via Wrangler:
```sh