Created
July 31, 2024 21:30
-
-
Save estevecastells/b048a29784a06bc478d73b3a4dd6a2ed to your computer and use it in GitHub Desktop.
Reverse proxy + Redirect GSC Live Test explorer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
addEventListener('fetch', event => { | |
event.respondWith(handleRequest(event.request)) | |
}) | |
async function handleRequest(request) { | |
const url = new URL(request.url) | |
// Serve robots.txt file | |
if (url.pathname === '/robots.txt') { | |
return new Response('User-agent: *\nDisallow: ', { | |
headers: { 'Content-Type': 'text/plain' } | |
}) | |
} | |
// Handle proxy requests | |
if (url.pathname === '/proxy') { | |
const targetUrlString = url.searchParams.get('url') | |
const device = url.searchParams.get('device') | |
const redirect = url.searchParams.get('redirect') | |
if (!targetUrlString) { | |
return new Response('Missing URL parameter', { status: 400 }) | |
} | |
try { | |
// Resolve relative URLs against the current origin | |
const targetUrl = new URL(targetUrlString, url.origin) | |
// Check if redirect is true | |
if (redirect === 'true') { | |
return Response.redirect(targetUrl.toString(), 302) | |
} | |
// If redirect is false or not set, proceed with proxy logic | |
if (redirect === 'false' || !redirect) { | |
// Clone the original headers | |
const newHeaders = new Headers(request.headers) | |
// Set the appropriate user-agent based on the device parameter | |
switch(device) { | |
case 'desktop': | |
newHeaders.set('User-Agent', 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Googlebot/2.1; +http://www.google.com/bot.html) Chrome/116.0.0.0 Safari/537.36') | |
break; | |
case 'windows': | |
newHeaders.set('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36') | |
break; | |
case 'android': | |
newHeaders.set('User-Agent', 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36') | |
break; | |
case 'iphone': | |
newHeaders.set('User-Agent', 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/116.0.5845.118 Mobile/15E148 Safari/604.1') | |
break; | |
default: | |
// Default to smartphone Googlebot if device is not specified or is set to 'mobile' | |
newHeaders.set('User-Agent', 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)') | |
} | |
const response = await fetch(targetUrl.toString(), { | |
method: request.method, | |
headers: newHeaders, | |
body: request.body | |
}) | |
// Check if the response is HTML | |
const contentType = response.headers.get('content-type') | |
if (contentType && contentType.includes('text/html')) { | |
// If it's HTML, modify the content | |
let content = await response.text() | |
content = rewriteUrls(content, targetUrl.toString()) | |
// Create a new response with the modified content | |
const newResponse = new Response(content, { | |
status: response.status, | |
statusText: response.statusText, | |
headers: response.headers | |
}) | |
// Add CORS headers | |
newResponse.headers.set('Access-Control-Allow-Origin', '*') | |
return newResponse | |
} else { | |
// If it's not HTML, return the original response | |
const newResponse = new Response(response.body, response) | |
// Add CORS headers | |
newResponse.headers.set('Access-Control-Allow-Origin', '*') | |
return newResponse | |
} | |
} | |
} catch (error) { | |
return new Response('Error fetching the requested URL: ' + error.message, { status: 500 }) | |
} | |
} | |
// Return 404 for any other requests | |
return new Response('Not Found', { status: 404 }) | |
} | |
function rewriteUrls(html, baseUrl) { | |
const baseUrlObj = new URL(baseUrl); | |
// Function to resolve a URL against the base URL | |
const resolveUrl = (url) => { | |
if (url.startsWith('//')) { | |
return baseUrlObj.protocol + url; | |
} | |
if (url.startsWith('/')) { | |
return baseUrlObj.origin + url; | |
} | |
if (!url.startsWith('http://') && !url.startsWith('https://') && !url.startsWith('data:')) { | |
return new URL(url, baseUrl).href; | |
} | |
return url; | |
}; | |
// Rewrite URLs in various attributes | |
html = html.replace(/(?:href|src|content|srcset)=['"]([^'"]+)['"]/gi, (match, url) => { | |
const newUrl = resolveUrl(url); | |
return match.replace(url, newUrl); | |
}); | |
// Rewrite URLs in inline styles | |
html = html.replace(/url\(['"]?(.+?)['"]?\)/gi, (match, url) => { | |
const newUrl = resolveUrl(url); | |
return `url("${newUrl}")`; | |
}); | |
return html; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment