/* * ============================================================ * CONFIGURAÇÕES PRINCIPAIS * ============================================================ */ const CHECKOUT_PAGE = "https://myangelcenter.com/checkout/"; const SALES_PAGE_NORMAL = "https://angelsaintapp.lovable.app/"; /* * COOKIE * * Criado ao acessar: * * https://healthnewsfr.com/salespage?_dst=true */ const COOKIE_NAME = "r_code"; const COOKIE_VALUE = "rasputin"; /* * 6 horas */ const COOKIE_DURATION_SECONDS = 6 * 60 * 60; /* * ============================================================ * UPSELLS * ============================================================ */ const UPSELLS = { "/up1": { normal: "https://myangelcenter.com/up1xmllllllllll", special: "https://myangelcenter.com/up1xmlllllllll-copia", }, "/up2": { normal: "https://myangelcenter.com/up2xmllllllllll", special: "https://myangelcenter.com/up2xmlllllllll-copia", }, "/up3": { normal: "https://myangelcenter.com/up3xmllllllllll", special: "https://myangelcenter.com/up3xmlllllllll-copia", }, }; /* * ============================================================ * FUNÇÕES AUXILIARES * ============================================================ */ /* * Faz: * * /up1 * /up1/ * * serem tratados da mesma forma. */ function normalizePath(pathname) { if ( pathname.length > 1 && pathname.endsWith("/") ) { return pathname.slice(0, -1); } return pathname; } /* * ============================================================ * LER COOKIE * ============================================================ */ function getCookie( request, cookieName ) { const cookieHeader = request.headers.get("cookie") || ""; const cookies = cookieHeader.split(";"); for (const cookie of cookies) { const separatorIndex = cookie.indexOf("="); if (separatorIndex === -1) { continue; } const name = cookie .slice(0, separatorIndex) .trim(); const value = cookie .slice(separatorIndex + 1) .trim(); if (name === cookieName) { try { return decodeURIComponent(value); } catch { return value; } } } return null; } /* * ============================================================ * CRIAR COOKIE * ============================================================ * * r_code=rasputin * * válido por 6 horas em healthnewsfr.com */ function createAuthorizedCookie() { return [ `${COOKIE_NAME}=${encodeURIComponent( COOKIE_VALUE )}`, "Path=/", `Max-Age=${COOKIE_DURATION_SECONDS}`, "HttpOnly", "Secure", "SameSite=Lax", ].join("; "); } /* * ============================================================ * APAGAR COOKIE * ============================================================ */ function createExpiredCookie() { return [ `${COOKIE_NAME}=`, "Path=/", "Max-Age=0", "HttpOnly", "Secure", "SameSite=Lax", ].join("; "); } /* * ============================================================ * CRIAR URL EXTERNA * ============================================================ * * Copia TODOS os parâmetros recebidos. * * Se removeDst = true: * não envia _dst para a página externa. */ function createTargetUrl( incomingUrl, targetAddress, removeDst = false ) { const targetUrl = new URL(targetAddress); for ( const [name, value] of incomingUrl.searchParams.entries() ) { /* * _dst só serve para nossa lógica interna. */ if ( removeDst && name === "_dst" ) { continue; } targetUrl.searchParams.append( name, value ); } return targetUrl; } /* * ============================================================ * PROXY * ============================================================ * * Busca a página externa e devolve seu conteúdo * mantendo healthnewsfr.com na barra. * * Também pode adicionar cabeçalhos extras, * como Set-Cookie. */ async function proxyPage( request, targetAddress, options = {} ) { const { removeDst = false, extraHeaders = {}, } = options; const incomingUrl = new URL(request.url); const targetUrl = createTargetUrl( incomingUrl, targetAddress, removeDst ); /* * Busca a página externa. */ const originResponse = await fetch( targetUrl.toString(), { method: "GET", redirect: "follow", headers: { Accept: request.headers.get("accept") || "text/html,application/xhtml+xml", "Accept-Language": request.headers.get( "accept-language" ) || "en-US,en;q=0.9", "User-Agent": request.headers.get( "user-agent" ) || "Mozilla/5.0", }, } ); /* * Trata erro da origem. */ if (!originResponse.ok) { throw new Error( `Página externa respondeu com status ${originResponse.status}` ); } /* * Obtém o HTML. */ let html = await originResponse.text(); /* * ========================================================== * BASE URL * ========================================================== * * Isso ajuda CSS, JS, imagens, fontes, * formulários e links relativos a usarem * o domínio original. */ if (/]/i.test(html)) { if (/]/i.test(html)) { html = html.replace( /]*>/i, `` ); } else { html = html.replace( /]*)>/i, `` ); } } /* * ========================================================== * RESPOSTA * ========================================================== */ return new Response( html, { status: 200, headers: { "Content-Type": "text/html; charset=UTF-8", /* * Não deixa uma versão ficar armazenada * e ser reutilizada para outra pessoa. */ "Cache-Control": "private, no-store, no-cache, must-revalidate", Pragma: "no-cache", Expires: "0", "X-Robots-Tag": "noindex, nofollow", /* * Cabeçalhos adicionais. * * Aqui entra Set-Cookie quando necessário. */ ...extraHeaders, }, } ); } /* * ============================================================ * FUNÇÃO PRINCIPAL * ============================================================ */ export default async function handler( request ) { try { const url = new URL(request.url); const pathname = normalizePath( url.pathname ); /* * ======================================================== * SALES PAGE * ======================================================== */ if ( pathname === "/salespage" ) { /* * Verifica: * * ?_dst=true */ const hasDst = url.searchParams.get( "_dst" ) === "true"; /* * ====================================================== * SALES PAGE COM _dst=true * ====================================================== * * Exemplo: * * healthnewsfr.com/salespage?_dst=true * * * Faz: * * 1. cria r_code=rasputin; * * 2. exibe: * myangelcenter.com/checkout/ * * 3. mantém: * healthnewsfr.com/salespage?_dst=true * * 4. preserva TODOS os outros parâmetros; * * 5. não envia _dst para myangelcenter. */ if (hasDst) { return await proxyPage( request, CHECKOUT_PAGE, { removeDst: true, extraHeaders: { "Set-Cookie": createAuthorizedCookie(), }, } ); } /* * ====================================================== * SALES PAGE SEM _dst=true * ====================================================== * * Exemplo: * * healthnewsfr.com/salespage * * * Faz: * * 1. apaga eventual r_code antigo; * * 2. exibe: * angelsaintapp.lovable.app * * 3. mantém: * healthnewsfr.com/salespage */ return await proxyPage( request, SALES_PAGE_NORMAL, { removeDst: true, extraHeaders: { "Set-Cookie": createExpiredCookie(), }, } ); } /* * ======================================================== * VERIFICA COOKIE * ======================================================== */ const rCode = getCookie( request, COOKIE_NAME ); const isAuthorized = rCode === COOKIE_VALUE; /* * ======================================================== * IDENTIFICA UPSELL * ======================================================== */ const upsell = UPSELLS[pathname]; /* * Rota que não pertence ao funil. */ if (!upsell) { return new Response( "Rota não encontrada.", { status: 404, headers: { "Content-Type": "text/plain; charset=UTF-8", "Cache-Control": "no-store", }, } ); } /* * ======================================================== * ESCOLHE A VERSÃO DO UPSELL * ======================================================== * * r_code=rasputin * → especial * * sem cookie * → normal */ const targetPage = isAuthorized ? upsell.special : upsell.normal; /* * ======================================================== * EXIBE O UPSELL * ======================================================== * * Mantém: * * healthnewsfr.com/up1 * healthnewsfr.com/up2 * healthnewsfr.com/up3 * * na barra do navegador. * * Todos os parâmetros recebidos no upsell * também são enviados para a página externa. */ return await proxyPage( request, targetPage ); } catch (error) { /* * ======================================================== * ERRO * ======================================================== */ console.error( "Erro no funnel-router:", error ); return new Response( "Não foi possível carregar esta página.", { status: 502, headers: { "Content-Type": "text/plain; charset=UTF-8", "Cache-Control": "no-store", }, } ); } } /* * ============================================================ * ROTAS CONTROLADAS * ============================================================ */ export const config = { path: [ "/salespage", "/salespage/", "/up1", "/up1/", "/up2", "/up2/", "/up3", "/up3/", ], };