Skip to content

Instantly share code, notes, and snippets.

@fabriziosalmi
Created January 14, 2025 11:13
Show Gist options
  • Save fabriziosalmi/8b77bcf2317dbf03751c79904091de34 to your computer and use it in GitHub Desktop.
Save fabriziosalmi/8b77bcf2317dbf03751c79904091de34 to your computer and use it in GitHub Desktop.
Convert Apache rewrites to Cloudflare worker JS 301s
import re
import urllib.parse
def escape_regex(text):
"""Escapes special characters in regex."""
escaped_text = re.escape(text)
# Replace escaped spaces with \s
escaped_text = escaped_text.replace(r'\ ', r'\s')
#remove escaped \
escaped_text = escaped_text.replace(r'\\', r'\')
# Replace escaped + with \+
escaped_text = escaped_text.replace(r'\+', r'\+')
return escaped_text
def generate_worker_script(redirect_file):
"""Generates a Cloudflare Worker script from a redirect file."""
worker_code = """
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const url = new URL(request.url);
const path = url.pathname;
const queryString = url.search.slice(1); // Remove the '?'
const redirects = [
"""
with open(redirect_file, 'r') as f:
lines = f.readlines()
i = 0
while i < len(lines):
line = lines[i].strip()
if line.startswith("RewriteCond"):
cond_line = line
rule_line = lines[i + 1].strip() if i + 1 < len(lines) else None
i+=2
if not rule_line or not rule_line.startswith("RewriteRule"):
continue
match_cond = re.match(r'RewriteCond %{QUERY_STRING} \^(.*)$', cond_line)
match_rule = re.match(r'RewriteRule \^(.*)\$\s+(.*?)\s+\[L,R=301,NC\]$', rule_line)
if match_cond and match_rule:
query_string_condition = match_cond.group(1)
original_path = match_rule.group(1)
redirect_url = match_rule.group(2)
if redirect_url.endswith("?"):
redirect_url = redirect_url[:-1]
escaped_query_string_condition = escape_regex(query_string_condition)
worker_code += f"""
{{
test: () => {{
const cond = new RegExp('^{escaped_query_string_condition}$');
const path_rule = new RegExp('^{original_path}$', 'i');
return cond.test(queryString) && path_rule.test(path);
}},
target: "{redirect_url}"
}},
"""
else:
i += 1
worker_code += """
];
for (const rule of redirects) {
if (rule.test()) {
return Response.redirect(rule.target, 301);
}
}
return fetch(request);
}
"""
return worker_code
if __name__ == "__main__":
redirect_file = "redirect.txt"
worker_script = generate_worker_script(redirect_file)
print(worker_script)
with open("worker.js", "w") as outfile:
outfile.write(worker_script)
print("Worker script generated and saved as worker.js")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment