Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates Python Workers examples to use new Python SDK API #18596

Draft
wants to merge 1 commit into
base: production
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Updates Python Workers examples to use new cloudflare.workers API
  • Loading branch information
dom96 committed Dec 9, 2024
commit a938004ce325edcc692a1f66f84cd3730f74134a
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ The value of `binding` is how you will refer to your database from within your W
To create a Python Worker, create an empty file at `src/entry.py`, matching the value of `main` in your `wrangler.toml` file with the contents below:

```python
from js import Response
from cloudflare.workers import Response

async def on_fetch(request, env):
# Do anything else you'd like on request here!
Expand Down
10 changes: 5 additions & 5 deletions src/content/docs/workers/examples/103-early-hints.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default {

```py
import re
from js import Response, Headers
from cloudflare.workers import Response

CSS = "body { color: red; }"
HTML = """
Expand All @@ -129,11 +129,11 @@ HTML = """
"""
def on_fetch(request):
if re.search("test.css", request.url):
headers = Headers.new({"content-type": "text/css"}.items())
return Response.new(CSS, headers=headers)
headers = {"content-type": "text/css"}
return Response(CSS, headers=headers)
else:
headers = Headers.new({"content-type": "text/html","link": "</test.css>; rel=preload; as=style"}.items())
return Response.new(HTML, headers=headers)
headers = {"content-type": "text/html","link": "</test.css>; rel=preload; as=style"}
return Response(HTML, headers=headers)
```

</TabItem> </Tabs>
5 changes: 2 additions & 3 deletions src/content/docs/workers/examples/ab-testing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export default {
```py
import random
from urllib.parse import urlparse, urlunparse
from js import Response, Headers, fetch
from cloudflare.workers import Response, fetch

NAME = "myExampleWorkersABTest"

Expand Down Expand Up @@ -132,8 +132,7 @@ async def on_fetch(request):
res = await fetch(urlunparse(url))
headers = dict(res.headers)
headers["Set-Cookie"] = f'{NAME}={group}; path=/'
headers = Headers.new(headers.items())
return Response.new(res.body, headers=headers)
return Response(res.body, headers=headers)

return fetch(urlunparse(url))
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ export default {

```py
import json
from js import Response, Headers, JSON
from cloudflare.workers import Response
from js import JSON

def on_fetch(request):
error = json.dumps({ "error": "The `cf` object is not available inside the preview." })
data = request.cf if request.cf is not None else error
headers = Headers.new({"content-type":"application/json"}.items())
return Response.new(JSON.stringify(data, None, 2), headers=headers)
headers = {"content-type":"application/json"}
return Response(JSON.stringify(data, None, 2), headers=headers)
```

</TabItem> </Tabs>
12 changes: 7 additions & 5 deletions src/content/docs/workers/examples/aggregate-requests.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,21 @@ export default {
</TabItem> <TabItem label="Python" icon="seti:python">

```py
from js import Response, fetch, Headers, JSON, Promise
from cloudflare.workers import Response, fetch
import asyncio
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be deployed even when packages not enabled?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah

import json

async def on_fetch(request):
# some_host is set up to return JSON responses
some_host = "https://jsonplaceholder.typicode.com"
url1 = some_host + "/todos/1"
url2 = some_host + "/todos/2"

responses = await Promise.all([fetch(url1), fetch(url2)])
results = await Promise.all(map(lambda r: r.json(), responses))
responses = await asyncio.gather(*[fetch(url1), fetch(url2)])
results = await asyncio.gather(*map(lambda r: r.json(), responses))

headers = Headers.new({"content-type": "application/json;charset=UTF-8"}.items())
return Response.new(JSON.stringify(results), headers=headers)
headers = {"content-type": "application/json;charset=UTF-8"}
return Response(json.dumps(results), headers=headers)
```

</TabItem> </Tabs>
23 changes: 11 additions & 12 deletions src/content/docs/workers/examples/alter-headers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,28 +80,27 @@ export default {
</TabItem> <TabItem label="Python" icon="seti:python">

```py
from js import Response, fetch
from cloudflare.workers import Response, fetch

async def on_fetch(request):
response = await fetch("https://example.com")

# Clone the response so that it's no longer immutable
new_response = Response.new(response.body, response)
# Grab the response headers so they can be modified
new_headers = response.headers

# Add a custom header with a value
new_response.headers.append(
"x-workers-hello",
"Hello from Cloudflare Workers"
)

new_headers["x-workers-hello"] = "Hello from Cloudflare Workers"

# Delete headers
new_response.headers.delete("x-header-to-delete")
new_response.headers.delete("x-header2-to-delete")
if "x-header-to-delete" in new_headers:
del new_headers["x-header-to-delete"]
if "x-header2-to-delete" in new_headers:
del new_headers["x-header2-to-delete"]

# Adjust the value for an existing header
new_response.headers.set("x-header-to-change", "NewValue")
new_headers["x-header-to-change"] = "NewValue"

return new_response
return Response(response.body, headers=new_headers)
```

</TabItem> </Tabs>
Expand Down
6 changes: 3 additions & 3 deletions src/content/docs/workers/examples/auth-with-headers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,20 @@ export default {
</TabItem> <TabItem label="Python" icon="seti:python">

```py
from js import Response, fetch
from cloudflare.workers import Response, fetch

async def on_fetch(request):
PRESHARED_AUTH_HEADER_KEY = "X-Custom-PSK"
PRESHARED_AUTH_HEADER_VALUE = "mypresharedkey"

psk = request.headers.get(PRESHARED_AUTH_HEADER_KEY)
psk = request.headers[PRESHARED_AUTH_HEADER_KEY]

if psk == PRESHARED_AUTH_HEADER_VALUE:
# Correct preshared header key supplied. Fetch request from origin.
return fetch(request)

# Incorrect key supplied. Reject the request.
return Response.new("Sorry, you have supplied an invalid key.", status=403);
return Response("Sorry, you have supplied an invalid key.", status=403)
```

</TabItem> </Tabs>
4 changes: 2 additions & 2 deletions src/content/docs/workers/examples/block-on-tls.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ export default {
</TabItem> <TabItem label="Python" icon="seti:python">

```py
from js import Response, fetch
from cloudflare.workers import Response, fetch

async def on_fetch(request):
tls_version = request.cf.tlsVersion
if tls_version not in ("TLSv1.2", "TLSv1.3"):
return Response.new("Please use TLS version 1.2 or higher.", status=403)
return Response("Please use TLS version 1.2 or higher.", status=403)
return fetch(request)
```

Expand Down
7 changes: 4 additions & 3 deletions src/content/docs/workers/examples/bulk-redirects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ export default {
</TabItem> <TabItem label="Python" icon="seti:python">

```py
from js import Response, fetch, URL
from cloudflare.workers import Response, fetch
from urllib.parse import urlparse

async def on_fetch(request):
external_hostname = "examples.cloudflareworkers.com"
Expand All @@ -88,8 +89,8 @@ async def on_fetch(request):
"/bulk4": "https://google.com",
}

url = URL.new(request.url)
location = redirect_map.get(url.pathname, None)
url = urlparse(request.url)
location = redirect_map.get(url.path, None)

if location:
return Response.redirect(location, 301)
Expand Down
19 changes: 10 additions & 9 deletions src/content/docs/workers/examples/conditional-response.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -120,37 +120,38 @@ export default {

```py
import re
from js import Response, URL, fetch
from cloudflare.workers import Response
from urllib.parse import urlparse

async def on_fetch(request):
blocked_hostnames = ["nope.mywebsite.com", "bye.website.com"]
url = URL.new(request.url)
url = urlparse(request.url)

# Block on hostname
if url.hostname in blocked_hostnames:
return Response.new("Blocked Host", status=403)
return Response("Blocked Host", status=403)

# On paths ending in .doc or .xml
if re.search(r'\.(doc|xml)$', url.pathname):
return Response.new("Blocked Extension", status=403)
if re.search(r'\.(doc|xml)$', url.path):
return Response("Blocked Extension", status=403)

# On HTTP method
if "POST" in request.method:
return Response.new("Response for POST")
return Response("Response for POST")

# On User Agent
user_agent = request.headers["User-Agent"] or ""
if "bot" in user_agent:
return Response.new("Block User Agent containing bot", status=403)
return Response("Block User Agent containing bot", status=403)

# On Client's IP address
client_ip = request.headers["CF-Connecting-IP"]
if client_ip == "1.2.3.4":
return Response.new("Block the IP 1.2.3.4", status=403)
return Response("Block the IP 1.2.3.4", status=403)

# On ASN
if request.cf and request.cf.asn == 64512:
return Response.new("Block the ASN 64512 response")
return Response("Block the ASN 64512 response")

# On Device Type
# Requires Enterprise "CF-Device-Type Header" zone setting or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export default {
</TabItem> <TabItem label="Python" icon="seti:python">

```py
from js import Response, fetch
from cloudflare.workers import Response, fetch

async def on_fetch(request):
countries = {
Expand Down
6 changes: 3 additions & 3 deletions src/content/docs/workers/examples/extract-cookie-value.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default {

```py
from http.cookies import SimpleCookie
from js import Response
from cloudflare.workers import Response

async def on_fetch(request):
# Name of the cookie
Expand All @@ -68,9 +68,9 @@ async def on_fetch(request):

if cookie_name in cookies:
# Respond with cookie value
return Response.new(cookies[cookie_name].value)
return Response(cookies[cookie_name].value)

return Response.new("No cookie with name: " + cookie_name)
return Response("No cookie with name: " + cookie_name)
```

</TabItem> </Tabs>
Expand Down
9 changes: 5 additions & 4 deletions src/content/docs/workers/examples/fetch-json.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ export default {
</TabItem> <TabItem label="Python" icon="seti:python">

```py
from js import Response, fetch, Headers, JSON
from cloudflare.workers import Response, fetch
import json

async def on_fetch(request):
url = "https://jsonplaceholder.typicode.com/todos/1"
Expand All @@ -85,15 +86,15 @@ async def on_fetch(request):
content_type = headers["content-type"] or ""

if "application/json" in content_type:
return (content_type, JSON.stringify(await response.json()))
return (content_type, json.dumps(await response.json()))
return (content_type, await response.text())

response = await fetch(url)
content_type, result = await gather_response(response)


headers = Headers.new({"content-type": content_type}.items())
return Response.new(result, headers=headers)
headers = {"content-type": content_type}
return Response(result, headers=headers)
```

</TabItem> </Tabs>
16 changes: 8 additions & 8 deletions src/content/docs/workers/examples/geolocation-app-weather.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export default {
</TabItem> <TabItem label="Python" icon="seti:python">

```py
from js import Response, Headers, fetch
from cloudflare.workers import Response, fetch

async def on_fetch(request):
endpoint = "https://api.waqi.info/feed/geo:"
Expand All @@ -140,11 +140,11 @@ async def on_fetch(request):

html_content += "<p>This is a demo using Workers geolocation data. </p>"
html_content += f"You are located at: {latitude},{longitude}.</p>"
html_content += f"<p>Based off sensor data from <a href='{content.data.city.url}'>{content.data.city.name}</a>:</p>"
html_content += f"<p>The AQI level is: {content.data.aqi}.</p>"
html_content += f"<p>The N02 level is: {content.data.iaqi.no2.v}.</p>"
html_content += f"<p>The O3 level is: {content.data.iaqi.o3.v}.</p>"
html_content += f"<p>The temperature is: {content.data.iaqi.t.v}°C.</p>"
html_content += f"<p>Based off sensor data from <a href='{content['data']['city']['url']}'>{content['data']['city']['name']}</a>:</p>"
html_content += f"<p>The AQI level is: {content['data']['aqi']}.</p>"
html_content += f"<p>The N02 level is: {content['data']['iaqi']['no2']['v']}.</p>"
html_content += f"<p>The O3 level is: {content['data']['iaqi']['o3']['v']}.</p>"
html_content += f"<p>The temperature is: {content['data']['iaqi']['t']['v']}°C.</p>"

html = f"""
<!DOCTYPE html>
Expand All @@ -159,8 +159,8 @@ async def on_fetch(request):
</body>
"""

headers = Headers.new({"content-type": "text/html;charset=UTF-8"}.items())
return Response.new(html, headers=headers)
headers = {"content-type": "text/html;charset=UTF-8"}
return Response(html, headers=headers)
```

</TabItem> </Tabs>
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export default {
</TabItem> <TabItem label="Python" icon="seti:python">

```py
from js import Response, Headers
from cloudflare.workers import Response

async def on_fetch(request):
html_content = ""
Expand Down Expand Up @@ -133,8 +133,8 @@ async def on_fetch(request):
</body>
"""

headers = Headers.new({"content-type": "text/htmlcharset=UTF-8"}.items())
return Response.new(html, headers=headers)
headers = {"content-type": "text/html;charset=UTF-8"}
return Response(html, headers=headers)
```

</TabItem> </Tabs>
5 changes: 3 additions & 2 deletions src/content/docs/workers/examples/hot-link-protection.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ export default {
</TabItem> <TabItem label="Python" icon="seti:python">

```py
from js import Response, URL, fetch
from cloudflare.workers import Response, fetch
from urllib.parse import urlparse

async def on_fetch(request):
homepage_url = "https://tutorial.cloudflareworkers.com/"
Expand All @@ -97,7 +98,7 @@ async def on_fetch(request):

if referer and content_type.startswith(protected_type):
# If the hostnames don't match, it's a hotlink
if URL.new(referer).hostname != URL.new(request.url).hostname:
if urlparse(referer).hostname != urlparse(request.url).hostname:
# Redirect the user to your website
return Response.redirect(homepage_url, 302)

Expand Down
4 changes: 2 additions & 2 deletions src/content/docs/workers/examples/logging-headers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ export default {
</TabItem> <TabItem label="Python" icon="seti:python">

```py
from js import Response
from cloudflare.workers import Response

async def on_fetch(request):
print(dict(request.headers))
return Response.new('Hello world')
return Response('Hello world')
```

</TabItem> <TabItem label="Rust" icon="seti:rust">
Expand Down
Loading
Loading