Skip to content

Instantly share code, notes, and snippets.

@maximum-pixels
Last active May 31, 2024 13:29
Show Gist options
  • Save maximum-pixels/1836bad626369b843d84d2e705f7b911 to your computer and use it in GitHub Desktop.
Save maximum-pixels/1836bad626369b843d84d2e705f7b911 to your computer and use it in GitHub Desktop.
This is the index.js code for a CloudFlare worker to proxy RudderStack's JS SDK and Requests to make them Ad-Blocker Proof
addEventListener('fetch', event => {
if(event.request.method === 'OPTIONS'){
event.respondWith(handleOptions(event.request))
}else{
event.respondWith(handleRequest(event.request))
}
})
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,HEAD,POST,OPTIONS",
"Access-Control-Max-Age": "86400",
}
function handleOptions(request){
let headers = request.headers;
if (
headers.get("Origin") !== null &&
headers.get("Access-Control-Request-Method") !== null &&
headers.get("Access-Control-Request-Headers") !== null
){
let respHeaders = {
...corsHeaders,
"Access-Control-Allow-Headers": request.headers.get("Access-Control-Request-Headers"),
}
return new Response(null, {headers: respHeaders});
}else{
return new Response(null, {headers: {Allow: "GET, HEAD, POST, OPTIONS"}})
}
}
async function handleRequest(request) {
const { pathname, origin } = new URL(request.url);
const DATA_PLANE_URL = 'https://obsessivealnoa.dataplane.rudderstack.com';
const RUDDER_METHODS = ['page', 'identify', 'group', 'track', 'alias'];
const RUDDER_SDK_URL = 'https://cdn.rudderlabs.com/v1/rudder-analytics.min.js';
const RUDDER_SOURCE_CONFIG_URL = 'https://api.rudderlabs.com/sourceConfig';
if ( pathname === '/sourceConfig/'){
request = new Request(RUDDER_SOURCE_CONFIG_URL, request)
request.headers.set("Origin", origin)
let response = await fetch(request)
response = new Response(response.body, response);
response.headers.set("Access-Control-Allow-Origin", '*');
response.headers.append("Vary", "Origin");
return response;
} else if ( pathname === '/dataPlane' ){
const init = {headers: {'Content-Type': 'application/javascript'}};
const response = await fetch(RUDDER_SDK_URL, {headers: request.headers});
const responseText = await response.text();
return new Response(responseText, init);
}else{
const fragments = pathname.split('/');
/**
* this is to catch the actual rudder calls which will be in format
* /v1/page
* /v1/track
* etc.
* Splitting on '/' will give us ['','v1','page'] for instance
* Rudder request will also be POST requests
* Time to filter out bad requests
*/
if (request.method !== 'POST' || !RUDDER_METHODS.includes(fragments[2])){
return new Response(null, {status: 500});
}else{
return fetch(
`${DATA_PLANE_URL}${pathname}`,
{
method: 'POST',
headers: request.headers,
body: request.body
}
)
}
}
}
@suthar26
Copy link

Hi, are there any plans to make it this work with v3 SDK?

@maximum-pixels
Copy link
Author

HI @suthar26 , not currently. But the only thing changed in v3 as far as the URLs go is RUDDER_SDK_URL is going to be either https://cdn.rudderlabs.com/v3/modern/rsa.min.js or https://cdn.rudderlabs.com/v3/legacy/rsa.min.js. This script is also missing proxy handling for potential JS integrations (aka device mode destinations). Those all live under https://cdn.rudderlabs.com/v3/modern/js-integrations/ or https://cdn.rudderlabs.com/v3/legacy/js-integrations. So I'd recommend making the else if ( pathname === '/dataPlane' ){ part a bit more flexible to simply re-route any request where pathname matches /^\/v3\/(modern|legacy)\/.* to fetch https://cdn.rudderlabs.com${pathname}.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment