Turnstile with Workers
Inject Turnstile implicitly into HTML elements using the HTMLRewriter runtime API.
export default {  async fetch(request, env) {    const SITE_KEY = env.SITE_KEY; // The Turnstile Sitekey of your widget (pass as env or secret)    const TURNSTILE_ATTR_NAME = 'your_id_to_replace'; // The id of the element to put a Turnstile widget in    let res = await fetch(request)
    // Instantiate the API to run on specific elements, for example, `head`, `div`    let newRes = new HTMLRewriter()
      // `.on` attaches the element handler and this allows you to match on element/attributes or to use the specific methods per the API      .on('head', {        element(element) {          // In this case, you are using `append` to add a new script to the `head` element          element.append(`<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>`, { html: true });        },      })      .on('div', {        element(element) {          // Add a turnstile widget element into if an element with the id of TURNSTILE_ATTR_NAME is found          if (element.getAttribute('id') === TURNSTILE_ATTR_NAME) {            element.append(`<div class="cf-turnstile" data-sitekey="${SITE_KEY}"></div>`, { html: true });          }        },      })      .transform(res);    return newRes  }}export default {  async fetch(request, env): Promise<Response> {    const SITE_KEY = env.SITE_KEY; // The Turnstile Sitekey of your widget (pass as env or secret)    const TURNSTILE_ATTR_NAME = 'your_id_to_replace'; // The id of the element to put a Turnstile widget in
    let res = await fetch(request)
    // Instantiate the API to run on specific elements, for example, `head`, `div`    let newRes = new HTMLRewriter()
      // `.on` attaches the element handler and this allows you to match on element/attributes or to use the specific methods per the API      .on('head', {        element(element) {
          // In this case, you are using `append` to add a new script to the `head` element          element.append(`<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>`, { html: true });        },      })      .on('div', {        element(element) {          // Add a turnstile widget element into if an element with the id of TURNSTILE_ATTR_NAME is found          if (element.getAttribute('id') === TURNSTILE_ATTR_NAME) {            element.append(`<div class="cf-turnstile" data-sitekey="${SITE_KEY}" data-theme="light"></div>`, { html: true });          }        },      })      .transform(res);    return newRes  }} satisfies ExportedHandler<Env>;from pyodide.ffi import create_proxyfrom js import HTMLRewriter, fetch
async def on_fetch(request, env):    site_key = env.SITE_KEY  attr_name = env.TURNSTILE_ATTR_NAME    res = await fetch(request)
    class Append:        def element(self, element):            s = '<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>'            element.append(s, {"html": True})
    class AppendOnID:        def __init__(self, name):            self.name = name        def element(self, element):            # You are using the `getAttribute` method here to retrieve the `id` or `class` of an element            if element.getAttribute("id") == self.name:                div = f'<div class="cf-turnstile" data-sitekey="{site_key}" data-theme="light"></div>'                element.append(div, { "html": True })
    # Instantiate the API to run on specific elements, for example, `head`, `div`    head = create_proxy(Append())    div = create_proxy(AppendOnID(attr_name))    new_res = HTMLRewriter.new().on("head", head).on("div", div).transform(res)
    return new_resasync function handlePost(request, env) {    const body = await request.formData();    // Turnstile injects a token in `cf-turnstile-response`.    const token = body.get('cf-turnstile-response');    const ip = request.headers.get('CF-Connecting-IP');
    // Validate the token by calling the `/siteverify` API.    let formData = new FormData();
    // `secret_key` here is the Turnstile Secret key, which should be set using Wrangler secrets    formData.append('secret', env.SECRET_KEY);    formData.append('response', token);    formData.append('remoteip', ip); //This is optional.
    const url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';    const result = await fetch(url, {        body: formData,        method: 'POST',    });
    const outcome = await result.json();
    if (!outcome.success) {        return new Response('The provided Turnstile token was not valid!', { status: 401 });    }    // The Turnstile token was successfully validated. Proceed with your application logic.    // Validate login, redirect user, etc.
  // Clone the original request with a new body    const newRequest = new Request(request, {        body: request.body, // Reuse the body        method: request.method,        headers: request.headers    });
    return await fetch(newRequest);}
export default {  async fetch(request, env) {    const SITE_KEY = env.SITE_KEY; // The Turnstile Sitekey of your widget (pass as env or secret)    const TURNSTILE_ATTR_NAME = 'your_id_to_replace'; // The id of the element to put a Turnstile widget in
    let res = await fetch(request)
    if (request.method === 'POST') {      return handlePost(request, env)    }
    // Instantiate the API to run on specific elements, for example, `head`, `div`    let newRes = new HTMLRewriter()      // `.on` attaches the element handler and this allows you to match on element/attributes or to use the specific methods per the API      .on('head', {        element(element) {
          // In this case, you are using `append` to add a new script to the `head` element          element.append(`<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>`, { html: true });        },      })      .on('div', {        element(element) {          // You are using the `getAttribute` method here to retrieve the `id` or `class` of an element          if (element.getAttribute('id') === <NAME_OF_ATTRIBUTE>) {            element.append(`<div class="cf-turnstile" data-sitekey="${SITE_KEY}" data-theme="light"></div>`, { html: true });          }        },      })      .transform(res);    return newRes  }}