Skip to content

Commit b70c12f

Browse files
authored
Fix uses of env and ctx in Python examples (#24790)
Since #24392, most of the Python examples use env and ctx incorrectly. This fixes it. I also replaced all tabs with spaces in signing-requests.mdx.
1 parent 6ec9ccb commit b70c12f

File tree

16 files changed

+91
-91
lines changed

16 files changed

+91
-91
lines changed

src/content/changelog/workers/2025-05-14-python-worker-durable-object.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class MyDurableObject(DurableObject):
3232
return Response(result.greeting)
3333

3434
class Default(WorkerEntrypoint):
35-
async def fetch(self, request, env, ctx):
35+
async def fetch(self, request):
3636
url = urlparse(request.url)
3737
id = env.MY_DURABLE_OBJECT.idFromName(url.path)
3838
stub = env.MY_DURABLE_OBJECT.get(id)

src/content/changelog/workers/2025-08-14-new-python-handlers.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Here's an example of how to now define a Worker with a fetch handler:
1616
from workers import Response, WorkerEntrypoint
1717

1818
class Default(WorkerEntrypoint):
19-
async def fetch(self, request, env, ctx):
19+
async def fetch(self, request):
2020
return Response("Hello World!")
2121
```
2222

src/content/docs/d1/examples/query-d1-from-python-workers.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ To create a Python Worker, create an empty file at `src/entry.py`, matching the
8484
from workers import Response, WorkerEntrypoint
8585

8686
class Default(WorkerEntrypoint):
87-
async def fetch(self, request, env):
87+
async def fetch(self, request):
8888
# Do anything else you'd like on request here!
8989

9090
# Query D1 - we'll list all tables in our database in this example
91-
results = await env.DB.prepare("PRAGMA table_list").run()
91+
results = await self.env.DB.prepare("PRAGMA table_list").run()
9292
# Return a JSON response
9393
return Response.json(results)
9494

src/content/docs/durable-objects/get-started.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,9 @@ from workers import handler, Response, WorkerEntrypoint
225225
from urllib.parse import urlparse
226226

227227
class Default(WorkerEntrypoint):
228-
async def fetch(request, env, ctx):
228+
async def fetch(request):
229229
url = urlparse(request.url)
230-
stub = env.MY_DURABLE_OBJECT.getByName(url.path)
230+
stub = self.env.MY_DURABLE_OBJECT.getByName(url.path)
231231
greeting = await stub.say_hello()
232232
return Response(greeting)
233233
```
@@ -360,9 +360,9 @@ class MyDurableObject(DurableObject):
360360
return result.greeting
361361

362362
class Default(WorkerEntrypoint):
363-
async def fetch(self, request, env, ctx):
363+
async def fetch(self, request):
364364
url = urlparse(request.url)
365-
stub = env.MY_DURABLE_OBJECT.getByName(url.path)
365+
stub = self.env.MY_DURABLE_OBJECT.getByName(url.path)
366366
greeting = await stub.say_hello()
367367
return Response(greeting)
368368
```

src/content/docs/workers/examples/cache-api.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ from pyodide.ffi import create_proxy
111111
from js import Response, Request, URL, caches, fetch
112112

113113
class Default(WorkerEntrypoint):
114-
async def fetch(self, request, _env, ctx):
114+
async def fetch(self, request):
115115
cache_url = request.url
116116

117117
# Construct the cache key from the cache URL
@@ -133,7 +133,7 @@ class Default(WorkerEntrypoint):
133133
# will limit the response to be in cache for 10 seconds s-maxage
134134
# Any changes made to the response here will be reflected in the cached value
135135
response.headers.append("Cache-Control", "s-maxage=10")
136-
ctx.waitUntil(create_proxy(cache.put(cache_key, response.clone())))
136+
self.ctx.waitUntil(create_proxy(cache.put(cache_key, response.clone())))
137137
else:
138138
print(f"Cache hit for: {request.url}.")
139139
return response

src/content/docs/workers/examples/debugging-logs.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ async def post_log(data):
124124
await fetch(log_url, method="POST", body=data)
125125

126126
class Default(WorkerEntrypoint):
127-
async def fetch(self, request, _env, ctx):
127+
async def fetch(self, request):
128128
# Service configured to receive logs
129129
response = await fetch(request)
130130

@@ -136,7 +136,7 @@ class Default(WorkerEntrypoint):
136136
except Exception as e:
137137
# Without ctx.waitUntil(), your fetch() to Cloudflare's
138138
# logging service may or may not complete
139-
ctx.waitUntil(create_proxy(post_log(str(e))))
139+
self.ctx.waitUntil(create_proxy(post_log(str(e))))
140140
# Copy the response and add to header
141141
response = Response.new(stack, response)
142142
response.headers["X-Debug-err"] = str(e)

src/content/docs/workers/examples/protect-against-timing-attacks.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ from workers import WorkerEntrypoint, Response
7777
from js import TextEncoder, crypto
7878

7979
class Default(WorkerEntrypoint):
80-
async def fetch(self, request, env):
80+
async def fetch(self, request):
8181
auth_token = request.headers["Authorization"] or ""
82-
secret = env.MY_SECRET_VALUE
82+
secret = self.env.MY_SECRET_VALUE
8383

8484
if secret is None:
8585
return Response("Missing secret binding", status=500)

src/content/docs/workers/examples/signing-requests.mdx

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -387,75 +387,75 @@ encoder = TextEncoder.new()
387387
EXPIRY = 60
388388

389389
class Default(WorkerEntrypoint):
390-
async def fetch(self, request, env):
391-
# Get the secret key
392-
secret_key_data = encoder.encode(env.SECRET_DATA if hasattr(env, "SECRET_DATA") else "my secret symmetric key")
390+
async def fetch(self, request):
391+
# Get the secret key
392+
secret_key_data = encoder.encode(getattr(self.env, "SECRET_DATA", None) or "my secret symmetric key")
393393

394-
# Import the secret as a CryptoKey for both 'sign' and 'verify' operations
395-
key = await crypto.subtle.importKey(
396-
"raw",
397-
secret_key_data,
398-
to_js({"name": "HMAC", "hash": "SHA-256"}),
399-
False,
400-
["sign", "verify"]
401-
)
394+
# Import the secret as a CryptoKey for both 'sign' and 'verify' operations
395+
key = await crypto.subtle.importKey(
396+
"raw",
397+
secret_key_data,
398+
to_js({"name": "HMAC", "hash": "SHA-256"}),
399+
False,
400+
["sign", "verify"]
401+
)
402402

403-
url = URL.new(request.url)
403+
url = URL.new(request.url)
404404

405-
if url.pathname.startswith("/generate/"):
406-
url.pathname = url.pathname.replace("/generate/", "/", 1)
405+
if url.pathname.startswith("/generate/"):
406+
url.pathname = url.pathname.replace("/generate/", "/", 1)
407407

408-
timestamp = int(Date.now() / 1000)
408+
timestamp = int(Date.now() / 1000)
409409

410-
# Data to authenticate
411-
data_to_authenticate = f"{url.pathname}{timestamp}"
410+
# Data to authenticate
411+
data_to_authenticate = f"{url.pathname}{timestamp}"
412412

413-
# Sign the data
414-
mac = await crypto.subtle.sign(
415-
"HMAC",
416-
key,
417-
encoder.encode(data_to_authenticate)
418-
)
413+
# Sign the data
414+
mac = await crypto.subtle.sign(
415+
"HMAC",
416+
key,
417+
encoder.encode(data_to_authenticate)
418+
)
419419

420-
# Convert to base64
421-
base64_mac = Buffer.from(mac).toString("base64")
420+
# Convert to base64
421+
base64_mac = Buffer.from(mac).toString("base64")
422422

423-
# Set the verification parameter
424-
url.searchParams.set("verify", f"{timestamp}-{base64_mac}")
423+
# Set the verification parameter
424+
url.searchParams.set("verify", f"{timestamp}-{base64_mac}")
425425

426-
return Response.new(f"{url.pathname}{url.search}")
427-
else:
428-
# Verify the request
429-
if not "verify" in url.searchParams:
430-
return Response.new("Missing query parameter", status=403)
426+
return Response.new(f"{url.pathname}{url.search}")
427+
else:
428+
# Verify the request
429+
if not "verify" in url.searchParams:
430+
return Response.new("Missing query parameter", status=403)
431431

432-
verify_param = url.searchParams.get("verify")
433-
timestamp, hmac = verify_param.split("-")
432+
verify_param = url.searchParams.get("verify")
433+
timestamp, hmac = verify_param.split("-")
434434

435-
asserted_timestamp = int(timestamp)
435+
asserted_timestamp = int(timestamp)
436436

437-
data_to_authenticate = f"{url.pathname}{asserted_timestamp}"
437+
data_to_authenticate = f"{url.pathname}{asserted_timestamp}"
438438

439-
received_mac = Buffer.from(hmac, "base64")
439+
received_mac = Buffer.from(hmac, "base64")
440440

441-
# Verify the signature
442-
verified = await crypto.subtle.verify(
443-
"HMAC",
444-
key,
445-
received_mac,
446-
encoder.encode(data_to_authenticate)
447-
)
441+
# Verify the signature
442+
verified = await crypto.subtle.verify(
443+
"HMAC",
444+
key,
445+
received_mac,
446+
encoder.encode(data_to_authenticate)
447+
)
448448

449-
if not verified:
450-
return Response.new("Invalid MAC", status=403)
449+
if not verified:
450+
return Response.new("Invalid MAC", status=403)
451451

452-
# Check expiration
453-
if Date.now() / 1000 > asserted_timestamp + EXPIRY:
454-
expiry_date = Date.new((asserted_timestamp + EXPIRY) * 1000)
455-
return Response.new(f"URL expired at {expiry_date}", status=403)
452+
# Check expiration
453+
if Date.now() / 1000 > asserted_timestamp + EXPIRY:
454+
expiry_date = Date.new((asserted_timestamp + EXPIRY) * 1000)
455+
return Response.new(f"URL expired at {expiry_date}", status=403)
456456

457-
# Proxy to example.com if verification passes
458-
return fetch(URL.new(f"https://example.com{url.pathname}"), request)
457+
# Proxy to example.com if verification passes
458+
return fetch(URL.new(f"https://example.com{url.pathname}"), request)
459459
```
460460
461461
</TabItem> </Tabs>

src/content/docs/workers/examples/turnstile-html-rewriter.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,9 @@ from pyodide.ffi import create_proxy
217217
from js import HTMLRewriter, fetch
218218

219219
class Default(WorkerEntrypoint):
220-
async def fetch(self, request, env):
221-
site_key = env.SITE_KEY
222-
attr_name = env.TURNSTILE_ATTR_NAME
220+
async def fetch(self, request):
221+
site_key = self.env.SITE_KEY
222+
attr_name = self.env.TURNSTILE_ATTR_NAME
223223
res = await fetch(request)
224224

225225
class Append:
@@ -264,7 +264,7 @@ async function handlePost(request, env) {
264264
let formData = new FormData();
265265

266266
// `secret_key` here is the Turnstile Secret key, which should be set using Wrangler secrets
267-
formData.append('secret', env.SECRET_KEY);
267+
formData.append('secret', self.env.SECRET_KEY);
268268
formData.append('response', token);
269269
formData.append('remoteip', ip); //This is optional.
270270

src/content/docs/workers/languages/python/examples.mdx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ from workers import WorkerEntrypoint, Response
1818
from urllib.parse import urlparse, parse_qs
1919

2020
class Default(WorkerEntrypoint):
21-
async def fetch(self, request, env):
21+
async def fetch(self, request):
2222
# Parse the incoming request URL
2323
url = urlparse(request.url)
2424
# Parse the query parameters into a Python dictionary
@@ -89,15 +89,15 @@ def to_js(obj):
8989
return _to_js(obj, dict_converter=Object.fromEntries)
9090

9191
class Default(WorkerEntrypoint):
92-
async def fetch(self, request, env):
93-
# Bindings are available on the 'env' parameter
92+
async def fetch(self, request):
93+
# Bindings are available on the 'env' attribute
9494
# https://developers.cloudflare.com/queues/
9595

9696
# The default contentType is "json"
9797
# We can also pass plain text strings
98-
await env.QUEUE.send("hello", contentType="text")
98+
await self.env.QUEUE.send("hello", contentType="text")
9999
# Send a JSON payload
100-
await env.QUEUE.send(to_js({"hello": "world"}))
100+
await self.env.QUEUE.send(to_js({"hello": "world"}))
101101

102102
# Return a response
103103
return Response.json({"write": "success"})
@@ -109,8 +109,8 @@ class Default(WorkerEntrypoint):
109109
from workers import WorkerEntrypoint, Response
110110

111111
class Default(WorkerEntrypoint):
112-
async def fetch(self, request, env):
113-
results = await env.DB.prepare("PRAGMA table_list").run()
112+
async def fetch(self, request):
113+
results = await self.env.DB.prepare("PRAGMA table_list").run()
114114
# Return a JSON response
115115
return Response.json(results)
116116
```

0 commit comments

Comments
 (0)