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 CloudFlare worker setup docs #72

Merged
merged 1 commit into from
Feb 27, 2024
Merged
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
113 changes: 64 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,78 +195,93 @@ To run Wagtail A/B testing on a site that uses Cloudflare, firstly generate a se
WAGTAIL_AB_TESTING_WORKER_TOKEN = '<token here>'
```

Then set up a Cloudflare Worker based on the following JavaScript. Don't forget to set ``WAGTAIL_DOMAIN``:
Then set up a Cloudflare Worker based on the following JavaScript:

```javascript
// Set this to the domain name of your backend server
const WAGTAIL_DOMAIN = "mysite.herokuapp.com";

// Set to false if Cloudflare shouldn't automatically redirect requests to use HTTPS
const ENFORCE_HTTPS = true;

async function handleRequest(request) {
const url = new URL(request.url)
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url)

// Set this to the domain name of your backend server
const WAGTAIL_DOMAIN = env.WAGTAIL_DOMAIN;

if (url.protocol == 'http:' && ENFORCE_HTTPS) {
url.protocol = 'https:';
return Response.redirect(url, 301);
}
// This should match the token on your Django settings
const WAGTAIL_AB_TESTING_WORKER_TOKEN = env.WAGTAIL_AB_TESTING_WORKER_TOKEN;

if (url.protocol == 'http:' && ENFORCE_HTTPS) {
url.protocol = 'https:';
return Response.redirect(url, 301);
}

if (request.method === 'GET') {
const newRequest = new Request(request, {
if (request.method === 'GET') {
const newRequest = new Request(request, {
headers: {
...request.headers,
'Authorization': 'Token ' + WAGTAIL_AB_TESTING_WORKER_TOKEN,
'X-Requested-With': 'WagtailAbTestingWorker'
}
});

url.hostname = WAGTAIL_DOMAIN;
response = await fetch(url.toString(), newRequest);

// If there is a test running at the URL, the worker would return
// a JSON response containing both versions of the page. Also, it
// returns the test ID in the X-WagtailAbTesting-Test header.
const testId = response.headers.get('X-WagtailAbTesting-Test');
if (testId) {
// Participants of a test would have a cookie that tells us which
// version of the page being tested on that they should see
// If they don't have this cookie, serve a random version
const versionCookieName = `abtesting-${testId}-version`;
const cookie = request.headers.get('cookie');
let version;
if (cookie && cookie.includes(`${versionCookieName}=control`)) {
version = 'control';
} else if (cookie && cookie.includes(`${versionCookieName}=variant`)) {
version = 'variant';
} else if (Math.random() < 0.5) {
version = 'control';
} else {
version = 'variant';
}
});

return response.json().then(json => {
return new Response(json[version], {
url.hostname = WAGTAIL_DOMAIN;
response = await fetch(url.toString(), newRequest);

// If there is a test running at the URL, the worker would return
// a JSON response containing both versions of the page. Also, it
// returns the test ID in the X-WagtailAbTesting-Test header.
const testId = response.headers.get('X-WagtailAbTesting-Test');
if (testId) {
// Participants of a test would have a cookie that tells us which
// version of the page being tested on that they should see
// If they don't have this cookie, serve a random version
const versionCookieName = `abtesting-${testId}-version`;
const cookie = request.headers.get('cookie');
let version;
if (cookie && cookie.includes(`${versionCookieName}=control`)) {
version = 'control';
} else if (cookie && cookie.includes(`${versionCookieName}=variant`)) {
version = 'variant';
} else if (Math.random() < 0.5) {
version = 'control';
} else {
version = 'variant';
}

return response.json().then(json => {
return new Response(json[version], {
headers: {
...response.headers,
'Content-Type': 'text/html'
}
});
});
});
}

return response;
} else {
return await fetch(url.toString(), request);
}
},
};
```

return response;
} else {
return await fetch(url.toString(), request);
}
}
You can use CloudFlare's `wrangler` to setup your worker. On an empty directory, install `wrangler`:

addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
```sh
npm install wrangler --save-dev
```

Add a variable to the worker called ``WAGTAIL_AB_TESTING_WORKER_TOKEN``, giving it the same token value that you generated earlier.
and then initialise a new Wrangler project:

```sh
npx wrangler init
```

Follow the CLI prompt until it generates a project for you, then add the JS script above to `src/index.js`.

Add a ``WAGTAIL_AB_TESTING_WORKER_TOKEN`` variable to the worker, giving it the same token value that you generated earlier. Make sure to also setup a ``WAGTAIL_DOMAIN`` variable with the value of the domain where your website is hosted (e.g. `"www.mysite.com"`).

Finally, add a route into Cloudflare so that it routes all traffic through this worker.

Expand Down
Loading