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

Update code from service worker to module worker format #17905

Merged
merged 1 commit into from
Nov 11, 2024
Merged
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
31 changes: 13 additions & 18 deletions src/content/docs/bots/concepts/bot-score/delay-action.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
pcx_content_type: how-to
title: Delay action

---

Customers with a Bot Management and a [Workers](/workers/) subscription can use the template below to introduce a delay to requests that are likely from bots.
Expand All @@ -14,26 +13,22 @@ const PATH_START = '/exampleURI';
const DELAY_FROM = 5; // in seconds
const DELAY_TO = 10; // in seconds

addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
export default {
async fetch(request, env, ctx): Promise<Response> {
const url = new URL(request.url);
const botScore = request.cf.botManagement.score

async function handleRequest(request) {
let url = new URL(request.url);
let botScore = request.cf.botManagement.score
if (url.pathname.startsWith(PATH_START) && botScore < 30) {
// Random delay between DELAY_FROM and DELAY_TO seconds
const delay = Math.floor(Math.random() * (DELAY_TO - DELAY_FROM + 1)) + DELAY_FROM;
await new Promise(resolve => setTimeout(resolve, delay * 1000));


if (url.pathname.startsWith(PATH_START) && botScore < 30) {
// Random delay between DELAY_FROM and DELAY_TO seconds
const delay = Math.floor(Math.random() * (DELAY_TO - DELAY_FROM + 1)) + DELAY_FROM;
await new Promise(resolve => setTimeout(resolve, delay * 1000));
// Fetch the original request
return fetch(request);
}

// Fetch the original request
return fetch(request);
}
else {
// Fetch the original request without delay
return fetch(request);
}
}
},
} satisfies ExportedHandler<Env>;
```
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,26 @@ sidebar:
order: 5
head: []
description: Configure per-hostname settings such as URL rewriting and custom headers.

---

import { Render } from "~/components"
import { Render } from "~/components";

You may wish to configure per-hostname (customer) settings beyond the scale of Page Rules or Rate Limiting, which have a maximum of 125 rules each.

To do this, you will first need to reach out to your account team to enable access to Custom Metadata. After configuring custom metadata, you can use it in the following ways:

* Read the metadata JSON from [Cloudflare Workers](/workers/) (requires access to Workers) to define per-hostname behavior.
* Use custom metadata values in [rule expressions](/ruleset-engine/rules-language/expressions/) of different Cloudflare security products to define the rule scope.
- Read the metadata JSON from [Cloudflare Workers](/workers/) (requires access to Workers) to define per-hostname behavior.
- Use custom metadata values in [rule expressions](/ruleset-engine/rules-language/expressions/) of different Cloudflare security products to define the rule scope.

<Render file="ssl-for-saas-plan-limitation" />

***
---

## Examples

* Per-customer URL rewriting — for example, customers 1-10,000 fetch assets from server A, 10,001-20,000 from server B, etc.
* Adding custom headers — for example, `X-Customer-ID: $number` based on the metadata you provided
* Setting HTTP Strict Transport Security (“HSTS”) headers on a per-customer basis
- Per-customer URL rewriting — for example, customers 1-10,000 fetch assets from server A, 10,001-20,000 from server B, etc.
- Adding custom headers — for example, `X-Customer-ID: $number` based on the metadata you provided
- Setting HTTP Strict Transport Security (“HSTS”) headers on a per-customer basis
hyperlint-ai[bot] marked this conversation as resolved.
Show resolved Hide resolved
vicb marked this conversation as resolved.
Show resolved Hide resolved

Please speak with your Solutions Engineer to discuss additional logic and requirements.

Expand Down Expand Up @@ -54,32 +53,32 @@ curl --request PATCH \

Changes to metadata will propagate across Cloudflare’s edge within 30 seconds.

***
---

## Accessing custom metadata from a Cloudflare Worker

The metadata object will be accessible on each request using the `request.cf.hostMetadata` property. You can then read the data, and customize any behavior on it using the Worker.

In the example below we will use the user\_id in the Worker that was submitted using the API call above `"custom_metadata":{"customer_id":"12345","redirect_to_https": true,"security_tag":"low"}`, and set a request header to send the `customer_id` to the origin:
In the example below we will use the user_id in the Worker that was submitted using the API call above `"custom_metadata":{"customer_id":"12345","redirect_to_https": true,"security_tag":"low"}`, and set a request header to send the `customer_id` to the origin:

```js
addEventListener('fetch', event => {
event.respondWith(fetchAndAddHeader(event.request));
});
/**
* Fetch and add a X-Customer-Id header to the origin based on hostname
* @param {Request} request
*/ async function fetchAndAddHeader(request) {
let customer_id = request.cf.hostMetadata.customer_id;
let newHeaders = new Headers(request.headers);
newHeaders.append('X-Customer-Id', customer_id);
let init = {
headers: newHeaders,
method: request.method,
};
let response = await fetch(request.url, init);
return response;
}
export default {
/**
* Fetch and add a X-Customer-Id header to the origin based on hostname
* @param {Request} request
*/
async fetch(request, env, ctx): Promise<Response> {
const customer_id = request.cf.hostMetadata.customer_id;
const newHeaders = new Headers(request.headers);
newHeaders.append('X-Customer-Id', customer_id);

const init = {
headers: newHeaders,
method: request.method,
};
return fetch(request.url, init);
},
} satisfies ExportedHandler<Env>;
```

## Accessing custom metadata in a rule expression
Expand All @@ -92,35 +91,35 @@ The following rule expression defines that there will be a rule match if the `se
lookup_json_string(cf.hostname.metadata, "security_tag") eq "low"
```

***
---

## Best practices

* Ensure that the JSON schema used is fixed: changes to the schema without corresponding Cloudflare Workers changes will potentially break websites, or fall back to any defined “default” behavior
* Prefer a flat JSON structure
* Use string keys in snake\_case (rather than camelCase or PascalCase)
* Use proper booleans (true/false rather than `true` or `1` or `0`)
* Use numbers to represent integers instead of strings (`1` or `2` instead of `"1"` or `"2"`)
* Define fallback behaviour in the non-presence of metadata
* Define fallback behaviour if a key or value in the metadata are unknown
- Ensure that the JSON schema used is fixed: changes to the schema without corresponding Cloudflare Workers changes will potentially break websites, or fall back to any defined “default” behavior
hyperlint-ai[bot] marked this conversation as resolved.
Show resolved Hide resolved
vicb marked this conversation as resolved.
Show resolved Hide resolved
- Prefer a flat JSON structure
- Use string keys in snake_case (rather than camelCase or PascalCase)
- Use proper booleans (true/false rather than `true` or `1` or `0`)
- Use numbers to represent integers instead of strings (`1` or `2` instead of `"1"` or `"2"`)
- Define fallback behaviour in the non-presence of metadata
- Define fallback behaviour if a key or value in the metadata are unknown

General guidance is to follow [Google’s JSON Style guide](https://google.github.io/styleguide/jsoncstyleguide.xml) where appropriate.

***
---

## Limitations

There are some limitations to the metadata that can be provided to Cloudflare:

* It must be valid JSON.
* Any origin resolution — for example, directing requests for a given hostname to a specific backend — must be provided as a hostname that exists within Cloudflare’s DNS (even for non-authoritative setups). Providing an IP address directly will cause requests to error.
* The total payload must not exceed 4 KB.
* It requires a Cloudflare Worker that knows how to process the schema and trigger logic based on the contents.
* Custom metadata cannot be set on custom hostnames that contain wildcards.
- It must be valid JSON.
- Any origin resolution — for example, directing requests for a given hostname to a specific backend — must be provided as a hostname that exists within Cloudflare’s DNS (even for non-authoritative setups). Providing an IP address directly will cause requests to error.
hyperlint-ai[bot] marked this conversation as resolved.
Show resolved Hide resolved
vicb marked this conversation as resolved.
Show resolved Hide resolved
- The total payload must not exceed 4 KB.
- It requires a Cloudflare Worker that knows how to process the schema and trigger logic based on the contents.
- Custom metadata cannot be set on custom hostnames that contain wildcards.

:::note

Be careful when modifying the schema. Adding, removing, or changing keys and possible values may cause the Cloudflare Worker to either ignore the data or return an error for requests that trigger it.
Be careful when modifying the schema. Adding, removing, or changing keys and possible values may cause the Cloudflare Worker to either ignore the data or return an error for requests that trigger it.
:::

### Terraform support
Expand Down
40 changes: 13 additions & 27 deletions src/content/docs/cloudflare-one/tutorials/access-workers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,20 @@ products:
- Access
languages:
- JavaScript

---



This tutorial covers how to use a [Cloudflare Worker](/workers/) to add custom HTTP headers to traffic, and how to send those custom headers to your origin services protected by [Cloudflare Access](/cloudflare-one/policies/access/).

Some applications and networking implementations require specific custom headers to be passed to the origin, which can be difficult to implement for traffic moving through a Zero Trust proxy. You can configure a Worker to send the [user authorization headers](/cloudflare-one/identity/authorization-cookie/) required by Access.

***
---

## Before you begin



* Secure your origin server with Cloudflare Access

- Secure your origin server with Cloudflare Access

## Before you begin


1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. Go to **Workers & Pages**.

2. If this is your first Worker, select **Create Worker**. Otherwise, select **Create application**, then select **Create Worker**.
Expand All @@ -41,30 +34,26 @@ Some applications and networking implementations require specific custom headers

5. Input the following Worker:

```javascript title="Worker with custom HTTP headers"
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request))
})
```js title="Worker with custom HTTP headers"
export default {
async fetch(request, env, ctx): Promise<Response> {
const { headers } = request;
const cfaccessemail = headers.get("cf-access-authenticated-user-email");

async function handleRequest(request) {
const { headers } = request;
const cfaccessemail = headers.get("cf-access-authenticated-user-email");
const requestWithID = new Request(request);
requestWithID.headers.set('company-user-id', cfaccessemail);
const requestWithID = new Request(request);
requestWithID.headers.set('company-user-id', cfaccessemail);

return await fetch(requestWithID);
}

```
return fetch(requestWithID);
},
} satisfies ExportedHandler<Env>;
```

6. Select **Save and deploy**.

Your Worker is now ready to send custom headers to your Access-protected origin services.

## Apply the Worker to your hostname



1. Select the Worker you created, then go to **Triggers**.
2. In **Routes**, select **Add route**.
3. Enter the hostname and zone for your origin, then select **Add route**.
Expand All @@ -79,6 +68,3 @@ The Worker will now insert a custom header into requests that match the defined
"Company-User-Id": "user@example.com",
"Connection": "keep-alive"
```



Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pcx_content_type: how-to
title: Serve private images
sidebar:
order: 23

---

You can serve private images by using signed URL tokens. When an image requires a signed URL, the image cannot be accessed without a token unless it is being requested for a variant set to always allow public access.
Expand All @@ -14,10 +13,8 @@ You can serve private images by using signed URL tokens. When an image requires

:::note


Private images do not currently support custom paths.


:::

The example below uses a Worker that takes in a regular URL without a signed token and returns a tokenized URL that expires after one day. You can, however, set this expiration period to whatever you need, by changing the const `EXPIRATION` value.
Expand Down Expand Up @@ -62,11 +59,13 @@ async function generateSignedUrl(url) {
return new Response(url);
}

addEventListener('fetch', event => {
const url = new URL(event.request.url);
const imageDeliveryURL = new URL(
url.pathname.slice(1).replace('https:/imagedelivery.net', 'https://imagedelivery.net')
);
event.respondWith(generateSignedUrl(imageDeliveryURL));
});
export default {
async fetch(request, env, ctx): Promise<Response> {
const url = new URL(event.request.url);
const imageDeliveryURL = new URL(
url.pathname.slice(1).replace('https:/imagedelivery.net', 'https://imagedelivery.net')
);
return generateSignedUrl(imageDeliveryURL);
},
} satisfies ExportedHandler<Env>;
```
Loading