How to write python workers?

I'm trying to learn how to write python workers because I really don't know much about JS so I better try with python. The examples I found are different and I think some stuff is not being explained. For example, here in the examples page: https://developers.cloudflare.com/workers/languages/python/examples it says that we should import Response and other stuff from the js package, but there is no js package, or well, there is one but I don't think it's related, there is no Response in that package. Then if I go to this example https://github.com/cloudflare/python-worker-hello-world/blob/master/index.py there is an addEventListener which afaik is not part of python. I'm trying to write the worker on python because I need to access environment variables and I don't quite understand how to do that in JS, but then again I don't know how to do that in python either. In general, as far as I've understood, I should write an on_fetch() function and call other functions from there as that's the only part where I can actually access the environment variables, is this right? If this is true then how do I make it so that the function/worker is not available publicly, I mean if my function is at /api/function then anyone that finds out about it can make a request to it and the environment variables will be exposed. I'm using the functions subdirectory to store the workers. specifically what I'm want to write is a function to send mails to myself from the form data the worker receives, the logic is already done but how to access the environment variables is what I don't understand plus my concern about the public access of that function. Please help
6 Replies
Cyb3r-Jak3
Cyb3r-Jak32mo ago
The js package is a part of pyodide package. If you want to use the environment variable then the code would look something like
from js import Response

async def on_fetch(request, env):
return Response.new(env.API_HOST)
from js import Response

async def on_fetch(request, env):
return Response.new(env.API_HOST)
For the public part, you can disable the workers.dev domain and put a firewall rule in front of custom hostname with restrictions so only you can trigger it.
i.wont.tell
i.wont.tell2mo ago
I have this in my function contact.js file:
export async function onRequestPost(request, env) {
try {
console.log(env);
return await handleRequest(request, env);
} catch (e) {
console.error(e);
return new Response("Error sending message", {status: 500});
}
}
export async function onRequestPost(request, env) {
try {
console.log(env);
return await handleRequest(request, env);
} catch (e) {
console.error(e);
return new Response("Error sending message", {status: 500});
}
}
And the function log in the dashboard says that the first log returned null and the second log is about the worker not being able to access an environment variable "TypeError: Cannot read properties of undefined (reading 'TURNSTILE_SECRET_KEY')" the env vars are set up in the dashboard for both preview and production, I don't understand why it fails this is the function where the exception happens:
async function handleRequest(request, env) {
const TURNSTILE_SECRET_KEY = env.TURNSTILE_SECRET_KEY;

const ip = request.headers.get("CF-Connecting-IP");

const formData = await request.formData();

const user = {};
user.name = formData.get("nombre");
user.email = formData.get("email");

const token = formData.get("cf-turnstile-response");

if (formData.get("terms")) {
user.policy = "Sí";
} else {
user.policy = "No";
}

const tokenValidated = await validateToken(ip, token, TURNSTILE_SECRET_KEY);

if (!tokenValidated) {
return new Response("Token validation failed", {status: 403});
}

await forwardMessage(user, env);

return new Response("OK", {status: 200});
}
async function handleRequest(request, env) {
const TURNSTILE_SECRET_KEY = env.TURNSTILE_SECRET_KEY;

const ip = request.headers.get("CF-Connecting-IP");

const formData = await request.formData();

const user = {};
user.name = formData.get("nombre");
user.email = formData.get("email");

const token = formData.get("cf-turnstile-response");

if (formData.get("terms")) {
user.policy = "Sí";
} else {
user.policy = "No";
}

const tokenValidated = await validateToken(ip, token, TURNSTILE_SECRET_KEY);

if (!tokenValidated) {
return new Response("Token validation failed", {status: 403});
}

await forwardMessage(user, env);

return new Response("OK", {status: 200});
}
i.wont.tell
i.wont.tell2mo ago
the env var is set
No description
i.wont.tell
i.wont.tell2mo ago
I don't understand what I'm doing wrong, I'm following the docs, here https://developers.cloudflare.com/pages/functions/api-reference/ it says that onRequestPost does receive the request and env objects so my code should be working, right?
Cyb3r-Jak3
Cyb3r-Jak32mo ago
Are you trying to use python with functions? I don’t think that’s supported yet
i.wont.tell
i.wont.tell2mo ago
no, it's javascript, I ended up using it because I already had the logic there and only the env var retrieving was missing and just learned that I can only access env vars from functions and not from say a Vue component. I have figured out what I was doing wrong. onRequestPost receives a context object, I have to access request and env from there with context.request and so on.