Skip to content

Commit

Permalink
Update CloudFlare worker setup docs (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
jhonatan-lopes authored Feb 27, 2024
1 parent 4695e07 commit 29a807f
Showing 1 changed file with 64 additions and 49 deletions.
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

0 comments on commit 29a807f

Please sign in to comment.